Protocol mechanics
Revenue routing
From the Mine, through the Router, into a seven-day stream to strategies.
Loading…
Protocol mechanics
From the Mine, through the Router, into a seven-day stream to strategies.
Loading…
Protocol mechanics
From the Mine, through the Router, into a seven-day stream to strategies.
At launch, mining revenue is directed through ResonanceRouter into the Resonance revenue stream. The router is ownerless and permanently paired with one Resonance; the Mine's destination can be changed by the FundController owner.
Every nonzero mining payment sends its remainder to the Mine's current revenueRouter, after recording outgoing-miner, team and protocol claims. FundController.setRevenueRouter(address) can redirect future payments to another deployed contract. Only the presence of code is checked; compatible routing behavior is not enforced.
The change does not migrate old balances, signals, strategies or rewards. FundController remains bound to its original Resonance. A replacement destination may use different rules or strand or divert the revenue. The rest of this page describes the launch-time routing setup.
The router is permanently paired with one Resonance and USDC. Anyone can call route() to forward its balance, subject to three checks:
route() reverts and the balance waits. This prevents a stream from starting with nobody to receive it.604,800 seconds, so anything smaller would round to a zero rate. Below that, the router emits RevenueHeld and keeps the balance.remainingRevenue(). Below that, the router again holds and retries later.A qualifying attempt approves the exact amount, calls Resonance.notifyRevenue, transfers the USDC and emits RevenueRouted, all atomically. A downstream failure leaves the balance in the router, retryable. The app's auction fills through the Periphery and its Operations batch (OperationsPeriphery.run) try route() when these checks pass; the function is public so anyone, including a bot, can do it.
notifyRevenue(amount) is callable only by the bound router. It checkpoints the global accumulator through the earlier of now and the current period's end, then starts a new seven-day period whose rate is:
rate = floor((amount + remaining of the previous period + saved remainder) / 604,800)The division remainder is saved and included in the next qualifying notification. If no further funding qualifies, it remains pending. Separate accumulator and account conversions also round down. The accumulator is scaled by 1e36 per raw unit of signal weight, and a lifetime cap of (2^256 - 1) / 1e36 raw USDC bounds what the Resonance will ever accept.
Every live strategy accrues its share of the stream continuously:
strategy share per second = rate * strategyWeight / totalSignalWeightWeights change whenever signals are added or removed; the accumulator is checkpointed at the old weight first, so no strategy can claim revenue that accrued before it had weight, and a strategy added later starts at the current index with nothing owed.
distributeRevenue(strategy) is permissionless. It checkpoints one strategy and transfers its accrued USDC to that strategy's own address, rounding down to whole raw units. It works for killed strategies too: a kill checkpoints the strategy under its full prior weight and preserves what it had earned. A strategy that has been distributed to holds that USDC until its auction is filled; earnedRevenue(strategy) shows what has accrued but not yet been distributed.
A running stream does not pause if live signals fall to zero. Revenue elapsed with zero live weight becomes unallocated surplus and cannot be claimed by a strategy that receives signals later.
A strategy's auction sells its complete USDC balance, and Auction.buy first pulls any undistributed revenue for itself, so buyers never need to distribute manually.
The original router has no rescue function. A lifetime funding cap, incompatible token, or abandoned signal can leave balances pending indefinitely. Redirecting the Mine does not recover those balances. See team authority for this trust boundary.