SettleMint
ConceptsIssuing & markets

Token Distribution

In Build

Token Distribution lets an issuer put an allocation into every wallet an eligibility list names, at one fixed cost, without a payout system per campaign.

One shared base, three distinct claim contracts.Every token distribution verifies eligibility against the same fixed Merkle root and shares one seven-day timelocked withdrawal for unclaimed tokens. Below that shared base, three separate contract families diverge. A push distribution has the sender distribute tokens directly, with no claim step, and calling claim always reverts. A time-bound distribution lets each recipient claim their full allocation once, self-service, inside a fixed start and end window. A vesting distribution has the recipient initialize their allocation before a deadline, then claim repeatedly as the strategy pinned at that initialization unlocks more.One shared base, three distinct claim contracts.The same figure as the desktop variant, drawn portrait for phone widths: the shared Merkle-root eligibility check and timelocked withdrawal sit on top, and the push, time-bound, and vesting families stack below them, each linked to the shared base by its own arrow rather than to each other.

Every token distribution shares one Merkle-root eligibility check and one timelocked withdrawal path; how a recipient actually receives tokens diverges by family.

Token Distribution puts an allocation into as many wallets as an eligibility list names, at one fixed publishing cost whether that list holds ten recipients or ten thousand. Every claim checks against a single Merkle root rather than a stored per-address list. A seven-day timelock on owner withdrawals is the same across all three families.

A push distribution moves tokens the moment the sender distributes them, with no claim step for the recipient. A time-bound distribution flips that: each recipient claims their own full allocation once, self-service, only inside a fixed start and end window.

A vesting distribution initializes first, then pays claim after claim as the strategy pinned at that initialization unlocks more.

Why put an allocation in many hands without running a sale

After a token is issued, an issuer often needs to put units into many wallets at once. That covers rewarding the holders who already stayed, seeding a launch's early community, or paying out the allocations a subscription round already promised. Doing that as a sequence of individual transfers means paying gas for every one, keeping a private list of who has been paid, and reconciling that list against what the chain actually moved.

Token distribution replaces that private list with one published Merkle root: a single committed value that proves the whole recipient set and every allocation the moment the contract deploys. Publishing it costs the same whether the list names ten recipients or ten thousand, because the contract never stores the list itself, only the root a caller's proof is checked against. Asset Lifecycle names design, issue, created-paused, service, and retire as an instrument's five stages. Each distribution transfer runs as an ordinary movement through that same instrument's transfer path, the one issuance and every other servicing operation already write to. A private, off-platform list of who was owed what is the kind of separate record Asset Lifecycle's own seam-count argument warns against: a second ledger that can drift from the one the chain actually settled.

Why this runs on the token's own compliance path, not a separate payout system

The transfer a distribution pays out runs through the underlying token's own transfer-compliance modules. Those are the same modules that check every other transfer on that token, detailed under Controls and evidence. A payout system built beside the platform instead would need its own view of who may hold the token, a second copy of the eligibility rules the token's compliance modules already enforce. Any daylight between those two views is where a distribution could pay a wallet the token's own rules would have refused.

Nothing here needs a separate custodian or a second wallet holding funds in transit. A push distribution's sender holds the tokens until the moment they move, and a self-service distribution's contract holds them under the same eligibility check that already governs the token everywhere else. Whichever of the three families the issuer picks, the same eligibility rules decide where the tokens are allowed to land.

What Token Distribution is, and how the three families differ

Token Distribution lets you put an allocation into as many wallets as your eligibility list names, at one fixed publishing cost. Markets colloquially call this an airdrop, and the platform's contract families and API identifiers keep that word. What differs from one family to the next is who pays gas, and when the reward actually reaches a recipient's wallet.

A push distribution puts every transfer on the sender. The issuer calls distribute or batchDistribute, and tokens land in each wallet unasked. Reach for it when a reward must land on a fixed date, and the issuer is willing to cover every transfer's gas.

A time-bound distribution flips who pays and who acts. Each recipient calls claim themselves, once, inside a start and end window the issuer sets. Each recipient authorizes their claim. The recipient or a configured relayer pays its gas. A recipient list of any size costs the issuer the same amount to publish, because eligibility rests on a Merkle proof rather than a stored per-address list. Reach for it when recipients can cover their own gas and should self-serve inside a window you set, rather than wait for the issuer to push every transfer out one by one.

A vesting distribution spreads the reward's economic effect out over time, discouraging an immediate sell-off. A recipient first initializes their allocation, which starts a vesting clock but moves no tokens, then claims repeatedly as more of the allocation unlocks under a pluggable strategy, such as a linear schedule with a cliff. No separate lock-up contract is needed for any single recipient; the distribution itself carries the schedule.

Every family shares one recovery path. The owner can withdraw unclaimed tokens, but only by scheduling a withdrawal and waiting a fixed seven days, a wait the owner cannot shorten. The timelock delays owner withdrawals; the underlying token's transfer rules still apply. This shared design sits beside Primary Offering as the platform's other route for putting a token in a holder's hands, sold rather than distributed under a Merkle root.

Running a distribution day to day

Token distribution's three families divide the day-to-day operating work differently. Push distribution is operator-driven: the operator or a role-holding automation calls distribute or batchDistribute, moving tokens to each recipient without the recipient acting. Time-bound and vesting distributions are self-service, so the operator's job narrows to setting the claim window or the vesting strategy.

Each recipient on a self-service distribution calls claim or batchClaim themselves; the operator never moves a token on their behalf.

A push distribution enforces two limits on chain. It cannot double-pay the same Merkle index, and it cannot exceed a distribution cap when one is set (a cap of zero means uncapped). Both checks run inside distribute itself, so a batch that would violate either one fails before any tokens move. The cap is not fixed for life: the owner can raise or lower it later, and each distribution is checked against the running total at that moment.

A vesting distribution has an operator-visible step that push and time-bound skip: initialization. A recipient's index moves through two states worth tracking separately: not yet initialized, and initialized and vesting. An uninitialized index cannot be claimed at all, no matter how much time has passed, and initialization itself stops working once the distribution's own initialization deadline passes. Track which recipients have initialized separately from which have claimed, since initializing moves no tokens and is not itself a transfer.

A vesting claim's three-state lifecycle.Before initialization, an index is not yet in the vesting clock and a claim reverts. Initializing proves the Merkle allocation, pins the vesting strategy active at that moment, and starts the clock, without moving any tokens. Once initialized, claiming is repeatable: each call moves only the newly unlocked amount. When the cumulative claimed amount reaches the total allocation, the index is fully claimed and nothing more unlocks for it.A vesting claim's three-state lifecycle.The same figure as the desktop variant, drawn portrait for phone widths: awaiting initialization, then initialized and vesting, then fully claimed, stacked as a vertical state sequence.

A vesting index moves through exactly one initialization, any number of claims, then a fully claimed state; push and time-bound skip the initialization step entirely.

Recovering unclaimed tokens is the one lifecycle step every family shares, and it is deliberately two steps. An owner schedules a withdrawal, waits seven days, then executes it. The owner can cancel the schedule at any point before execution, and a rescheduled withdrawal waits the full seven days again. Only one withdrawal can be pending at a time, and no direct, one-call withdrawal exists.

Recovering unclaimed tokens takes a schedule, a fixed wait, then execution.The owner schedules a withdrawal, which starts a clock recipients can read on chain. A fixed seven-day wait follows, and the owner cannot shorten it. Execution then moves the entire remaining balance to the address the owner names. The owner can cancel at any time before execution, and a rescheduled withdrawal waits the full seven days again.Recovering unclaimed tokens takes a schedule, a fixed wait, then execution.The same figure as the desktop variant, drawn portrait for phone widths: scheduled, the seven-day wait, and execution, stacked as a vertical sequence with the cancel note beneath.

Recovery is slow by design. The wait is the recipients' notice, and a cancelled schedule starts over from zero rather than resuming.

Watch a push distribution's cap and per-index claim state the way you would watch any batch payment run, for failed items rather than only completed ones. A time-bound distribution needs its window watched, since a claim outside the start and end time fails outright rather than queuing. The window is set when the distribution deploys and has no setter, so extending one means deploying a new distribution. A vesting distribution needs its initialization deadline tracked separately from its claims, since a recipient who never initializes in time never enters the vesting clock at all.

One base contract, three claim implementations

One abstract base contract underlies all three token distribution families and owns exactly two things: Merkle-root eligibility and the seven-day timelocked withdrawal. The root has no setter; a changed eligibility list needs an entirely new distribution contract, not an update to an existing one.

Everything about claiming diverges below that shared base. Each family plugs in its own claim-tracking behavior, and the tracker type is what actually distinguishes a push claim from a vesting claim at the storage level. A push distribution tracks claims with a bitmap, one bit per index, claimed or not, with no concept of a partial amount. Time-bound and vesting distributions both track a cumulative claimed amount per index instead. Time-bound spends that capacity on one full claim; vesting is the family that actually exercises it, claiming progressively.

BehaviorPushTime-boundVesting
Choose it whenA reward must land on a fixed date and the issuer covers every transfer's gasRecipients can cover their own gas and should self-serve inside a window you setThe reward should unlock gradually rather than land all at once
Who moves tokensThe owner, calling distribute or batchDistributeEach recipient, calling claim or batchClaimEach recipient, calling claim or batchClaim
Claim stepNone; claim and batchClaim always revertOne claim per index, full allocationInitialize once per index, then claim repeatedly
Timing gateNone beyond the owner's own scheduleOnly inside the start and end timeInitialize before the deadline; claim any time after
Claim trackingBitmap: claimed or not, no partial amountAmount-based, used for one full claimAmount-based, used for progressive claims
Unlock paceSet by the owner's own distribution scheduleFull amount unlocks at the single claimSet by the strategy pinned at initialization

The three distribution contract families, compared where they diverge.

A vesting distribution's second divergence is strategy pinning. Calling initializeVesting for an index pins the strategy current at that moment into the index's own record, before any tokens move. Every later claim for that index recomputes against the pinned strategy, never the contract's current one. An owner can repoint future initializations at a new strategy, but no index already initialized ever notices the change. A linear vesting strategy fixes its cliff and total duration as constructor arguments at deployment, both immutable afterward. The allocation vests linearly across the full duration measured from your own initialization, but nothing is claimable until the cliff elapses; once it does, your first claim pays out everything the line has already reached.

Every distribution, in any family, is deployed as its own contract with a predictable address, so its identity is known before deployment. Deploying one needs the TOKEN_FACTORY_MODULE_ROLE at the system level, or the GOVERNANCE_ROLE on that specific token, a role grant the access manager checks before the deployment call runs; it is not open to arbitrary callers.

The integration contract

On chain, the three token distribution families expose different verb sets, and calling the wrong one for a given distribution's family reverts rather than silently doing nothing. Push exposes distribute and batchDistribute, gated to the owner, and its claim and batchClaim always revert with a dedicated error (DALP-3018).

Time-bound and vesting both expose claim and batchClaim to any caller; vesting requires initializeVesting or batchInitializeVesting too, as a mandatory first call per index, before that index's claim will succeed.

A claim, a distribution, and an initialization all check against the same fixed Merkle root, using the exact leaf-encoding format the platform API reference specifies for an index, an account, and a total amount. The proof must match that format precisely, with no fallback path, and building the correct proof for a given entry is entirely your integration's responsibility.

Two caller-side limits shape how you submit. Every claim and initialization verifies the leaf against the caller's own address and pays that address, so integrations submit claims from the recipient's wallet rather than a service account. And batch calls cap at 100 entries in every family; a larger batch reverts before any entry processes.

A batch call's effect on token movement also differs by family. A push batchDistribute sends a separate transfer to each named recipient. A batchClaim on time-bound or vesting collapses several of the caller's own indices into one transfer.

Read a distribution's identity, its token, and its Merkle root from the platform's read model, which includes a discriminator distinguishing the three families. The platform API reference documents three discriminator values: push-airdrop, time-bound-airdrop, and vesting-airdrop. Cross-reference the per-recipient totals for what has actually moved. Vesting-only fields stay empty for push and time-bound entries.

Distinguish a failed eligibility check from an ineligible-right-now state before you surface an error to a caller. An index that has not yet initialized fails vesting's claim with DALP-3025, and a claim outside the active window fails time-bound's claim with DALP-3001 or DALP-3002, depending on which side of the window it falls. Neither of those is the condition a bad Merkle proof produces (DALP-3032), nor the one an already-claimed index produces (DALP-3030). Treat all four as separate cases in your own error handling, rather than collapsing them into one generic claim-failed message.

Controls and evidence

A distribution's eligibility decision happens entirely off chain, as a control function. Whoever builds the Merkle tree decides who is on the recipient list and for how much; the contract enforces only that a claim, a distribution, or an initialization matches the committed root.

The audit question for a distribution is who built that tree, from what source list, and under what approval, not what the contract technically allows, because the contract allows anything the tree contains.

The transfer runs through the underlying token's own transfer-compliance modules, the same modules that check every other transfer on that token by evaluating each configured rule before balances change and reverting if any rule fails.

Evidence is on chain and per distribution, across all three families. Creation, every transfer, whether a push distribution or a self-service claim, every vesting initialization, and every withdrawal-schedule step each emits its own event. An auditor reconstructs exactly which index paid whom and when, and through which of the three paths: a push send, a time-bound claim, or a vesting initialization followed later by one or more claims. The chain records execution. Keep the recipient list and its approval evidence separately to explain how the Merkle root was chosen.

A push distribution and a self-service claim carry different accountability even though both move the same tokens. A push distribution is a step the operator, or an authorized automation, took on the recipient's behalf. A claim is a step the recipient took themselves. The event trail preserves that distinction rather than flattening both into one generic transfer record.

Frequently asked questions

What happens when a push distribution misses a recipient?

The owner can still distribute to that index later, because a push distribution has no claim window and no deadline of its own. The recipient cannot self-serve in the meantime: a claim on a push contract always reverts. The index stays payable until the owner distributes it, the distribution cap would be exceeded, or the owner withdraws the remaining balance through the timelocked path.

What happens if I never initialize my vesting allocation?

Nothing unlocks, ever. The vesting clock starts only when initialization runs for your index, and the contract refuses that call once the distribution's initialization deadline passes, so a late attempt reverts. Your allocation then sits in the contract as unclaimed balance, recoverable by the owner through the seven-day timelocked withdrawal. Initialize before the deadline even when you plan to claim much later.

Does my vesting schedule run from deployment or from my own initialization?

From your own initialization. The contract records the timestamp of your initialization, and the strategy measures the cliff and vesting duration from that moment, so two recipients who initialize a week apart also finish a week apart. Waiting to initialize does not bank vested time; it delays the entire schedule, and the initialization deadline caps how long you can wait.

Can I claim while the cliff is still running?

No; the call reverts rather than paying zero. Under a linear strategy, nothing is claimable until the cliff duration has passed since your initialization, and the contract rejects a claim whose computed claimable amount is zero. Once the cliff passes, the first claim pays everything vested since initialization in one transfer, and later claims pay only what unlocked since the previous one.

Can someone else claim my allocation for me?

Not the claim itself; only the gas payment can move. The platform's meta-transaction support lets a relayer submit the transaction and pay the gas, but the recipient still authorizes it and still receives the tokens. When recipients cannot transact at all, even through a relayer, a push distribution is the family built for that.

Can the owner withdraw tokens while claims are still open?

Yes. Scheduling a withdrawal is not blocked by an open claim window or a running vesting schedule; the seven-day wait is the notice recipients get, and the scheduled time is readable on chain. Execution then empties the contract, after which a claim has nothing left to pay and fails. Fund the contract for the full allocation, and withdraw only once the window or deadline you set has passed.

  • Asset Lifecycle: the whole working life of a regulated tokenized instrument; a distribution transfer runs through the same instrument's transfer path that every other servicing operation already writes to.
  • Primary Offering: the platform's other route for putting a token in a holder's hands, sold to investors rather than distributed under a Merkle root.

On this page