ohmvault.xyz · Ethereum mainnet (1) · Technical paper

OHMVAULT: a token floored on OHM

Version 1.07 October 2026Pre-launch: design, constants and tests. Protocol addresses are added at launch.

OHMVAULT is an ERC-20 on Ethereum that trades in a single Uniswap v4 pool against OHM, the Olympus reserve currency. The whole genesis supply and an OHM seed go into that pool as full-range liquidity that no contract can remove. A hook takes 5% of every swap and adds part of it back to the locked position, so the OHM under the curve grows with volume. Supply is elastic but gated: new tokens are minted by a Ratchet only while OHM backing per token is above an up-only mark, in both OHM and dollar terms, at most 2% of supply per six-hour slot; and by a Bond that pays for every token it mints with OHM added to the locked position, never below live backing.

The protocol is SEMI v1 (semivault.xyz, Robinhood Chain, August 2026) moved to Ethereum and to a new collateral. Most of the code is unchanged. This paper describes every contract and constant, and spends most of its length on the parts that changed and why, using SEMI's on-chain history as the test set. The working ticker is OHMV.

1System overview

Nine contracts. None has an owner. Every privileged setter is a one-shot pointer that the launch script calls once, after which it reverts for every address, the deployer's included.

before/afterSwapseed LPprice()consumeMin()donateFloor(OHM)mint ΔSmintnotify(ΔS)60% of harvested OHMTraderwallet or botUniswap v4 pool · OHMV / OHMlpFee 0 · tickSpacing 60OhmUsdOracleChainlink feedsOHM/ETH × ETH/USDVaultLauncherseed positionno exitVaultHook5% skim · harvest() · donateFloor()reserves() · epochMin · TWAPOperationstreasury walletVaultRatchetpoke() per 6 h slottrailing markVaultBondOHM → locked LPvests 24 hVaultLensread-onlyVaultStakerpending → active → coolingVaultMinteronly mint gateVaultTokenERC-20 · OHMV
Figure 1. Contract graph. Solid edges are calls; dashed edges are value flows to the operations wallet and reads from Chainlink.
ContractRoleLinesMutable configuration
VaultTokenERC-20, 18 decimals; one gated mint path89minter, set once
VaultMinterThe only address the token accepts mints from; forwards for two callers54ratchet, bond, each set once
VaultLauncherOpens the pool and owns the seed position175none; launched = true
VaultHookv4 hook: 5% fee, launch minute, harvest, floor donations, backing oracle, TWAP454launcher, ratchet, each set once
VaultRatchetBacking-gated emissions on a fixed 6 h grid, OHM and USD marks205none
VaultStakerReceives emissions; pending, active and cooling stake197ratchet, set once
VaultBondOHM in, locked LP up, discounted OHMV out over 24 h189none
OhmUsdOracleChainlink OHM/ETH × ETH/USD with staleness limits64none
VaultLensOne-call proof-of-reserves view79none

The test suite has 32 unit and fuzz tests against a local PoolManager with a 9-decimal mock OHM and mock feeds, and one fork test that runs the full launch against the real mainnet PoolManager, OHM and Chainlink feeds. Fuzzing covers the two properties everything else rests on: a bond never lowers backing per token, and a mint never leaves live backing under the mark.

2The token

VaultToken is a minimal ERC-20 with no transfer hooks, no tax, no pause, no blacklist and no owner. Name, symbol and links are constructor arguments, so the final brand ships in the same bytecode the tests ran against and can't change afterwards. The constructor mints 10,000,000 tokens to the deployer. The only other mint path is mint(to, amount), callable only by the minter, which is set once to VaultMinter. VaultMinter accepts calls from exactly two contracts: VaultRatchet and VaultBond.

There is no burn function. Tokens sent to 0x…dEaD leave circulation but stay in totalSupply, and backing is always computed against totalSupply, so a burn never flatters the numbers.

3Launch and locked liquidity

The launch transaction

VaultLauncher.launch(ohmSeed) runs once, from the deployer, and does five things in one transaction:

  1. pulls the entire 10,000,000 tokens (POOL_SUPPLY) and the OHM seed from the deployer;
  2. initializes the OHMV/OHM pool with lpFee 0, tickSpacing 60 and VaultHook attached, priced exactly at the seed ratio;
  3. adds everything as one full-range position owned by the launcher, after shaving liq / 1,000,000 + 1 so v4's round-up on adds can never ask for more than it holds;
  4. calls VaultRatchet.poke(), which starts the 6-hour clock and seals both marks at the seed backing;
  5. emits FloorPoured.

The planned seed is $2,000 of OHM, about 100 OHM at $20. Launch price is then 10,000,000 / 100 = 100,000 OHMV per OHM, and the fully diluted value at launch equals the seed. There is no dev bag: the deployer holds 0 OHMV when launch returns, and the launch script checks it.

The launcher has no function that removes liquidity, and the hook's own compounded position has the same property. OHM leaves the pool only when someone sells OHMV into it.

Deployment order

scripts/launch-ohmvault.mjs sends 18 transactions from one wallet, in this order, writing each address to deployment-ohmvault.json as it goes so an interrupted run can be read back:

#TransactionNote
1–4VaultToken, VaultMinter, VaultStaker, OhmUsdOracleplain deploys; the token deploy is genesis
5VaultHook via the CREATE2 deployer 0x4e59…956Csalt mined so the address ends in flag bits 0x30C8
6–9VaultRatchet, VaultBond, VaultLauncher, VaultLensimmutable wiring in constructors
10–15minter.setRatchet, minter.setBond, token.setMinter, staker.setRatchet, hook.setRatchet, hook.setLauncherevery one-shot setter used up
16–17approve 10M OHMV and the OHM seed to the launcher
18launch(seed)pool opens; the launch minute starts

How SEMI launched, from the chain

SEMI's launch on Robinhood Chain is the reference run. From its Transfer and Ratchet logs:

EventBlockTime (UTC, 13 Aug 2026)
Genesis: 10M SEMI minted to the deployer35,772,94623:07:15
Launch: 10M SEMI and 2 MU into the pool, first poke, mark sealed at 0.2 µMU35,773,26523:07:47, 32 s after genesis
First buy, 459,615 SEMI, inside the launch minute35,773,2705 blocks after the launch transaction
Next buys23:08:14 (+27 s), three in one block at 23:08:39 (+52 s)
Steady buying begins as the fee reaches 5%from about 23:08:47 (+60 s)
First sells back into the pool23:08:52 and 23:09:04
First Ratchet mint36,216,07914 Aug 11:27, the second regular poke

Robinhood Chain makes a block roughly every tenth of a second; Ethereum makes one every 12 seconds. The launch minute is therefore five blocks long on Ethereum, and the fee each block pays is fixed in advance:

Seconds after launch01224364860+
Hook fee50%33.8%21.2%12.2%6.8%5%

A bot that lands in the launch block itself pays 50%, and while the fee is above 5% no single swap may take more than 10% of the pool's reserve. On Ethereum the 18 setup transactions take a few minutes, and the token contract is public from transaction 1. That gives no head start: there is no pool to trade in until transaction 18, and the hook refuses to initialize a pool for anyone but the launcher.

4VaultHook: the fee

The hook's address carries permission flags 0x30C8: beforeInitialize, afterInitialize, beforeSwap, afterSwap and beforeSwapReturnsDelta. The constructor checks its own address against these flags and reverts on a mismatch. beforeInitialize reverts unless the initializer is the launcher, so no other pool can be opened on this hook. afterInitialize stores startTime.

The skim

On every swap not made by the hook itself, beforeSwap computes the fee on the absolute specified amount and takes it in the specified currency:

Currency feeCur = (params.amountSpecified < 0) == params.zeroForOne ? key.currency0 : key.currency1;
uint256 fee = (absAmt * feeBps) / 10_000;
poolManager.take(feeCur, address(this), fee);
return (beforeSwap.selector, toBeforeSwapDelta(int128(int256(fee)), 0), 0);

Returning the fee as the specified delta makes the swapper owe it. For exact-input swaps the fee is on the input: OHMV on sells, OHM on buys. The hook accrues fees in both tokens until a harvest.

The launch minute

For 60 seconds after startTime the rate falls quadratically from 50% to 5%, front-loaded:

feeBps(t) = 500 + 4500 · ((60 − t) / 60)² for 0 ≤ t < 60 feeBps(t) = 500 for t ≥ 60
0%5%16.25%33.8%50%0 s12 s30 s45 s60 s75 shook feeseconds since the pool opened50%33.8%16.25%5% from here on
Figure 2. Hook fee during the launch minute. On Ethereum this is five blocks.

The hook's own swaps pay 5% too

Uniswap v4 does not run a hook's callbacks for swaps the hook makes itself. In SEMI v1 that made the hook's own swaps free. Here _swap sends 95% of the intended amount into the pool and keeps 5% back as fees, so harvest compounds and the sold half of every bond pay the same skim as a trader. That fee stays in the hook and is split at the next harvest like any other.

Each of the hook's own swaps is also bounded to a price move of about 8% (√price × 0.9591 or × 1.0392). On a pool where every leg pays 5%, a sandwich around a move smaller than 8% costs the attacker more in skims than the move is worth. An oversized harvest fills partially and the rest waits for the next one; an oversized donation is refunded.

Harvest

harvest() is permissionless. Inside one unlock it sells the hook's whole OHMV balance for OHM, then splits the hook's OHM 40/60:

Hook balancesOHMV fees + OHM feesSell all OHMV → OHMpays 5% · ±8% price boundohmBaleverything now in OHM40% · _compound()sell 1/1.95, pays 5%Full-range LPowner = hook, salt 060% · TREASURYOHM transfer_observe()post-harvest reserve
Figure 3. Harvest. Both of the hook's internal swaps pay the 5% skim and respect the 8% bound.
External swapamountSpecified = 100VaultHook skim5.00 (500 bps)Locked LP, owned by the hook2.00 · COMPOUND_BPS 4000TREASURY (operations)3.00 · remainder
Figure 4. Where a 5% skim on a swap of 100 ends up: 2 in the locked pool, 3 to operations.

_compound(ohmAmt) sells 1/1.95 of the OHM for OHMV, so that after the 5% skim on the sold part the two halves match, and adds both as full-range liquidity owned by the hook. There is no burn slice: SEMI v1 sent 20% of each harvest to a GIWA buy-and-burn pointer, which was in practice the operations wallet. On Ethereum that slice is simply part of the 60%.

donateFloor

donateFloor(ohmAmt) is permissionless. It pulls OHM from the caller and runs only the compounding step: no treasury cut. It returns what it placed and refunds what the 8% bound left unplaced. Because the sold half pays 5%, the share of a donation that reaches the pool is 1 − 0.05 / 1.95 ≈ 97.44% (donationNetBps()). VaultBond delivers all bonded OHM through this function.

5VaultHook: the backing oracle

Reserves from protocol liquidity only

reserves() reads the liquidity of exactly two positions with getPositionInfo (launcher and hook, full range, salt 0) and converts it to token amounts at the current price. OHM sent to the hook or pool directly and any third-party liquidity are invisible to it. Nobody can park liquidity to force a mint and pull it afterwards.

Price never sits under live backing

For a full-range constant-product position, price in OHM per OHMV is R_ohm / R_tok and live backing is R_ohm / S. Their ratio is S / R_tok: total supply over the tokens held by the protocol position. Since that position holds part of the supply, the ratio is never below 1. If every holder sold everything, the price would end exactly at backing. Backing itself moves with trading, though: buys add OHM to the pool and sells take it out.

The minimum over the window

The hook records epochMin = min(epochMin, ohmReserve()) before every external swap, after every external swap, and after every harvest or donation. consumeMin(), callable only by the Ratchet, returns that minimum and resets it. SEMI v1 sampled only before swaps, so a window's last trade was never seen until the next window; sampling after each swap as well closes that.

slot nslot n+1slot n+2OHM reserve (schematic)one-block spike: not in the minimumconsumeMin() returns thisohmReserve() before and after each swapepochMin
Figure 5. Schematic. A reserve spike that reverts inside the window does not raise the minimum. Backing counts only if it held at every observation.

TWAP

Each observation also updates a time-weighted price accumulator and writes at most one entry per block into a 32-slot ring. twapTokenPerOhm() returns the average OHMV-per-OHM over the last 10 minutes, falling back to the oldest entry if the ring is younger. The bond uses it (section 9).

6VaultRatchet: emissions

Backing ratio and marks, scaled by 10³⁶ because OHM has 9 decimals (at 10¹⁸, one token's backing would read about 10⁴ and move in 0.01% steps):

fbr = R_min · 10³⁶ / S R_min = hook.consumeMin() usdFbr = fbr · usdPerOhm / 10¹⁸ usdPerOhm from Chainlink mint iff fbr > mark and usdFbr > usdMark and staker.totalStaked() > 0 ΔS = min( ¾ · S · (fbr − mark) / mark , 2% · S )

A fixed clock

The launch poke sets genesis. Slots are 6 hours long and counted from it. poke() is permissionless and pays no reward; it reverts until a slot boundary has passed since the last settlement, then settles once, however many slots were missed. In SEMI v1 the six hours ran from the previous poke, so whoever poked chose which observations fell into the window. Here the boundaries are fixed and a late poke changes nothing but gas.

yesyesyesyesyesyesnonononononopoke()anyonehook.ohmReserve() > 0 ?genesis set ?a 6 h slot closed since the last one ?rMin = hook.consumeMin()fbr = rMin · 1e36 / SChainlink fresh ?fbr > mark and usdFbr > usdMark ?staker.totalStaked() > 0 ?mint ΔS to VaultStakermark = trailing mark · notify(ΔS)returnno state changeseal both marksMarkInitializedrevert"epoch not closed"notify(0)OracleDownnotify(0)NoNewHighmarks = observedBankedNoStakersThe first poke runs insideVaultLauncher.launch().ΔS = min( ¾ · S · (fbr / mark − 1), 2% · S )
Figure 6. Every path through poke(). Each path that reads the oracle also calls staker.notify, which advances the staker's epoch.

Two marks: OHM and dollars

The OHM mark alone has one blind spot. If OHM crashes against the dollar, arbitrageurs sell cheap OHM into every OHM pool, including this one; OHM backing per token rises while the dollar value of the floor falls. The Ratchet therefore keeps a second mark in USD per token and needs a new reading above both. An OHM crash with arbitrage inflow raises the OHM reading but not the dollar one: no mint. An OHM pump with no trading raises the dollar reading but not the OHM one: no mint. A stale or broken feed means no mint and both marks untouched; the slot still ticks so stakers keep activating.

The trailing mark

In SEMI v1 the mark was set to the post-mint backing after every mint. That is harmless for small gains. For large ones it threw most of the gain away: the 2% cap paid a sliver, and the mark still jumped to the top. OHMVAULT moves the mark by the part of the gain the mint actually paid for, and lets it trail the post-mint backing by at most 20%:

paidFor = mark · (1 + ΔS / (¾ · S)) level this mint paid for carried = paidFor · S / (S + ΔS) same level, post-mint units trailed = R_min · 10³⁶ / (S + ΔS) · (1 − 20%) mark := min( post-mint backing , max(carried, trailed) )

When the cap doesn't bind, carried equals the post-mint backing exactly and the rule is v1's. When it binds, the unpaid part of the gain stays in front of the mark and is paid at up to 2% a slot for as long as the backing holds. The three invariants of v1 still hold: nothing mints unless backing is above the mark; the mark never goes down; after a mint, live backing is at or above the mark.

0%2%10%20%30%40%0%2.67%10%20%28%40%50%60%g = observed backing ÷ mark − 1cap bindstrail binds: mark = 80% of post-mint backingmark rise, SEMI v1mark rise, OHMVAULT (20% trail)ΔS, % of supply
Figure 7. One mint, as a function of the observed gain over the mark. The mint size is the same in both designs. What differs is how far the mark moves: in v1 it follows the whole gain; with the trailing mark it moves 0.65% per capped mint until the 20% trail takes over at a gain of about 28%.
02468101214+0%+20%+40%+60%+80%+100%6-hour rounds that mintjump in backing that then holds flat+50%: 10 rounds, 20.6% of supplyrounds paid, SEMI v1rounds paid, OHMVAULT
Figure 8. A jump in backing that then holds flat. v1 pays one slot for any gain above 2.67%. The trailing mark pays 7 slots for a held +20% (14.7% of supply) and 10 slots for +50% or more (20.6%). The run is limited by the trail, not by the size of the jump, so a giant pump cannot turn into weeks of printing.

When there are no stakers, the whole gain moves both marks and nothing is minted, so the first staker can't collect a backlog. This is unchanged from v1.

7The trailing mark on SEMI's history

SEMI's Ratchet was poked 146 times after initialization between 14 August and 6 October 2026. It minted 27 times, 12,143,846 SEMI in total, and never after 3 September. Bonds minted 59.1M in the same period: 73% of all SEMI ever created came from bonding, 15% from emissions.

The question for OHMVAULT was how to get more paying slots without changing what the mint is backed by. The test: take SEMI's real window-minimum backing at every poke and its real bond mints, keep both fixed, and replay only the mark rule. Supply in the replay grows by the extra emissions, which dilutes the backing reading the way it would have.

Mark ruleSlots that mintedEmittedShare of final supply
SEMI v1, on chain2712.1M14.9%
SEMI v1 rule, replayed (check)2312.2M13.0%
10% trail3420.8M20.3%
20% trail (OHMVAULT)4429.5M26.6%
30% trail5644.1M35.2%

The replayed v1 rule lands within 0.2% of the real emissions, with four fewer paying slots than the chain, which is close enough to trust the comparison. At 20%, emissions are 2.4× v1's and the number of paying slots roughly doubles. 20% was chosen over 30% because the 30% run kept printing into the first day of SEMI's September drawdown.

02468101215 Aug22 Aug29 Aug5 Sept12 Sept19 Sept26 Sept3 OctµMU per SEMIlast replayed mintwindow-minimum backing (v1 tape)v1 mark, on chaintrailing mark, replayed
Figure 9. SEMI's real backing tape with the v1 mark (on chain) and the trailing mark (replayed). The trailing mark climbs in steps behind the backing instead of jumping to each peak.
0M10M20M30M40M50M15 Aug22 Aug29 Aug5 Sept12 Sept19 Sept26 Sept3 Octcumulative Ratchet emissions29.5M12.1Mv1, on chain10% trail20% trail (OHMVAULT)30% trail
Figure 10. Cumulative emissions, v1 on chain against three trail settings.

What no mark rule fixes: from 3 September SEMI's backing fell about 65% and never came back. Any rule that keeps the promise "never mint below an up-only mark" stops paying in that situation, and the trailing mark does too. It extends the payout of every rise that holds; it does not pay through a bear market. Getting emissions there would mean letting the mark fall, which is the one thing this design will not do.

8VaultStaker

An accumulator without rebasing. The Ratchet mints ΔS to the staker and calls notify(ΔS):

accRewardPerShare += ΔS · 10¹⁸ / totalActive (if ΔS > 0 and totalActive > 0) epochCount += 1

Entry: one slot

New stake is pending and earns nothing until the next tick. Staking one block before a poke and leaving after it earns nothing.

In SEMI v1 a pending stake became active only when its owner next touched the contract. A holder who staked and walked away was invisible to the Ratchet, which then saw "no stakers" and banked the gain instead of minting it. Here the tick itself activates everything staked in the closed slot (pendingTotal[epoch]), and each account settles lazily from the accumulator value recorded at that tick (accAtEpoch). No keeper and no loop over users.

Exit: one slot

unstake(amount) draws from active stake only, and not within 6 hours of the account's last stake. It does not pay out. The amount stops earning immediately and moves into cooling with coolingEnds = now + 6 h. withdraw() pays it out once that time has passed. Unstaking again while a cooldown runs adds to it and restarts the 6 hours on the total. Rewards are accounted separately: claim() works at any time, cooldown or not, and can never touch principal.

tick ntick n+1tick n+2tick n+3tick n+4stake(x)pendingactive: shares ΔS at n+2, n+3 …unstake(x)cooling 6 h, earns 0withdraw() opensΔS(n+1) excludes xΔS(n+3) excludes x
Figure 11. One stake from entry to exit. It waits one slot to start earning and six hours to leave, and earns nothing in either wait.

The exit wait does two jobs. It makes staking a commitment of at least two slots, so rewards go to people who stay, and it slows a run on the exit: a staker who wants out in a panic is out six hours later, not in the same block as everyone else.

9VaultBond

bond(ohmIn, minTokenOut) pulls OHM, routes it through donateFloor, and mints OHMV through VaultMinter, vesting linearly over 24 hours:

p = min( 10-min TWAP , spot ) OHMV per OHM marketOut = ohmIn · p · 1.20 20% discount fbrCap = ohmIn · S / R_ohm · (1 − 10⁻⁶) live backing quoted = min(marketOut, fbrCap) fixed first tokenOut = quoted · placed / ohmIn placed = OHM in the floor

The gate defends live backing

In SEMI v1 the gate was ohmIn / mark. After SEMI's September drawdown the mark sat 2.8× above live backing, so every bond was capped far below the market and bonding was dead until a 137% recovery. A bond only needs to leave backing per token where it was to be non-dilutive, and ohmIn / live backing is exactly that. The marks now gate emissions only. The 1 ppm shave keeps v4's liquidity rounding from ever tipping a capped bond a fraction under par; the fuzz test checks it.

gate binds-5%0%+5%+10%+15%+20%+25%1×1.2×1.5×2×2.5×pool premium: spot price ÷ live backing (never below 1)−2.6% at launch+16.9% from 1.2×bond result vs buying the same OHM at spot
Figure 12. What a bond returns against buying the same OHM's worth at spot, net of the skim on the sold half. Because price never sits under live backing, the worst case is −2.6%, at launch. Above a 1.2× premium the full 20% applies (+16.9% net). SEMI v1's gate, on the mark, returned −49% on 5 October.

Quote, partial fills, skim

The price is the lower of the 10-minute TWAP and spot, so dumping right before a bond does not improve it. The quote and the gate are fixed before the donation runs. The hook places what its 8% bound allows and refunds the rest in the same transaction; OHMV is minted only against OHM that reached the floor. The sold half pays the pool's 5%, about 2.56% of the bond, which stays in the hook as fees. quote() shows the result net of that skim.

A new bond pays out whatever has vested, then puts the unvested remainder and the new amount on a fresh 24-hour schedule. There is no per-slot bond cap.

10OHM and its price

OHM v2 (0x64aa…f1D5, 9 decimals) is the token of Olympus, on Ethereum since 2021. Olympus backs it with a treasury the protocol owns and runs Range Bound Stability: standing treasury orders that buy OHM below a lower band and sell above an upper band. Holders can also borrow against staked OHM through Cooler Loans instead of selling. The point for OHMVAULT is that OHM has a defended price; a floor made of it moves less with the market than a floor made of ETH would. Bands, backing and treasury figures change and are published by Olympus; check them there.

The OHM in OHMVAULT's pool is plain OHM, not staked gOHM, and earns no Olympus yield. It grows from fees and bonds.

OhmUsdOracle

usdPerOhm = ohmEth · ethUsd · 10¹⁸ / 10^(ohmEthDecimals + ethUsdDecimals) ok = both answers > 0 and OHM/ETH updated within 26 h and ETH/USD within 2 h

OHM/ETH has a 24-hour heartbeat and a 2% deviation trigger; ETH/USD has a 1-hour heartbeat and 0.5%. The limits sit two hours past the OHM heartbeat and one hour past the ETH one. A reading that fails any check returns ok = false and the Ratchet skips the mint; it never reverts the poke.

11What changed from SEMI v1

ChangeWhy
Pair asset is OHM (9 dp) on Ethereum instead of MU on Robinhood ChainA defended collateral on the main chain, with deep OHM/ETH liquidity for routing in and out.
Harvest 40% floor / 60% operations; no burn slicev1's 20% GIWA burn went to the operations wallet anyway, and there is no GIWA on Ethereum.
The hook's own swaps pay 5%v4 skips hook callbacks for the hook's swaps, so v1's compounds and bonds traded free. Now every leg pays.
Hook's own swaps bounded to ~8% (v1: 2× / ½×)No sub-8% move can be sandwiched profitably through two 5% skims.
Reserves sampled after every swap as well as before (flags 0x30C8)v1 never saw a window's closing reserve.
Fixed 6 h slots from launchv1 let the poker choose the window.
USD mark next to the OHM markBlocks the "collateral crashes, arbitrage OHM flows in, mint" path.
Trailing mark (20%)v1 paid one slot per pump. Replayed on v1's tape: 44 slots and 29.5M instead of 27 and 12.1M.
Backing scaled 10³⁶OHM's 9 decimals made 10¹⁸ coarse.
Passive stakers activate at the tickv1 banked gains when holders had staked and walked away.
6 h unstake cooldownOne slot to enter, one to leave.
Bond gate on live backingv1's mark gate shut bonding for weeks after a drawdown.
Bond quote = min(TWAP, spot); partial fills with refundA dump before bonding doesn't help; large bonds are safe under the 8% bound.
Removed: FloorWall, router fee tiers, launchpad, The Fab, SemiScapeNot part of this launch.

Everything else is v1's logic: the 5% skim and launch minute, the protocol-only reserve reading, the minimum over the window, α = ¾, the 2% cap, banking when nobody is staked, the 20% discount and 24-hour vest, 10M supply all in the pool, one-shot setters and no owner.

12Read paths

VaultLens.snapshot() returns in one call: supply, OHM and OHMV in the protocol positions, both marks, live backing, spot and TWAP, Chainlink's USD price and whether it's fresh, lifetime emissions, the current and last settled slot, whether a poke is due, the current fee, and what 1 OHM would bond for right now with the gate flag. Anyone can re-derive every number the site shows from that one read. VaultStaker.earned(u), stakeOf(u), cooling(u) and coolingEnds(u) cover a single account; VaultBond.claimable(u) and locked(u) cover its bond.

13Trust model and risks

What nobody can do

Remove the locked liquidity. Mint outside the two gates. Change the fee, the split, α, the cap, the trail, the discount, the vest or the cooldown. Pause anything. Point any contract somewhere else. Each of these needs a function that doesn't exist or a one-shot setter that has already been used.

What the team controls

The operations wallet, which receives 60% of harvested fees (3% of volume). It is the team's income and pays for development, infrastructure and promotion. Nothing in the mechanics depends on it.

Risks

  • OHM. Olympus is governed by its DAO, which can mint OHM, move the bands and change the treasury. OHMVAULT has no say. If OHM fails, the floor under OHMV fails with it.
  • Oracle. Chainlink can go stale or be wrong. Stale halts minting; wrong-but-fresh could let one slot mint against a bad dollar reading, still bounded by the OHM mark and the 2% cap.
  • More emissions. The trailing mark pays more and for longer. Stakers who sell their rewards add selling pressure during the run. The run is bounded by the 20% trail, never by the size of a pump.
  • Bond supply. On SEMI, bonds created 73% of supply. With the gate on live backing bonding stays open in drawdowns, so supply can grow faster than in v1. Each bond is non-dilutive to backing per token by construction; it can still dilute price.
  • Liquidity and routing. The pool starts at $2,000 of OHM. The Uniswap app routes hooked pools only once Uniswap allowlists the hook. Until then buyers come through the site, bots that support v4 hooks, or direct pool calls.
  • Code. 32 tests, fuzzing and a fork rehearsal are not an audit. v1's logic ran for two months on Robinhood Chain with real money; the changed parts have not.
  • Keeper. poke() and harvest() need someone to send them. Both are permissionless, so a dead keeper delays but never locks anything.

14Address registry

NameAddress
OHM v2 (Olympus)0x64aa3364F17a4D01c6f1751Fd97C2BD3D7e7f1D5
Uniswap v4 PoolManager0x000000000004444c5dc75cB358380D2e3dE08A90
Chainlink OHM/ETH0x9a72298ae3886221820B1c878d12D872087D3a23
Chainlink ETH/USD0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419
CREATE2 deployer0x4e59b44847b379578588920cA78FbF26c0B4956C
Operations wallet (TREASURY)0x63888d25934504CfcFb83aCc3f9af90B3e30dDce
VaultToken · Minter · Hook · Launcher · Ratchet · Staker · Bond · Oracle · Lenspublished here, on the site and on X at launch

All nine protocol contracts will be verified on Etherscan with exact-match source.