|
2 | 2 |
|
3 | 3 | ## Recalculating Distribution Shares
|
4 | 4 |
|
5 |
| -The distributor app will re-calculate the distribution shares for each Send token holder by analyzing the Ethereum mainnet blocks for Send token transfers. The distributor app will then update the distribution shares for each Send token holder in the database. |
| 5 | +The distributor app calculates distribution shares through a three-step process, applying various adjustments and caps to ensure fair token distribution. |
| 6 | + |
| 7 | +### Distribution Calculation Process |
| 8 | + |
| 9 | +#### 1. Initial Hodler Rewards |
| 10 | + |
| 11 | +The first step calculates initial rewards using the full distribution amount. This establishes baseline amounts that will be used to cap fixed rewards. For each hodler: |
| 12 | + |
| 13 | +- Balances are checked against minimum hodler requirements |
| 14 | +- Time-based adjustments are applied based on qualification period |
| 15 | +- Send ceiling/slash adjustments are applied to balances |
| 16 | +- Initial weighted distribution is calculated |
| 17 | + |
| 18 | +#### 2. Fixed Pool Rewards |
| 19 | + |
| 20 | +Fixed rewards are calculated based on user verifications and achievements: |
| 21 | + |
| 22 | +- Each verification type can have fixed values and multipliers |
| 23 | +- Multipliers increase based on repeated verifications |
| 24 | +- Fixed rewards are capped by the initial hodler amounts |
| 25 | +- Send ceiling/slash adjustments are applied |
| 26 | +- Total fixed pool allocation is tracked |
| 27 | + |
| 28 | +#### 3. Final Hodler Pool Rewards |
| 29 | + |
| 30 | +The remaining amount after fixed pool allocation is distributed: |
| 31 | + |
| 32 | +- Uses (total distribution amount - fixed pool allocated amount) |
| 33 | +- Applies time-based adjustments to the remaining pool |
| 34 | +- Applies send ceiling/slash adjustments |
| 35 | +- Distributes based on weighted hodler balances |
| 36 | + |
| 37 | +### Key Mechanisms |
| 38 | + |
| 39 | +#### Time-based Adjustments |
| 40 | + |
| 41 | +Distribution amounts are progressively released throughout the qualification period: |
| 42 | + |
| 43 | +- Calculated based on hours in qualification month |
| 44 | +- Adjusted for current hour in qualification period |
| 45 | +- Prevents early participants from receiving full allocation immediately |
| 46 | +- Formula: `hourlyAmount * currentHour / totalHours` |
| 47 | + |
| 48 | +#### Send Ceiling and Slash Mechanism |
| 49 | + |
| 50 | +Rewards are adjusted based on send activity: |
| 51 | + |
| 52 | +- Previous distribution rewards affect base calculation |
| 53 | +- Send ceiling verification weight impacts reward allocation |
| 54 | +- Scaling divisor applied to previous rewards |
| 55 | +- Slash percentage calculated as: `(cappedSendScore * PERC_DENOM) / scaledPreviousReward` |
| 56 | + |
| 57 | +#### Verification Multipliers |
| 58 | + |
| 59 | +Fixed rewards can be amplified through multipliers: |
| 60 | + |
| 61 | +- Each verification type can have min/max multiplier values |
| 62 | +- Multiplier steps increase based on verification count |
| 63 | +- Multiple verification types can compound multipliers |
| 64 | + |
| 65 | +### API Usage |
6 | 66 |
|
7 | 67 | To manually request a distribution be recalculated, send a `POST` request to the `/distributor` endpoint:
|
8 | 68 |
|
9 |
| -```js |
10 | 69 | process.env.DISTRIBUTOR_URL="https://distributor.prod.send.it"
|
11 | 70 | process.env.DISTRIBUTION_ID="11"
|
12 | 71 | process.env.SUPABASE_SERVICE_ROLE =
|
13 |
| - '<same service role configured on distributor>' |
| 72 | +'<same service role configured on distributor>' |
14 | 73 |
|
15 | 74 | const response = await fetch(`${process.env.DISTRIBUTOR_URL}/distributor/v2`, {
|
16 |
| - method: 'POST', |
17 |
| - body: JSON.stringify({ id: process.env.DISTRIBUTION_ID }), |
18 |
| - headers: { |
19 |
| - 'Content-Type': 'application/json', |
20 |
| - Authorization: process.env.SUPABASE_SERVICE_ROLE, |
21 |
| - }, |
| 75 | +method: 'POST', |
| 76 | +body: JSON.stringify({ id: process.env.DISTRIBUTION_ID }), |
| 77 | +headers: { |
| 78 | +'Content-Type': 'application/json', |
| 79 | +Authorization: process.env.SUPABASE_SERVICE_ROLE, |
| 80 | +}, |
22 | 81 | })
|
23 | 82 |
|
24 | 83 | // get the response body
|
25 | 84 | const body = await response.json()
|
26 | 85 | console.log(body)
|
27 |
| -``` |
28 | 86 |
|
29 | 87 | ## Generate Merkle Tree Root
|
30 | 88 |
|
31 |
| -```shell |
32 | 89 | yarn workspace @my/contracts run gen-dist-merkle-tree $DISTRIBUTION_ID
|
33 |
| -``` |
34 | 90 |
|
35 |
| -The output of the command is the merkle root hash. This hash is used to create a distribution tranche. You can find the full details (including the distribution total) in the `./var` directory. |
| 91 | +The output of the command is the merkle root hash. This hash is used to create a distribution tranche. You can find the full details (including the distribution total) in the ./var directory. |
36 | 92 |
|
37 | 93 | ## Creating a Distribution
|
38 | 94 |
|
39 |
| -[Send Token `0x3f14920c99BEB920Afa163031c4e47a3e03B3e4A`](https://etherscan.io/address/0x3f14920c99beb920afa163031c4e47a3e03b3e4a) |
40 |
| -[SendMerkleDrop (distribution contract) `0xB9310daE45E71c7a160A13D64204623071a8E347`]( |
41 |
| -https://etherscan.io/address/0xB9310daE45E71c7a160A13D64204623071a8E347) |
| 95 | +[Send Token `0xEab49138BA2Ea6dd776220fE26b7b8E446638956`](https://basescan.io/address/0xEab49138BA2Ea6dd776220fE26b7b8E446638956) |
| 96 | +[SendMerkleDrop (distribution contract) `0xB9310daE45E71c7a160A13D64204623071a8E347`](https://basescan.io/address/0xB9310daE45E71c7a160A13D64204623071a8E347) |
42 | 97 |
|
43 | 98 | To get started, connect [Send Distribution Safe](https://app.safe.global/home?safe=eth:0x6204Bc0662ccd8a9A762d59fe7906733f251E3b7) via WalletConnect to etherscan
|
44 | 99 |
|
|
0 commit comments