Getting started
What is NAV
NAV is a token with one Uniswap v4 pool, ETH/NAV, and a hook on that pool. The hook takes a fee in ether from every trade and keeps it in a treasury. The treasury is turned, a slice at a time, into three assets: staked ether (wstETH), bitcoin (WBTC) and gold (XAUt).
Anyone holding NAV can burn it and receive their share of the treasury: their tokens over all the tokens there are, of every asset, in kind. That share is the token's backing, and it only grows: trades add to the treasury, and a redemption takes exactly a share and destroys the tokens that held it.
NAV is its own measure: net asset value, what is behind each token. The Treasury tab shows it live.
Getting started
Buy and sell
NAV trades in its one Uniswap v4 pool, from the Uniswap app, any aggregator or any router. Nothing special is needed: no hook data, no allow-list. Every swap pays 2% of its ether side to the hook (1.5% treasury, 0.5% owner), in all four shapes: buying or selling, with the amount in or the amount out fixed.
For the first five minutes after the pool opened the fee started at 25% and fell to 2%. Everything above 2% went to the treasury.
Getting started
Redeem your share
Open the vault, choose how much of your NAV to redeem, and confirm. Or call the token directly:
NAV.redeem(amount, to, skip, message)
- Your
amount is burned first. Then the hook sends to exactly holding × amount / supplyBefore × 99% of wstETH, WBTC, XAUt and treasury ether.
skip leaves assets behind: bit 1 wstETH, 2 WBTC, 4 XAUt, 8 ether. Use it if one of them can't reach you; your share of it stays in the treasury for everyone else.
message is up to 280 bytes, written to the chain with the burn.
Nothing is priced in a redemption, so no oracle or market move can change what you get. Nobody can block it.
Getting started
Burn as a gift
NAV.burn(amount, message) destroys tokens and takes nothing. The treasury stays the same and there are fewer tokens, so every other token's backing rises. It is the purest way to say something on chain: a message that cost you exactly what it says it did.
Getting started
Move the treasury
allocate() turns up to 1 ETH of treasury ether into the asset furthest below its target. Anyone may call it, once a block, when at least 0.1 ETH is waiting. The caller is paid 0.2% of the slice, at most 0.004 ETH, enough to cover the gas at ordinary prices.
next() shows what it would do right now: the asset, the ether and the tip. The vault has a button for it.
Trading never waits on it. If nobody allocates, the ether simply waits in the treasury, where it is still counted and still redeemable.
Concepts
The treasury
The treasury is exactly what the hook holds: its wstETH, WBTC and XAUt balances, and its ether claims on the Uniswap PoolManager less what the owner is owed. There is no separate ledger that could disagree with the balances. The only number the hook keeps about money is ownerOwed.
That design choice is deliberate. Hook coins have died of two numbers drifting apart by rounding until a reserve could no longer pay what it promised. NAV has nothing to drift.
Concepts
The fee
The hook charges 2% of the ether side of every swap. When the ether amount is the one named in the swap (an exact-in buy or an exact-out sell) it is charged before the swap; otherwise after, on the ether that actually moved. Either way the swapper pays exactly 2% of the ether leg.
- 0.5% is owed to the owner, paid by
collect(), which anyone may call.
- 1.5% is the treasury's.
- During the five-minute opening, the fee above 2% is the treasury's too. The owner never earns more than 0.5%.
Concepts
The guard
A treasury that buys in public markets is a target: push the price up, let it buy, sell back. NAV only buys near where a market has been.
- Each route pool's tick is folded into a 15-minute time-weighted average, at most once a block. One sample never counts for more than 15 minutes of time.
- A buy is refused when the pool sits more than 60 ticks (0.6%) from its average, and its price limit stops it at 0.6% if it gets there.
- The check uses the average as it stood before this block's price entered it.
Moving a market for the occasion only gets that asset skipped. The slice goes to another asset, or waits.
Concepts
The helm
The helm decides what the next slice buys. It is a rule, not a mind:
- Each asset starts with a weight of 1. wstETH is ether, so it has no trend against ether and stays at 1.
- WBTC's and XAUt's weights move with their trend in ether: the 15-minute average against the 3-day average. A 10% rise lifts the weight to 1.5; a 10% fall cuts it to 0.5; never further.
- Targets are the weights over their sum, so no asset is ever targeted above 60%.
- The slice buys the open asset furthest below its target, counting the slice itself in the total.
Concepts
The floor
Because any holder can redeem, NAV's price has a floor near its backing. If the pool's price falls below what a token can redeem for, buying NAV and redeeming it is profitable, and that buying pushes the price back up. The 2% swap fee and the 1% redemption fee are the width of that band.
The floor rises with every trade. It does not fall when others leave: a redemption takes exactly its share and destroys the tokens that held it, and the 1% left behind raises everyone else's backing a little.
The floor is a floor in assets, not in dollars. If gold, bitcoin and ether fall, so does what NAV is backed by.
Concepts
The LP
NAV launched the standard way. The whole supply was minted to the deployer, who created ETH/NAV in the Uniswap app and put all of it in, one-sided, below the opening price, so no ether went in. The LP position NFT was then sent to 0x000000000000000000000000000000000000dEaD.
- Only the holder of a position's NFT can remove it. Nobody holds the dead address's key.
- Check it yourself:
ownerOf(id) on Uniswap's PositionManager. The Contracts tab reads it live.
- The hook binds exactly one pool: ETH/NAV at the launch fee tier, created by the owner's wallet. Every other pool that names it is refused.
Reference
Formulas
fee 2% of the ETH leg (25% → 2% linearly over the first 5 minutes)
owner 0.5% of the ETH leg, capped at the fee
treasury claims(ETH) − ownerOwed + wstETH, WBTC, XAUt balances
slice min(treasury ETH, 1 ETH) − tip when treasury ETH ≥ 0.1 ETH
tip min(slice × 0.2%, 0.004 ETH)
average a ← a + (tick − a)(1 − e^(−min(dt, 900)/τ)) τ = 900 s, 259 200 s
guard |spot − average₁₅ₘ| < 60 ticks; price limit = average ∓ 60
trend WBTC: −(avg₁₅ₘ − avg₃d) XAUt: (XAUt/USDT − ETH/USDT)(avg₁₅ₘ − avg₃d)
weight clamp(1 + trend / 1000 ticks, 0.5, 1.5); wstETH = 1
target weightᵢ / Σ weight
choose open asset with the largest target × (holdings + slice) − holding
redeem out = holding × amount / supplyBefore × 0.99 for each asset and ETH
Reference
Hook ABI
allocate() returns (uint8 asset, uint256 eth, uint256 got)
donate() payable
collect()
next() view returns (uint8 asset, uint256 slice, uint256 tip) // 255: nothing to buy now
holdings() view returns (uint256[4]) // wstETH, WBTC, XAUt, ETH
values() view returns (uint256[4]) // the same, in wei of ether
nav() view returns (uint256 total, uint256 perToken)
targets() view returns (uint256[3]) // millionths
references() view returns (int24[3] spot, int24[3] fast, int24[3] slow)
price() view returns (uint256) // ETH per whole NAV, in wei
feePips() view returns (uint256)
treasuryEth() view returns (uint256)
ownerOwed() view returns (uint256)
Reference
Token ABI
redeem(uint256 amount, address to, uint8 skip, string message)
burn(uint256 amount, string message)
transfer, transferFrom, approve, balanceOf, totalSupply, allowance // plain ERC-20
HOOK() view returns (address)
No owner, no mint, no pause, no tax inside the token. The fee lives in the pool's hook.
Reference
Events and errors
Redeemed(holder, to, amount, supplyBefore, skip, message) // token
Burned(holder, amount, message) // token
Allocated(asset, eth, got, tip, by) // hook
Paid(to, amount, supplyBefore, out[4]) // hook
Donated(from, eth) Collected(eth) Launched(poolId, openTick)
NothingToDo(pending) less than 0.1 ETH waiting
OncePerBlock an allocation already ran this block
NoRoute every market is outside its guard right now
Thin the gold leg could not take every dollar
TooLong a message over 280 bytes
WrongPool · NotOwner a pool the hook refuses to bind
Help
FAQ
Can the owner take the treasury?
No. The owner is paid 0.5% of volume through collect and has no other power. The only way anything leaves the treasury is a holder redeeming, or an allocation turning its ether into an asset it then holds.
Why is the price above the backing?
The backing is a floor, not a price. People can pay more for what they expect the treasury to become.
What if nobody calls allocate?
The ether waits in the treasury, counted and redeemable. The tip exists so that someone always will.
Can I redeem part of my NAV?
Yes, any amount.
Help
Risks
- Not audited. The contracts are tested on a fork of Ethereum mainnet against the live Uniswap, Lido, WBTC and XAUt contracts, including a fuzz of every action in random order and over ten thousand ether of churn. That is not an audit.
- The assets carry their issuers' risks. Lido can pause staking. WBTC's custodian can pause it. XAUt is an upgradeable Tether contract that can freeze addresses. A redemption can leave any of them behind.
- The backing moves with the assets. It is measured in gold, bitcoin and ether, not in dollars.
- Buying moves markets. Every allocation pays the route pools' fees and some price impact, bounded by the guard.
- The price can sit far above the backing. The floor protects against the price falling below what the treasury holds per token, not against paying more than that.
Help
Glossary
- backing
- The treasury divided by the supply: what one NAV can redeem for, before the 1%.
- slice
- One allocation, up to 1 ETH.
- helm
- The rule that sets each asset's target.
- guard
- The 0.6% band around a market's 15-minute average.
- route pool
- A Uniswap v4 pool the treasury buys in.
- tick
- Uniswap's price unit: one tick is 0.01%.
- skip
- The bits that leave an asset behind in a redemption.