A keeper executes; contracts determine recipients.
The keeper discovers B20 swap routes off-chain, but it does not build a Merkle tree or submit an address list. Recipient enumeration, captured balances and payout accounting live in the token and vault contracts.
- 01
buyStocks(minOuts, routerCalldatas)Keeper
Uses available native ETH, retains 10% in platformClaimable and divides the other 90% over the current active basket by weight. Every configured stock must have a complete route or the supplied keeper skips the buy.
- 02
snapshotHolders(count)Keeper
Reads BasketToken.holderAt(i) in pages, excludes infrastructure and reward-excluded accounts, records balance plus address in one word, and accumulates eligibleSupply.
- 03
startCycle()Keeper
Requires a complete snapshot (or creates a one-transaction snapshot for a small registry), freezes each distributable B20 pot and sets nextDistribution to now + 1 hour.
- 04
distributeBatch(count)Keeper
Pushes every frozen B20 asset to the next page of recipients. A failed B20 receiver-policy check records an unpaid entitlement instead of reverting the whole batch.
- 05
flushUnpaidDividend(holder, stock)Anyone
Retries a recorded failed payment to its original holder. It cannot redirect that entitlement or redivide it across other accounts.
Payout formulastock pot × min(snapshot balance, live balance) ÷ eligibleSupply
Timing: nextDistribution is set when startCycle() begins, so a new cycle cannot start for one hour. Stock purchases are keeper-driven and are not independently rate-limited by this interval.