How Twofold works.
Twofold deploys Uniswap's DualPool hook on Robinhood Chain. The design puts the same capital to work twice: lending yield while it rests, trading fees while it works. 29 pools are live on the Registry, every one of them resting its USDG leg in an allowlisted Steakhouse vault, and deposits are open to anyone. TWO trades on-chain and staking is open.
Overview
Twofold deploys Uniswap's DualPool v4 hook on Robinhood Chain (chain id 4663), byte for byte unmodified, through Uniswap's own AllowlistedFactory pattern. Uniswap audited the hook upstream. Twofold adds a small set of open-source wrapper contracts around it: OperatorController, VaultAllowlist, Registry, StakingVault, and TwofoldToken.
LP capital rests in a lending vault and steps into the pool only for the instant a swap needs it, so you collect both income streams on the same dollars.
A Twofold pool is an ordinary Uniswap v4 pool with the hook attached. 37 of them are open, listed on a Registry and readable by anyone: one WETH pair, one TWO pair, one USDG/USDe stable pair, and the rest tokenized equities against USDG. The next section lists them live.
The live pools
Every pool here was created by the Twofold factory and is listed on the on-chain Registry. The current pools charge 0.05 percent on the equity pairs (tick spacing 10), 0.01 percent on WETH/USDG and USDe/USDG, and 1 percent on TWO/USDG. A first generation of pools at 0.3 percent stays listed for the wallets that still hold them; deposits go to the current pools. They all rest their USDG leg in the Steakhouse USDG vault, which the VaultAllowlist names by exact address. Deposits are open to anyone. This table is read from the chain, not typed by hand, so a pool listed a minute ago appears here on its own.
| Pair | Resting vault | Pair volume, 24h |
|---|---|---|
| Reading the Registry… | ||
The volume column is what the pair traded across every Uniswap v4 pool on Robinhood Chain in the last 24 hours, not what this pool traded. It is there to answer one question before you supply a pool: does this pair trade enough for the swap fee to be worth anything? A deep pair with heavy flow earns fees; a quiet one earns the vault rate and little else.
Opening another costs about fifty cents of gas and no contract deploy, because one hook serves every pool. Which pairs come next depends on which tokenized equities have a reference pool deep enough to price a seed against.
One-click deposit
A DualPool deposit takes both legs of the pair in the pool's own ratio. If you hold only ETH or only USDG, the zap does the rest. On the app deposit panel, tick Pay with ETH or Pay with USDG, enter an amount, and confirm once. One transaction buys the leg you lack, deposits both, and sends any remainder back to your wallet.
What the transaction does
- Splits your budget against the pool's live ratio, read from the hook's deposit preview, so the two legs land in the proportion the pool takes.
- Buys the missing leg on the deepest hookless Uniswap v4 pool for that pair on Robinhood Chain. An ETH payment into a USDG pool sells ETH for USDG on the WETH/USDG market first, then buys the equity leg with the USDG.
- Deposits both legs through the hook, the same call a two-sided deposit makes.
- Refunds the remainder. Share rounding favors the pool, so about half a percent of the budget goes unspent. You get it back in the same transaction, with any WETH unwrapped to ETH.
The PoolZapper contract at 0x8934A298d3E59a632994ac254Dee19112127f2B7 runs all four steps atomically (the first-generation pools keep their own zapper at 0x2eF1C576797a51FB60B25d9f946D2562d2d2F9Fc for withdrawals). If any step fails the transaction reverts and nothing leaves your wallet. The contract has no owner, no admin functions and no upgrade path. Blockscout holds its verified source, and it appears under Contracts.
Where the position lives
Because the zapper makes the deposit, the hook credits the shares to the zapper, and the zapper records in its own ledger which wallet owns them. Your entry is an ERC-1155 token named Twofold LP (TWO-LP), one id per pool. That is why your wallet's simulator shows you receiving a position instead of only spending ETH. You hold the same share of reserves, earn the same vault yield on the USDG leg and the same swap fees as a direct depositor. Only the ledger holder can withdraw, and sending the token to another wallet sends the exit right with it.
You withdraw with the same button as any other position. The pools page reads hook shares and zapper shares and shows them split. A zapped position leaves through the zapper's zapOut, which burns the ledger entry and pays both legs to your wallet in one transaction. If you also hold shares directly on the hook, the app asks you to confirm that part separately.
Price impact and limits
- ✓Quoted at your size. The reference markets vary widely in depth, so the pools page quotes the swap for the amount you entered rather than for one unit. The preview shows what the pool will fill.
- ✓A floor, never zero. The transaction carries a minimum output 1 percent under the quote. If the market moves against you by more than that between preview and confirmation, the deposit reverts.
- ✓Impact above 2 percent is shown; above 15 the page refuses. A swap that would move the reference market more than 15 percent does not get built. Enter a smaller amount or make a two-sided deposit.
- ✓Only where a market exists. If the other leg has no hookless reference pool, the pools page does not offer the box for that pool. A two-sided deposit still works everywhere.
You pay the reference pool's swap fee and its price impact. Twofold adds no fee for the zap.
How dual accrual works
In a normal AMM, liquidity sits in the pool around the clock and earns only when a trade crosses it. DualPool moves the idle time somewhere productive.
LP capital rests in an allowlisted ERC-4626 vault, earning lending yield block by block. When a swap arrives, the hook withdraws just-in-time concentrated liquidity from the vault, fills the trade, captures the swap fee, and returns the capital to the vault. All of that happens inside the one swap transaction. The capital never sleeps outside the vault.
You make one deposit and never move it between the two modes. The hook decides when the capital works and when it rests, and the swap pays for the trip.
Range maintenance
A Twofold pool keeps its depth in a band around the current price rather than spread across every price from zero to infinity. That band is the pool's liquidity shape: a set of price buckets telling the hook where to put liquidity when a swap arrives. Around 70 percent of the depth sits within 13 percent of the center, and the remainder reaches out to roughly 52 percent on either side.
Concentration is what makes the capital productive. A dollar stretched across all prices backs almost no trade at any single price. The same dollar inside a tight band fills many times as much, and those fills are where your swap fees come from. It is also why a Twofold pool quotes a tighter spread than a full-range pool holding the same reserves.
The band earns while the market trades inside it. Let the price walk out and your depth stays put, parked at prices nobody is trading. That is the problem range maintenance solves.
How the range follows the price
Twofold moves the band back over the market on its own, with no action from you. Once a minute the protocol reads where each pair trades on the wider market and compares that against the center of the pool's shape. Once the gap passes about 5 percent, the range starts walking toward the price.
The move is a step, never a jump, and the size and pace are capped in the contract call itself. A price spike that lasts one block cannot drag a range anywhere.
What this looks like on a stock pool
Tokenized stocks are where the difference shows. An equity token reprices in jumps rather than drifts: an earnings print, a downgrade, a gap between one session and the next. One of those moves can put the token several percent from where it traded an hour earlier, and it stays there.
A conventional concentrated pool has no answer. Somebody chose its range at deposit time and it sits at that price until a person notices and rebuilds the position by hand. After a jump the pool is quoting into empty space. The first trader through takes whatever thin depth is left at the old price, everyone after that sees a spread wide enough to walk away from, and the liquidity provider earns nothing while the market trades somewhere else.
A Twofold pool reads where the token is actually trading, on the deepest market for that pair on Robinhood Chain, and starts walking its band there inside a minute. Once the new price holds, the full shape sits underneath it: 70 percent of the depth within 13 percent of where the token now trades, the rest reaching out behind it. Traders get the same tight quote they had before the move. You did nothing, and your reserves never left the pool.
What recentering can and cannot do
- ✓Approved shapes only. The controller owner signs every shape a pool may use on-chain, in advance. Recentering picks one of those or pauses. There is no third option.
- ✓It never reaches your money. The function cannot withdraw liquidity, change a fee, or touch a pool's vault.
- ✓A strange price gets ignored. A market price more than 20 percent from the pool's own price has to hold for five straight minutes before it counts, so one manipulated block moves nothing.
- ✓Silence beats guessing. A failed price read, a low balance, or a price outside the approved set stops recentering. The pool is left alone.
- ✓Nothing here is discretionary. The rules above run the same way on every pool, every minute.
Every recenter is an on-chain transaction from the controller listed under Contracts, so the full history of range moves on every pool is readable on Blockscout. You do nothing and you lose nothing to the move. Shares are proportional to reserves, so re-bucketing the same reserves leaves a share worth what it was worth a second earlier.
Where yield comes from
Two sources, both visible on chain.
- 01Lending yield. While capital rests it sits in an allowlisted ERC-4626 vault, where the hook is an ordinary depositor and earns whatever that vault pays its depositors. Every live pool rests its USDG leg in Steakhouse USDG. Twofold operates no vault and is backed by no vault's assets; it is a depositor there like anyone else.
- 02Trading fees. Every swap through a Twofold pool pays the pool's swap fee, and the hook captures it during the same transaction that moves the liquidity. The fee is fixed when a pool is created and can never be changed: 0.3 percent on the stock and ETH pools, 1 percent on TWO/USDG and 0.01 percent on USDG/USDe.
We publish no APY projection. The vault rate shown on this site is the trailing rate the Steakhouse USDG vault has actually paid its depositors, measured from its share price over a rolling window, and it moves. Fee income floats with trading volume, which is why the pool list shows what each pair traded rather than a number we made up. Neither figure is a promise.
How to read the yield figure on a pool card
Each pool card leads with one number, and it is measured, not modeled. It adds two things: the vault rate on the USDG leg, and the swap fees the pool collected in the last 24 hours, annualized on the depth sitting in it right now. A pool that took no trades shows the vault rate alone, because that is all it paid that day.
The fee part can be large. A day of aggregator flow through a small pool at a 1 percent tier can annualize to hundreds of percent, and the card will say so, because that is what the pool earned per dollar of depth that day. It is a trailing rate, not a forecast. Volume comes in bursts, so the figure moves with each day's trading, and a pool that is busy today may be quiet tomorrow. A pool holding under 1,000 USDG shows no fee component at all, since a few trades against a seed-sized reserve produce a quotient that says nothing.
Fees are also only half the story on a moving pair. When traders buy one side hard, the pool sells that token on the way up and ends the day holding more of the other. The fee income is real and stays in the reserves, and the change in what the reserves hold is the usual cost of providing liquidity. The earnings line on your position shows both, per token, so you can see the fee against the mix.
Your earnings, plainly
Start here if you have never supplied a pool before. This section covers what you own after a deposit, when each kind of earning shows up, and where to read what you have made.
What you own
When you deposit, you put in both tokens of the pair at the pool's current ratio and receive shares. A share is a fixed slice of everything the pool holds. Nothing is paid out to you on a schedule and there is no reward to claim. Instead, the pool grows, and your slice of it is worth more tokens than you put in. You collect by withdrawing, which burns your shares and pays you both tokens in the pool's ratio at that moment. You can withdraw at any time except in the same block you deposited.
When swap fees arrive
Between trades a Twofold pool keeps no liquidity inside Uniswap. When a swap arrives, the hook places the pool's reserves as concentrated positions around the current price, the swap executes against them and pays the pool's fee, and the hook pulls every position back, fee included, all inside that one transaction. So fees land the instant a trade happens, trade by trade. There is no fee balance sitting somewhere waiting to be collected. Each fee is in the reserves, and in your shares, the moment the swap confirms.
When the USDG yield arrives
After every trade and every deposit, the hook moves the pool's idle USDG into the Steakhouse USDG vault, a Morpho lending vault, where it earns interest from borrowers second by second. Only the USDG side rests there. The stock or ETH side sits as a plain balance, because nothing on this chain borrows those assets, so a vault for them would pay nothing. The interest is counted in the pool's reserves at every moment through the vault's share price, so your position reflects it continuously, not weekly or monthly. When you withdraw, the hook pulls what it needs back out of the vault to pay you.
Who takes a cut
Nobody, at the pool level. The hook charges no fee of its own, and Uniswap's protocol fee on these pools is zero. The operator contract can only ever touch the small seed it deposited itself when each pool was opened, so it cannot reach your share of the fees or the interest.
How to see what you have made
Open Pools with your wallet connected. My positions shows, for each pool, how many of each token your shares are worth right now, and under it an Earned so far line: what you would get out today, plus anything you already withdrew, minus everything you put in, per token. That figure is exact and comes from the deposit and withdrawal events the hook logs on chain. The line also gives a rough split of how much of the USDG side is vault interest. The contract does not separate interest from fees, so that part is an estimate made from the vault's share price at the time of each of your deposits; whatever is left is swap fees and price movement.
What can go against you
Two things. First, impermanent loss: if the pair's price moves a lot after you deposit, the pool's ratio moves with it and the two tokens you get back can be worth less than holding them would have been, exactly as in any AMM. Second, the vault: if Steakhouse pauses withdrawals, the hook may have to wait to pull USDG back out. The equity pools are small today, so their fee income is small in absolute terms; what the pair traded in the last 24 hours is shown in the pool table above.
The TWO token
TWO is the protocol token. Three rules cover its supply.
- ✓Fixed supply of 1,000,000,000. Minted once at deployment.
- ✓No mint function. The contract has no code path that creates new tokens.
- ✓No owner. The token contract has no owner, so nobody holds an admin key over it.
Stake TWO in the StakingVault and you hold a claim on whatever a rewarder funds into it, paid out per second instead of in one block. Harvested pool revenue has one destination, that vault. The next two sections cover both vaults.
Deposit rewards
Every dollar supplied to a V2 pool earns USDG every second it is there, on top of the swap fees and the vault yield the position already earns. The rate is the same for every V2 pool: the day's budget is split across the pools by the depth outside wallets hold in each, then inside a pool by share-seconds. Deposit and you start earning that second; withdraw and you keep every cent accrued up to that second. There is no warm-up, no forfeit and no lock.
Two ceilings set the day's budget. A fixed USDG figure caps what is paid in total, and a maximum APR caps what any depth can earn, so the rate on the pools page reads "up to" that APR. While depth is small the APR ceiling binds and the payout is proportional to what is actually supplied; when depth is large the fixed budget binds and the APR falls with it. Both numbers can change at any time, and the pools page always shows the current ceiling.
The stake boost
Staking TWO raises a wallet's ceiling, up to three times the base. Coverage is measured in TWO, not dollars: 1,000 TWO staked for every USDG of value the wallet has deposited in V2 pools is full coverage, and the multiplier scales in a straight line below that, so half the stake is a 2x. Stake in either vault counts, no price feed is involved, and a rising or falling TWO price changes nothing for a stake already in place. Adding deposits without adding stake lowers coverage; starting an unstake ends the boost that second. The pools page shows each wallet's multiplier and how much more TWO would reach the full one.
The TWO/USDG pool counts double in the budget, on the base rate and on the boosted one, because it is the pool the protocol most wants deep. Every pool card shows its own range.
Rewards are paid in USDG from a dedicated contract, RewardsPayer, that holds the budget. It is funded by hand from trading fees the protocol's own positions earn, nothing is minted and no TWO is sold to pay it. Payments go out every day, shortly after 00:00 UTC, to every wallet owed at least 1 USDG; smaller amounts roll into the following day. A wallet that withdraws its whole position is paid in the next cycle. The pools page shows the wallet's live rate, what it has earned so far and what it is owed, and the payout history is on chain as Paid events from the contract.
First-stack pools, the keys that take no new deposits, earn no rewards; their positions can still be withdrawn at any time. Deposits made by the protocol itself, through the operator controllers or the deployer, are excluded from both the accrual and the depth split, so the whole budget goes to outside wallets.
TWO staking (vault 1, retired)
Vault 1 is retired. It paid TWO stakers in TWO through the launch stream, and that stream has ended. It takes no new stake; anyone still inside can unstake, claim what they earned and move to vault 2 at any time. This section stays as the record of how it worked.
It runs on its own contract, StakingVaultV2, separate from vault 2. It is also where the operator controller sends the protocol's share of pool yield when a pool is harvested.
Everything streamed so far was topped into the vault directly by the operator: just under 55,000,000 TWO across seven fillings since launch. Each filling folds into whatever is still streaming and restarts a 7 day stream, paid out second by second rather than in lumps.
How the stream pays
The vault pays a rate per second, split across every TWO staked in that second. Arrive late and you earn from the second you arrive, never from time you were not staked for. Leave and the accrual stops there.
Each filling streams over 7 days from the block it lands, so nothing is claimable at the instant of a top-up and a late staker cannot take a share of time they were not staked for. The figure on the stake page is what the vault is paying at that moment.
No ceiling
Vault 1 had no cap. Whatever was streaming was divided across the whole staked total at each second, so more TWO staked meant a thinner slice per token. With the vault retired the rate on the stake page reads zero.
Exit cooldown
Unstaking is two steps: start it, wait 1 hour, withdraw. TWO stops earning the moment it is queued. The vault holds one exit per wallet at a time: while an exit is waiting or unclaimed, a second one is refused until the first has been withdrawn, so the two never mix and the hour is never restarted on you. The hour stops flash-in, flash-out capture of a distribution: nobody can stake as a filling lands, collect, and leave in the same breath.
The limits of the contract
- ✓Rewards leave one way. No contract path moves funded TWO out except a staker claiming what they earned. There is no sweep and no rescue function, and a filling cannot be taken back.
- ✓Staked TWO stays yours. No call removes a staker or reaches staked TWO, and there is no pause of any kind. Stake, exit and claim keep working in every state the contract can be in.
- ✓The hour is fixed. The cooldown and the 7 day stream length were set at deployment and cannot change, so nothing lengthens an exit after you queue it.
- ✓Nothing is minted. The vault pays out only what a rewarder has already transferred in. Staking does not touch LP deposits and TWO supply does not move.
- ✓One reward token today. The vault can carry up to 16 reward tokens; only TWO has ever been streamed through it.
The rate on the stake page is arithmetic, not a forecast: the current stream divided across what is staked at that moment. It moves with every filling and every stake, and we publish no projection of where it lands.
USDG staking (vault 2)
Vault 2 pays TWO stakers in USDG, the same stablecoin the pools rest their idle leg in. Stake TWO and USDG accrues to you every second you hold it there. Claim whenever you want, and the earned USDG carries no waiting period.
It runs on its own contract, TwoStakingUSDG, separate from vault 1 and wired to nothing else.
The USDG comes from the protocol's trading fees. Fee revenue is converted to USDG and topped into the vault on a rolling basis, and it pays out second by second rather than in lumps, so the stream keeps running as long as the pools keep trading.
How the stream pays
The vault pays a rate per second, split across every TWO staked in that second. Arrive late and you earn from the second you arrive, never from time you were not staked for. Leave and the accrual stops there.
Each top-up folds into what is already streaming and keeps the payout running, so the rate moves as fees arrive and as people stake or leave. The figure on the stake page is what the vault is paying at that moment.
Limited room, on purpose
The vault takes at most 400,000,000 staked TWO, 40 percent of supply. Whatever is funded gets divided by whatever is staked, so the ceiling is what keeps a fill from being spread across the whole float. Fewer TWO sharing the same stream means more USDG per token.
Once the vault holds that much, a new stake waits for room, which opens when somebody else exits. The pools page and the stake page both show what is staked against the cap, read from the contract.
Exit cooldown
Unstaking is two steps: start it, wait 7 days, withdraw. TWO stops earning the moment it is queued. Starting another unstake while one is waiting adds to the queue and restarts the 7 days for the whole queue, so a small test unstake never strands a later, larger one. The 7 days cannot be shortened by any sequence of calls.
The limits of the contract
- ✓USDG leaves one way. No contract path moves the USDG out except a staker claiming what they earned. There is no sweep and no rescue function.
- ✓Staked TWO stays yours. No call removes a staker or reaches staked TWO. Lowering the cap evicts nobody; it decides whether new stakes are accepted, nothing else.
- ✓The exit stays open. Pausing blocks new stakes only. Starting an unstake, withdrawing after the wait, and claiming earned USDG keep working while it is paused.
- ✓Both tokens are fixed. TWO in, USDG out, set at deployment and unchangeable, so nothing swaps the reward for a token you did not sign up for.
- ✓USDG is somebody else's contract. It is an upgradeable proxy, and its issuer sets its transfer rules. A freeze there would freeze this vault's balance too. Every USDG holder carries that risk, here and everywhere else on the chain.
The rate on the stake page is arithmetic, not a forecast: the current stream divided across what is staked at that moment. It moves with every fill and every stake, and we publish no projection of where it lands.
Safety and audits
The core is Uniswap's, unmodified
The DualPool hook we deploy is byte for byte identical to Uniswap's upstream release, deployed through Uniswap's own AllowlistedFactory pattern. Uniswap audited the hook upstream. Anyone can diff our deployment against the published source and confirm the match.
The wrappers are open source and machine checked
Twofold's wrapper contracts (OperatorController, VaultAllowlist, Registry, StakingVault, TwofoldToken) are open source. Each went through a static-analysis battery of Slither, Aderyn, Halmos, and Mythril, plus mutation-tested test suites that prove the tests fail when the guards break. We claim no third-party audit of the wrappers; read the code and the analysis output yourself.
Structural guarantees
- ✓Vaults allowlisted by exact address. A pool can only rest capital in a vault the allowlist names.
- ✓Every pool verifiable. The Twofold factory creates every pool, and the on-chain Registry lets anyone check a pool live before trading it. It holds 29 listings today, and this page reads them from the chain rather than from a list we typed.
- ✓No pre-bootstrap swaps. Pool prices cannot be swapped before bootstrap.
- ✓Pause only makes pools safer. The emergency pause can stop activity. It cannot redirect funds.
- ✓Principal cannot be touched by operations. Opening a pool, recentering, pausing and harvesting the seed's own gain are the operator's calls, and none of them can reach LP principal.
- ✓Owner powers are protected. Ownership is moving behind a multisig and a timelock; see Who controls what.Ownership sits with a multisig behind a timelock: no single key can act, and every owner change is queued in public on chain before it can take effect. See Who controls what.
- ✓Unstake cooldown. Prevents flash-in, flash-out capture of staking rewards.
- ✓Genesis liquidity locked forever. The TWO/WETH genesis position (Uniswap v4 position 1076283, all of its liquidity) sits in the PositionLocker contract. The locker has no transfer, no withdrawal and no burn path, and ownership cannot be renounced. The only thing anyone can do with it is claim the accrued swap fees, which any caller may trigger and which go to the fee wallet.
Who controls what
A DualPool is actively managed: pools get opened, bands get recentered as the market moves, and a pool can be paused if it ever needs to be. That is the operator role. It is not a single key. Owner functions sit behind a multisig and a timelock: a change has to be approved by more than one signer, and it is queued in public on chain before it can take effect. Recentering, pausing, deposits and withdrawals are unaffected and instant.
What it covers
Which vaults a pool may use, opening and seeding pools, approving range shapes, unpausing, moving hook ownership, and listing pools. Every one of those waits its turn in public.
What stays instant
- ✓Your deposits and withdrawals. They never pass through the operator, and no owner function can block a withdrawal.
- ✓Recentering. The range runner moves a pool's band into a pre-approved shape and can do nothing else.
- ✓Pause. Swaps on a pool can be stopped at once; pausing cannot move funds.
Pending changes
Read live from the chain. Nothing queued means no owner action is waiting to execute.
Not yet live
FAQ
Where do I trade Twofold pools?+
Do I need both tokens to deposit?+
No. Tick Pay with ETH or Pay with USDG on the pools page and one transaction buys the other leg, deposits both and refunds the remainder. See One-click deposit for what it does and where the position lives.
Did anyone audit the contracts?+
The DualPool hook: yes, Uniswap audited it upstream, and our deployment is byte for byte identical. The Twofold wrappers: open source, run through Slither, Aderyn, Halmos, and Mythril, with mutation-tested test suites. We claim no third-party audit of the wrappers.
What APY will I earn?+
We publish no projection. What the site shows is measured: the trailing rate the Steakhouse USDG vault has paid depositors, and the 24-hour volume each pair traded across the whole chain. Your own return depends on which pool you supply, how long you stay, and what trades through it. Impermanent loss applies here exactly as it does in any AMM pool.
When do I get paid?+
Continuously, into your shares. Swap fees land in the pool the moment each trade confirms and the USDG interest accrues every second in the Steakhouse vault. Neither is paid out or claimed separately: you receive both when you withdraw, as more tokens than you put in. See Your earnings, plainly.
Can the protocol take my deposited principal?+
No. No contract path lets the protocol reach deposited principal, and public depositors keep all of their growth.
Can more TWO ever be minted?+
No. Supply is fixed at 1,000,000,000, minted once. The token contract has no mint function and no owner.
What does the emergency pause let the team do?+
Pause, and only pause. The pause can make pools safer by stopping activity. It has no power to redirect funds.
Which vault holds the resting capital?+
Steakhouse USDG, 0xBeEff033F34C046626B8D0A041844C5d1A5409dd, for the USDG leg of every live pool. The other leg does not rest; only the stable side is bound to a vault. Vaults are allowlisted by exact address, so a pool can only use one the allowlist names. Twofold operates no vault and is backed by no vault's assets.
Can the team pull the genesis liquidity?+
No. The TWO/WETH genesis position is held by the PositionLocker, 0x485690D46e344127aa2EB45D8d9BAcbb5856D58b, which cannot transfer, decrease or burn it. Fees still accrue and anyone can call claim to send them to the fee recipient. Nobody, the locker owner included, can move, decrease or burn the position.
How do I know a pool is genuine?+
Check it against the on-chain Registry. The Twofold factory creates every genuine pool, and the Registry answers live for any pool address.
Integrate Twofold pools
For aggregators, routers, solvers and anyone building on top. Twofold pools are ordinary Uniswap v4 pools whose hook is Uniswap Labs' DualPoolHook, deployed unmodified. Swaps go through the standard PoolManager and Universal Router with the hook in the pool key. The one thing that differs from a plain v4 pool is pricing: the pool's tick liquidity is empty between trades, so reading slot0 and liquidity tells you nothing. The hook prices the swap itself, and it gives you two ways to ask.
Pool discovery
Two hook deployments are live and both stay live. Read the pool list from the Registry of each, or from the API, which merges them.
| Stack | Hook | Registry | Fee / spacing |
|---|---|---|---|
| First (2026-08), withdraw-only for most keys | 0x127B3f3b7769f659C5eDBfF8b4005443f19FAAc0 | 0x1b66DD14C9281A18E696dbdb40cFB5070842c0C2 | 3000 / 60, TWO/USDG 10000 / 200 |
On chain: Registry.allPoolIds() returns every listed pool id and Registry.getPool(bytes32) returns the listing, which holds the hook, both currencies, the fee, the vault on each leg and an active flag. The tick spacing is not in the listing; it is fixed per stack as above. Off chain: GET https://twofold.fi/api/pools returns every pool with its full key, symbols, decimals, current reserves and 24h volume, refreshed from an indexer that follows the hook's own events.
{ "pools": [ {
"poolId": "0x085e…a06b",
"key": { "currency0": "0xd060…9EEC", "currency1": "0x5fc5…d168",
"fee": 500, "tickSpacing": 10, "hooks": "0xd1Bc…2Ac0" },
"sym0": "NVDA", "sym1": "USDG", "dec0": 18, "dec1": 6,
"reserves": ["2006099115124073394", "463342245"],
"active": true, "vol24h": { "amount0": "…", "amount1": "…", "swaps": 0 }
} ] }
Quoting
Reserves live in the hook, not in the pool: hook.getReserves(PoolKey) returns both legs in token units, vault interest included. To price a swap:
- 01Ask the hook.
hook.getIndicativeQuote(key, zeroForOne, amountSpecified, "")is a view call. Pass a negativeamountSpecifiedfor exact input and it returns the output; pass a positive one for exact output and it returns the input, or 0 when the pool cannot deliver that much. It runs the same allocation math the swap will run, so it is the cheapest accurate price. It is indicative: put your own slippage bound on the execution. - 02Or ask the V4 Quoter.
V4Quoter.quoteExactInputSingleat 0x8Dc178eFB8111BB0973Dd9d722ebeFF267c98F94 with the hook in the key simulates the full swap, hook and all, and is exact to the wei. Use it when your router already speaks Quoter. - 03Or port the math. The hook places the reserves as concentrated positions in weighted tick buckets around the current price and swaps against them.
hook.getDistribution(poolId)returns the buckets. A reference implementation in Go, wei-exact against the Quoter on live pools, is in the KyberSwap adapter.
Two properties matter for a router. The price stays at the pool's own reserve ratio, which the range runner recenters onto the chain's reference price, so there is no standing arbitrage to harvest. And depth is what getReserves says it is, all of it deployable in one swap; a fill cannot exceed the output-side reserve.
Executing a swap
Standard v4. Call PoolManager.swap inside your own unlock callback, or use the Universal Router at 0x8876789976dEcBfCbBbe364623C63652db8C0904 with commands V4_SWAP and actions SWAP_EXACT_IN_SINGLE, SETTLE, TAKE_ALL. Pass empty hookData; the hook takes no input. Two chain-specific traps:
- 01The Universal Router on Robinhood Chain uses a six-field
ExactInputSingleParams:(poolKey, zeroForOne, amountIn, amountOutMinimum, minHopPriceX36, hookData). The canonical five-field layout reverts insideunlockCallback. SetminHopPriceX36to 0 unless you use it. - 02Pay through Permit2 (0x000000000022D473030F116dDEE9F6B43aC78BA3) for ERC-20 input with
payerIsUser = true; for native ETH,WRAP_ETHfirst and settle withpayerIsUser = false.
Depositing from a contract
Deposits mint shares proportional to reserves, so both tokens are needed at the pool's ratio. hook.previewDeposit(key, shares) tells you the amounts for a share count, hook.addLiquidity(key, shares, maxAmount0, maxAmount1, deadline) takes them, and hook.removeLiquidity(key, shares, minAmount0, minAmount1, deadline) pays both legs back. Shares are held per address in the hook (sharesOf(key, address)) and cannot be withdrawn in the block they were minted. For single-asset entry, the PoolZapper does the swap and the two-sided deposit in one transaction and keeps a per-wallet ledger; see One-click deposit.
Listings and contact
TWO is on CoinGecko and Twofold is on DefiLlama. Sources for every contract are verified on Blockscout and listed under Contracts. For an integration question, a quoter test vector, or a pool request, write to contact at twofold.fi.
Contracts
Robinhood Chain, chain id 4663. Every Twofold contract below is deployed and in use: the current Registry holds 30 listings and the first-generation Registry 30 more, of which 7 are still active and the hook is resting capital in the Steakhouse USDG vault right now. The "first stack" rows are the 2026-08 deployment: its pools stay listed and withdrawable, and the seven that still hold outside deposits stay active; new deposits go to the current contracts. The external addresses are third-party contracts, canonical today.
Twofold contracts
| Contract | Role | Address |
|---|---|---|
| DualPoolHook | Uniswap's audited v4 hook, deployed unmodified; every current pool (since 2026-09-05) | 0xd1BcbCCa41f3bdb6b4812652959c6dF725ea2Ac0 |
| AllowlistedFactory | Uniswap's factory pattern; creates every current pool | 0xa9ab194FB74dFD9991047839aE23A576c8403d95 |
| OperatorControllerV2 | Owns the current hook; opens and bootstraps pools, harvests gain above basis to the staking vault, within contract-enforced bounds | 0x705F4f94344feD3f7BA98300F8bC04fdAE570340 |
| VaultAllowlist | Names the exact vault addresses current pools may use | 0x3B1B0f1812a9a09664D82238E94c604D30Bb8134 |
| Registry | On-chain check that a current pool is genuine | 0xdF1a23B1A7507Cc3B270DfA78FDD9ddA7bC36325 |
| PoolZapper | One-transaction entry with ETH or USDG alone into a current pool; per-wallet ledger, no owner | 0x8934A298d3E59a632994ac254Dee19112127f2B7 |
| Range runner | Recenters current pool ranges through the controller; pre-approved shapes only, no other rights | 0x372f6aedaba9989186e52B1E9d2e7Ea5572aa6cF |
| DualPoolHook (first stack) | Uniswap's audited v4 hook, deployed unmodified | 0x127B3f3b7769f659C5eDBfF8b4005443f19FAAc0 |
| AllowlistedFactory (first stack) | Uniswap's factory pattern; creates every Twofold pool | 0x92cbCe5d1f5b7018b98bE81a8B9d010B547F0c85 |
| OperatorControllerV2 (first stack) | Owns the hook; opens and bootstraps pools, harvests gain above basis to the staking vault, within contract-enforced bounds | 0xc7295643EC5414DE243e3F9810Eb28F85e5d9ABb |
| VaultAllowlist (first stack) | Names the exact vault addresses pools may use | 0xe44C0d41A1aFbF7234492bb7a3F745246c351C42 |
| Registry (first stack) | On-chain check that a pool is genuine | 0x1b66DD14C9281A18E696dbdb40cFB5070842c0C2 |
| StakingVaultV2 | Vault 1, retired: no new stake; unstake (1 hour cooldown) and claims stay open | 0x06E463fDa4BEb4aA096142E673240aB9719fB3A9 |
| TwoStakingUSDG | Vault 2: stake TWO, earn USDG; per-second stream, 7-day unstake cooldown, 400,000,000 TWO cap | 0x9CF18bB1dD9AfBF75B579Cc0C473B2975c16E9e3 |
| TwofoldToken | TWO, fixed supply, no mint, no owner | 0x2A4a33A2163D005d8E7f1D9aC08d14c98db288d5 |
| VoteToken | vTWO, wrap TWO 1:1 for voting power, unwrap any time, no owner | 0x5c02401e945d86FB7109EC77F358498D6DA05950 |
| PoolVoting | On-chain signaling votes on Twofold proposals, weighted by vTWO | 0x6FDcc4A912b0f7d73251b7a719Aa2943734fD6E7 |
| Safe | Multisig that proposes every owner change; holds no funds and cannot execute one on its own | 0xB3eAb283ee90eC5333935C3526EB61D741836D09 |
| TimelockController | Owns the allowlists, controllers and registries; every owner change queues in public for 24 hours before it can run | 0x055a4f9583790e929a309cb0146280b1589A46FE |
| PoolZapper (first stack) | One-transaction entry with ETH or USDG alone; per-wallet ledger, no owner | 0x2eF1C576797a51FB60B25d9f946D2562d2d2F9Fc |
| Range runner (first stack) | Recenters pool ranges through the controller; pre-approved shapes only, no other rights | 0x2Bd61C3364e3D8dD7454cC5f1C47324fc2ACE35d |
| PositionLocker | Permanent lock on the TWO/WETH genesis liquidity; fees claimable by anyone, no exit path | 0x485690D46e344127aa2EB45D8d9BAcbb5856D58b |
External addresses
| Contract | Address |
|---|---|
| Uniswap v4 PoolManager | 0x8366a39cc670b4001a1121b8f6a443a643e40951 |
| Uniswap v4 PositionManager, holds the locked genesis position NFT | 0x58daec3116aae6D93017bAAea7749052E8a04fA7 |
| WETH | 0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73 |
| Steakhouse USDG vault | 0xBeEff033F34C046626B8D0A041844C5d1A5409dd |
| USDG | 0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168 |