Airdrop mechanics
Snapshots, the pro-rata formula, the five-minute window, gas and anti-sybil measures.
On this page
Distribution is the part most airdrop designs get expensive. Paying every holder on a schedule means gas costs that scale with the holder count, so this protocol never iterates over holders at all.
Accrual without snapshots
Instead of taking a snapshot and looping, the distributor maintains a single global accumulator: the cumulative number of HOOD shares distributed per unit of BANK since deployment. Each address stores the value of that accumulator the last time it settled.
A holder’s entitlement is the difference between the global index and their stored index, multiplied by their balance. Adding shares to the reserve is one storage write regardless of whether there are ten holders or a hundred thousand.
uint256 public accSharesPerToken; // scaled by ACC_PRECISION
mapping(address => uint256) public userIndex; // last settled index
mapping(address => uint256) public unclaimed; // settled but not withdrawn
/// Called by the vault when a batch settles.
function distribute(uint256 shares) external onlyVault {
accSharesPerToken += (shares * ACC_PRECISION) / token.taxableSupply();
emit Distributed(shares, accSharesPerToken, block.timestamp);
}
/// Called on every balance change and before every claim.
function _settle(address account) internal {
uint256 delta = accSharesPerToken - userIndex[account];
if (delta != 0) {
unclaimed[account] += (token.balanceOf(account) * delta) / ACC_PRECISION;
userIndex[account] = accSharesPerToken;
}
}The pro-rata formula
For a distribution of S shares across a taxable supply of T tokens, a holder with balance b receives:
entitlement = S × (b / T)
worked example
S = 8.610000 shares distributed in this batch
T = 900,000,000 BANK of taxable supply
b = 4,500,000 BANK held
share of supply = 4,500,000 / 900,000,000 = 0.5%
entitlement = 8.610000 × 0.005 = 0.043050 sharesTaxable supply excludes balances that are structurally not entitled to accrue — see excluded balances below. Using total supply instead would leak a slice of every distribution into addresses that should not receive one.
The five-minute window
The distributor enforces a 300-second cooldown per address. It is not a distribution schedule: accrual is continuous and the cooldown only limits how often an address may withdraw.
| Property | Behaviour |
|---|---|
| Cooldown | 300 seconds per address |
| Scope | Per address, not global. Your timer is yours. |
| Accrual during cooldown | Continues uninterrupted |
| First claim | Immediately available; no initial cooldown |
| Partial claims | Not supported. A claim withdraws the full unclaimed balance. |
Five minutes is short enough that the mechanism is visible while you watch it, and long enough that claim gas does not dominate small entitlements. The interval is a governance parameter with a floor, so it can be lengthened but not set to zero.
Why claims are pulled, not pushed
A push model requires the protocol to pay gas for every recipient on every distribution, which is the cost structure that kills reflection tokens at scale. Pull claims move that cost to the person who benefits and lets small holders batch their claims into larger, more gas-efficient ones.
Unclaimed accrual
Unclaimed balances never expire and are never swept. There is no forfeiture window, no dust threshold that voids small entitlements, and no administrative function that can zero a holder’s unclaimed balance.
The corollary is that the reserve must hold shares against entitlements indefinitely, including for wallets that have been abandoned. That is a permanent liability on the reserve rather than a windfall for the protocol, and it is the correct trade.
Gas
- Distribution is one storage update plus an event, independent of holder count.
- Claiming settles the caller, zeroes their unclaimed balance and transfers. It is a small, bounded cost with no loops.
- Transfers settle both sides, so a plain BANK transfer costs more than a vanilla ERC-20 transfer. This is the price of correct accounting and it is charged to the person moving tokens.
Because entitlements do not expire, waiting is a valid strategy. A holder who claims once a week pays a fraction of the gas of one who claims every window and ends up with the same shares.
Anti-sybil measures
Distribution is strictly proportional to balance, which is the strongest anti-sybil property available: splitting a balance across a thousand wallets produces exactly the same total entitlement, minus a thousand times the claim gas. There is no per-address bonus to farm.
The remaining vectors are narrower and handled directly:
| Vector | Mitigation |
|---|---|
| Sandwich a distribution | Settlement on transfer freezes accrual to the pre-distribution balance. |
| Flash-loan a balance | Distribution and claim cannot occur in the same block as the balance change that funded them. |
| Dust-claim spam | Per-address cooldown plus rounding in favour of the reserve makes it strictly loss-making. |
| Pool balance farming | Pool and protocol addresses are excluded from taxable supply. |
Excluded balances
The following do not accrue, and are subtracted from taxable supply so that they do not dilute holders who do:
- Registered liquidity pool addresses.
- The reserve vault, router, distributor and buffer.
- The zero address and the token contract itself.
Exclusions are visible on-chain and adding one is a timelocked action, for the obvious reason that an unrestricted exclusion function is a way to redirect distributions. See governance.