Buyback and burn
There are no payments#
This design choice has a concrete benefit: a burn needs no holder snapshot, no Merkle tree and no claim flow, so there is nothing for anybody to be excluded from and no distribution list to trust. It also has a real cost, which is that the benefit is diffuse and is not visible in any wallet. Both are stated plainly rather than one of them being buried.
Holders benefit through a smaller supply, never through a payment. There is no instruction that credits a wallet.
Two sources, one burn#
Tokens get burned from two entirely different places, and conflating them is the usual source of confusion.
| Source | What it is | Needs a swap? | Conditional on profit? |
|---|---|---|---|
| The base fee leg | Whatever sits in base_escrow in the launched token itself | No, it is already the token | No. It burns whenever there is any. |
| The profit buyback | Quote staged in holder_rewards by sweep_profit | Yes, through the AMM | Yes. Only profit above the high water mark reaches it. |
base_escrow ──────────────────────────────┐
├──▶ burn_checked ──▶ supply falls
holder_rewards ──▶ swap via the AMM ──▶ base ──┘Both land in base_escrow before a single burn call, which is why a buyback on a launch that has never made a profit still burns the fee leg.
What buyback_and_burn does#
Permissionless. In order:
- Read
holder_rewards's balance. If it is non-zero, forward the caller's swap instruction to the pinned AMM program, signing asholder_authand nothing else. If it is zero, skip the swap entirely. - Reload both accounts.
spentis the measured fall inholder_rewards;total_baseis the whole balance ofbase_escrowafterwards. - Require
total_base > 0, otherwise revert withNothingToDo. - Burn
total_basefrombase_escrowwithburn_checked, the policy PDA signing as authority. - Add
spenttopaid_to_holdersandtotal_basetotokens_burned.
The CPI target is checked against Config.amm_program before the call, so the signing seeds can never reach an arbitrary program. The amount credited is the measured delta, so a swap that moves nothing counts as nothing.
Why burn_base_leg exists separately#
buyback_and_burn does two unrelated jobs in one instruction. The swap can fail for a dozen ordinary reasons: no pool yet, thin liquidity, a bad route, a venue outage. The burn of the fee leg is our own token and cannot fail. Coupled, a swap that cannot be built takes the burn down with it, and the fee leg just accumulates.
That was observed on a real devnet run, and the fix is a second instruction: burn_base_leg burns whatever sits in base_escrow with no AMM program, no holder_rewards account and no remaining accounts at all. It is deliberately the smallest possible surface, so there is nothing in it that can fail except the burn itself.
| buyback_and_burn | burn_base_leg | |
|---|---|---|
| Permissionless | Yes | Yes |
| Touches the AMM | Yes, when holder_rewards is non-empty | No |
| Spends holder_rewards | Yes | No |
| Burns base_escrow | Yes, the whole balance | Yes, the whole balance |
| Increments paid_to_holders | Yes, by the measured quote spent | No, it is always 0 on this path |
| Increments tokens_burned | Yes | Yes |
| Can be blocked by a broken swap route | Yes | No |
Both emit the same BuybackBurned event; burn_base_leg emits it with spent: 0.
What the counters mean#
| Counter | Unit | Counts |
|---|---|---|
paid_to_holders | quote base units | quote actually spent buying the token back. Money landing in holder_rewards is staged, not paid, and does not move this counter. |
tokens_burned | base token units | every token destroyed, lifetime, from both sources combined. The two are not separable from this counter alone. |
"counters": {
"profitSwept": { "value": "399000000" },
"paidToHolders": { "value": "0" },
"tokensBurned": { "value": "250000000" }
},
"pdaBalances": [
{ "kind": "holder_rewards", "balance": { "value": "249375000" }, "decimals": 8 }
]Read that as: 249,375,000 base units of quote are waiting to buy the token back and have not been spent yet, while 250,000,000 base units of the token have already been burned from the fee leg. The name paid_to_holders is the on-chain field name and is kept verbatim here, but nothing was paid to anybody: it counts quote spent on a buyback.
Not the same as StonkFun's reward mode#
StonkFun offers its own "reward" launch mode, where the mint carries a 100 or 300 bps transfer tax collected by StonkFun's own withhold authority and distributed to holders on their reward cycle. That is a real distribution to wallets, and it is theirs, not ours. Stags cannot take that stream and does not interact with it.
| StonkFun reward mode | Stags | |
|---|---|---|
| Funded by | A transfer tax on every transfer of the mint | Trading profit from the bankroll, above the high water mark |
| Collected by | StonkFun's withhold authority | The policy PDA |
| Reaches holders as | A distribution to wallets | A smaller supply. Nothing reaches a wallet. |
| Can both run on one launch? | Yes | Yes |
A launch can carry both, which is exactly why this documentation never calls them the same thing. "Holder rewards" would otherwise mean two different mechanisms on the same token.