Pre-launch. The protocol is not publicly live yet. This documentation describes the contracts as implemented; deployed addresses are published at launch.

Buy and Burn

How supply gets destroyed, and how to observe it. There is no buyAndBurn() function — burning is a branch the contract selects from pool state, not an action a caller elects.

This changed

Earlier versions of the protocol exposed a deployer-only buyAndBurn(token) entry point. It no longer exists. Anything calling it will revert. Burning now happens inside distributeFees() and processProtocolFees(), chosen automatically.

Where burns come from

SourceTriggerWhat burns
Reinvest fallbackdistributeFees(token) when the pool is token-poorReinvest budget buys tokens, sent to 0x…dEaD
Protocol processingprocessProtocolFees() when the $LP24 pool holds ≥ 24M tokensProtocol balance buys $LP24, burned
Secondary pool feesEvery swap on a token↔$LP24 pool60 bps (0.6%) of the token side, burned in the callback
Dust cleanupAfter any liquidity addLeftover tokens above 1,000,000 wei
Gnosis DEEP pathdistributeFees(token) when pool ≥ 48,000,000 × 10⁹ (48M tokens)All pending tokens, plus the reinvest budget as a buy-and-burn

Which branch runs

The choice is made from the pool's token-side reserve, read from pool state rather than from a balance lookup on the pool manager — the latter would conflate this pool with any other pool holding the same token and could send the branch the wrong way.

V4, processProtocolFees:
  pool_token_side >= 24_000_000 tokens  →  buy and burn
  otherwise                             →  reinvest to deepen

V4, distributeFees reinvest step:
  acquired tokens > dust                →  add liquidity
  otherwise                             →  buy and burn the remainder

Gnosis, distributeFees:
  pool >= POOL_DEPTH_THRESHOLD          →  DEEP: burn everything
  otherwise                             →  THIN: pair into liquidity

The logic is deliberately counter-cyclical. A pool that has been bought heavily is token-poor, so fees go to refilling it; a pool that is deep and healthy gets supply removed instead.

Triggering a burn

You cannot request one directly, but calling distribution when conditions favour the burn branch will produce one:

// Read the current state to predict the branch
const [liquidity, sqrtPriceX96] = await hook.getPoolLiquidity(LP24_TOKEN);

// token-side reserve ≈ L * sqrtP / 2^96
const Q96 = 2n ** 96n;
const tokenSide = (liquidity * sqrtPriceX96) / Q96;

if (tokenSide >= 24_000_000_000_000_000n) {
    // processProtocolFees will buy and burn
    await (await hook.processProtocolFees()).wait();
}
# Read the current state to predict the branch
liquidity, sqrt_price_x96, _tick = hook.functions.getPoolLiquidity(LP24_TOKEN).call()

# token-side reserve ≈ L * sqrtP / 2^96
Q96 = 2 ** 96
token_side = (liquidity * sqrt_price_x96) // Q96

if token_side >= 24_000_000_000_000_000:
    # processProtocolFees will buy and burn
    send(hook.functions.processProtocolFees())

Observing burns

const burns = await hook.queryFilter(
    hook.filters.BuyAndBurn(token), fromBlock, "latest"
);

const totalNativeSpent = burns.reduce(
    (acc, e) => acc + e.args.nativeSpent, 0n
);
burns = hook.events.BuyAndBurn().get_logs(
    from_block=from_block, argument_filters={"token": token}
)

total_native_spent = sum(e["args"]["nativeSpent"] for e in burns)

Secondary-pool burns emit SecondaryTokenBurn(token, amount) on the SecondaryHook instead, one per taxed swap. For a complete picture of destroyed supply, watch both, plus Transfer events to 0x…dEaD which cover dust cleanup.

Supply only falls after graduation

The curve is the only minter, and it is closed once the token graduates. From that point every supply change is a burn, so totalSupply() is monotonically non-increasing. Comparing it against 1,200,000,000 × 10⁹ (1.2B) gives cumulative destruction without reconstructing any event history.