DualCurve
{{ blockLabel }}

Every swap pays the holders who stayed.

DualCurve takes {{ feePct }}% of the ETH leg on every trade through its Uniswap v4 hook and routes it into two distribution curves. One pays the top {{ smallTopN }} holders every {{ smallThreshold }} ETH; the other opens a Merkle round for the top 20 every {{ largeThreshold }} ETH. No treasury, no emissions, no governance token.

{{ c.name }}
{{ c.who }}
{{ c.accum }} / {{ c.ceiling }} ETH
{{ c.pct }}% to next {{ c.verb }} {{ c.eta }}
{{ s.label }}
{{ s.value }}
{{ s.note }}
Accumulation

Two curves, one fee stream.

Both curves fill from the same fees and empty the same way. The only difference is the height of the ceiling, which is what makes one pay constantly and the other pay rarely and large.

Cumulative fees captured
Every taxed swap since the pool was initialised
{{ feesTotal }} ETH · {{ feesUsd }}
{{ y }}
{{ x }}
{{ c.name }}
{{ c.window }}
{{ c.sub }}
{{ y }}
{{ x }}
{{ f.k }}
{{ f.v }}
The path of one fee

Five steps, all on-chain.

{{ f.n }}
{{ f.title }}
{{ f.body }}
{{ f.src }}
Protocol parameters
{{ p.k }} {{ p.v }}
Live fee feed
Streaming
{{ e.kind }} {{ e.addr }} {{ e.amount }}
Indexed from DualCurveHook.HookFeeCollected.
Ownership renounced · 5 of 7 contracts

The parameters cannot be changed. Not by us, not by anyone.

Token, hook, router and both snapshot managers have no owner. The only retained admin function is an inactivity valve on the distributors, reachable solely after three days without a single deposit, which any swap resets.

Position

Your standing in the ranking.

Rewards are computed from your balance at snapshot time, not at claim time.

{{ d.label }}
{{ d.value }}
{{ d.note }}
Next SmallCurve push
{{ smallAccum }} / {{ smallThreshold }} ETH · {{ smallPct }}%
Your projected share
{{ me.est }}
Eligibility
Passed

Held {{ me.held }}, above the 300-block minimum. Your balance must stay at or above 0.1% of supply through the snapshot to receive the push.

Your reward history
RoundCurveYour shareWhen
{{ r.id }} {{ r.curve }} {{ r.myShare }} {{ r.when }}
Official pool · Uniswap v4

Trade ETH against DCRV.

The {{ feePct }}% hook fee applies to the ETH leg only: taken from your input on a buy, from your output on a sell. It is never held: the hook forwards it to the router inside the same transaction.

Pool
{{ p.k }} {{ p.v }}
Buy DCRV
Sell DCRV
You payBalance {{ payBalance }}
{{ payToken }}
You receive (estimated)
{{ swapOut }}
{{ getToken }}
{{ r.k }} {{ r.v }}
Routed through UniversalRouter. Slippage 0.5%. The hook fee is not slippage; it is protocol revenue paid to holders.
Where your fee goes
{{ c.label }}
{{ c.value }}
{{ c.note }}
HolderRanking.sol · on-chain min-heap

The ranking is the contract.

Every transfer updates a bounded 100-slot heap. Holding under 0.1% of supply evicts you; holding under 300 blocks makes you visible but not yet eligible.

Snapshot at block {{ blockLabel }}
RankAddressBalanceShare of supplyStatusNext push (est.)
{{ h.rank }} {{ h.addr }} {{ h.bal }} {{ h.pct }} {{ h.status }} {{ h.est }}
Showing 20 of 100 ranked holders.
Distribution log

Every payout, since block one.

SmallCurve pushes settle in a single transaction. LargeCurve rounds publish a Merkle root and stay open for 30 days.

{{ d.label }}
{{ d.value }}
LargeCurve Merkle rounds
{{ m.id }} {{ m.status }}
{{ r.k }} {{ r.v }}
{{ m.pct }}% claimed by the top 20
SmallCurve pushes
RoundAmountHolders paidFailed pushesStatusExecuted
{{ r.id }} {{ r.amount }} {{ r.holders }} {{ r.failed }} {{ r.status }} {{ r.when }}
LargeCurveAccumulator.claim()

Pull your Merkle share.

Your leaf is keccak256(address ++ amount). The contract verifies the proof against the round's root, marks you claimed, then transfers, in that order. Anything unclaimed after the deadline is swept into SmallCurve and paid to the top 100 instead.

{{ c.label }} {{ c.note }}
{{ claimRoundLabel }} closes in 18d 04h
Your claimable amount
{{ me.claimable }}
Rank {{ me.rank }} at snapshot · {{ me.pct }} of supply
{{ r.k }} {{ r.v }}
One claim per round per address. Claiming is irreversible and cannot be split.
Architecture

Seven contracts. One direction of flow.

Nothing loops back. ETH moves from the pool to the hook, from the hook to the router, from the router into the two curves, and from the curves to holders. Ranking and snapshots are read-only inputs to that flow.

{{ c.stage }}
{{ b.name }}
{{ b.body }}
{{ b.owner }}
{{ n.kicker }}

{{ n.title }}

{{ n.body }}

Technical documentation · v1.0 · September 2026

DualCurve protocol specification

A complete description of the fee-capture hook, the ranking heap, the snapshot security model and both distribution curves as deployed on Robinhood Chain. Every constant quoted here is compiled into the bytecode and cannot be changed after renouncement.

01 · Abstract

A fee that pays the register, not a treasury

DualCurve is a fixed-supply ERC-20 whose trading fee is captured by a Uniswap v4 hook and redistributed to its own largest, longest-held holders. There is no treasury address, no emission schedule and no governance token. The protocol is seven contracts: a token, a hook, a router, a ranking heap, two snapshot managers and two distributors.

Value moves in exactly one direction. The hook takes {{ feePct }}% of the ETH leg of every swap and forwards it to the router in the same transaction. The router splits it {{ smallSplitPct }}/{{ largeSplitPct }} between two accumulators. Each accumulator has a ceiling; crossing it locks the balance, requests a ranking snapshot, then pays out once a mandatory delay has passed. SmallCurve pushes ETH to the top {{ smallTopN }} holders. LargeCurve publishes a Merkle root for the top 20 and lets them pull.

FieldMainnetTestnet
{{ r.k }} {{ r.main }} {{ r.test }}
02 · Architecture

Seven contracts, no cycles

The deployment script broadcasts the seven contracts and wires them with one-shot setters that revert once set, so the topology below is final. Ranking and snapshots are read-only inputs: no contract downstream of them can write back.

{{ archDiagram }}
{{ m.name }}
{{ m.body }}
03 · Fee capture

The hook, both legs

The hook is attached to a single ETH/DCRV v4 pool and holds four permissions, which the PoolManager enforces through the low bits of the hook's own address: the deployment mines a CREATE2 salt until uint160(addr) & ALL_HOOK_MASK == 0xCC. Only exactIn swaps are taxed; exact-output swaps and any non-ETH leg pass through untouched with a zero delta.

{{ l.leg }}
{{ l.fn }}

{{ l.body }}

{{ l.formula }}

The fee rate is capped in the bytecode at 1,000 bps (10%) and was deployed at {{ feeBps }} bps. The setter that could raise it within that cap is unreachable: the hook has renounced ownership. A fee of zero, or a computed fee that truncates to zero, short-circuits to a zero delta rather than reverting.

04 · Routing

Splitting in basis points

The router is deliberately dumb: it holds no balance between transactions and has no withdrawal path. It receives ETH, computes two shares, and calls deposit() on each accumulator, which in turn verify that the caller is the router. Both a direct transfer and an explicit routeFees() call route identically.

{{ r.k }} {{ r.v }}
05 · Holder ranking

A bounded heap, updated on every transfer

The token's _update override notifies the ranking with both parties' new balances on every transfer, mint and burn. The ranking keeps a 100-slot min-heap whose root is the smallest balance in the set, so admission is an O(1) comparison and insertion is O(log n).

Entry encoding · one uint256 per slot
balance
bits 255…160 · uint96
address
bits 159…0 · uint160

Packing the balance above the address makes the encoded integer sort by balance, which is what lets a plain min-heap rank holders with no comparator. 96 bits holds about 7.9 × 10²⁸, comfortably above the 10²⁷ wei-scale total supply, and an overflow reverts rather than truncating.

{{ r.k }}
{{ r.v }}
06 · Snapshots

A snapshot can never be used in the transaction that made it

This is the protocol's central security property. Crossing a threshold does not pay anyone; it records a request with an executeAfter block. Until that block, executeSnapshot reverts with TooEarlyToExecute. Any attempt to reshuffle the ranking inside the window is public, and execution is permissionless, so an honest party can settle the snapshot before an attacker can finish positioning.

{{ s.n }}
{{ s.title }}
{{ s.body }}

Execution also intersects the top-N list with getEligibleHolders(), so hold time is enforced a second time at settlement. The stored snapshot is immutable: holders, balances and the block it was taken at.

07 · SmallCurve

Push distribution, every {{ smallThreshold }} ETH

On the deposit that crosses the ceiling, the accumulated balance is moved to lockedForDistribution, the accumulator resets to zero, and a snapshot is requested. Once executable, anyone can call executeDistribution(), which iterates the snapshot and transfers each holder's pro-rata share.

share[i] = lockedForDistribution × balance[i] / Σ balance
{{ r.k }}
{{ r.v }}
Accounting invariant · fuzz-tested
address(this).balance == accumulated + lockedForDistribution + totalReclaimable
08 · LargeCurve

Merkle rounds, every {{ largeThreshold }} ETH

LargeCurve never pushes. At the ceiling it computes each holder's share, drops zero-share entries, builds a Merkle tree in memory and stores only the root, the total and a deadline. Holders then pull with a proof. This keeps a 20-holder settlement inside one transaction regardless of how hostile the receiving addresses are.

{{ m.k }}
{{ m.code }}
{{ m.note }}
{{ r.k }}
{{ r.v }}
Accounting invariant · fuzz-tested
address(this).balance == accumulated + lockedForDistribution + totalLockedInRounds
09 · Parameters & addresses

Deployed constants

{{ p.k }} {{ p.v }}
ContractAddressOwnership
{{ c.name }} {{ c.addr }} {{ c.owner }}
PoolManager, PositionManager, UniversalRouter and Permit2 are the canonical Robinhood Chain deployments and are not part of this protocol.
10 · Security, chain notes & risk

What can and cannot be changed

{{ o.k }}
{{ o.v }}
{{ r.kicker }}

{{ r.title }}

{{ r.body }}

This document summarises protocol design. The contract source and the deployment playbook are the authoritative reference. Licensed MIT. Nothing here is an offer, a solicitation, or investment advice.