Rewards
LP rewards
Daily THD for THD/ETH liquidity providers once the whole supply has unlocked: one pool of bucket and recycled sell-fee THD, a halving budget scaled by the public in-range share, and a cumulative root.
ThdLpRewards pays THD every day to liquidity providers in the THD/ETH pool, on top of the swap fees their own positions earn. It holds one balance, pays it out on a halving schedule, and pays against a cumulative Merkle root.
Status#
| Item | Status |
|---|---|
ThdLpRewards — the LP providers bucket’s beneficiary | Deployed |
| Daily rounds | Not startedStart once the whole supply has unlocked |
| Claims | Not openOpen 24 hours after THD's pool is seeded |
Where the THD comes from#
| Source | Amount | Arrives |
|---|---|---|
| LP providers bucket (bucket 4) | 1,000 bps of supply — 100,000,000 THD | 10% of every unlock, by THDEmissionControl.claim(4), while the fee meter runs |
| Recycled sell-fee THD | The THD leg of the platform’s locked position’s fees | Only while the monthly holder vote sets recycle, when ThdFeeRouter flushes it |
The contract does not tell the two apart. Recycled THD lengthens the same schedule; it does not start a second one. There is no quest split on this allocation.
The daily round#
Remaining = THD held − (totalPromised − totalClaimed) // ThdLpRewards.remaining()
Budget = Remaining × (1 − 0.5^(elapsed ÷ 104 weeks)) // elapsed = exact seconds since the last round
Emitted = Budget × min(1, s_t ÷ 50%)
LP i = Emitted × (LP i's weight ÷ all public weight) // named providers only| Term | Value |
|---|---|
| Cadence | One round per UTC day, closed at the first run past midnight |
| Half-life | HALF_LIFE = 104 weeks. At full emission, Remaining halves every 104 weeks |
s_t | Public in-range liquidity-seconds ÷ all in-range liquidity-seconds in the pool that round |
| Target | 50%. Below it the emission scales down linearly |
| Not emitted | Stays in Remaining for later rounds. Never burned |
| Starts | After 100% unlock (THDEmissionControl.isComplete()). Before it the bucket’s THD accrues here and no round runs |
As the platform’s own liquidity grows, s_t falls and so does the daily emission: the reward rents outside depth only while it is needed.
Who is paid, and by what weight#
Weight is liquidity × time in range, from the pool’s own events. A position out of range accrues nothing. A round counts only what accrued since the previous round’s cutoff.
| Position | In s_t’s denominator | In s_t’s numerator | Paid |
|---|---|---|---|
The platform’s own (ThdLiquidityManager) | Yes | No | No |
| A provider on the platform exclusion list | Yes | No | No |
| A public position with a named provider | Yes | Yes | Yes, by weight |
| A public position whose provider the index cannot name | Yes | Yes | No — its share stays in Remaining |
Roots, the publisher and the veto#
Each round adds to every provider’s lifetime total. The root commits to keccak256(abi.encode(account, cumulative)) leaves and is published with totalPromised, the sum of its leaves.
| Publisher | Bound | Active after | Veto |
|---|---|---|---|
publisher() — appointed by the owner Safe; publishes every day | May only raise totalPromised, by at most publisherAllowance(): an on-chain upper bound on one elapsed period’s budget | PUBLISHER_ROOT_DELAY, 12 hours | Owner Safe or guardian Safe |
| Owner Safe | Not bound by the allowance | OWNER_ROOT_DELAY, 48 hours | Guardian Safe only |
| Check | Refusal |
|---|---|
| Total below what has been paid | PromiseBelowPaid |
| Unpaid part above the THD held | PromiseExceedsHeld |
| Publisher lowering the total | PublisherCannotLowerPromise |
| Publisher rise above the allowance | PublisherRiseExceedsAllowance |
| Publisher staging over an immature root | PendingRootNotMatured |
Claiming#
| Rule | Value | Refusal |
|---|---|---|
| Pays | cumulative − claimedOf[account], always to account. Anyone may submit it | NothingToClaim |
| Opens | seededAt + TGE_CLIFF, 24 hours after THD’s pool is seeded | ClaimsNotOpen |
| Claim gate | Passed once on ClaimGateAttestor — see THD claims | ClaimGateNotPassed |
| Root went backwards | A lower figure can never claw back what was paid | CumulativeWentBackwards |
| Stated total | Lifetime payments never exceed the active root’s totalPromised | PromiseExceeded |
| Missed days | Never lost: the newest root carries every earlier round | — |
| Vest | None | — |
| Deadline | None. Nothing here expires or burns, and no owner path moves THD out | — |