OTF token economics
OTF is the protocol token, used for rewards and fee buybacks. Each fund issues its own shares, which represent a claim on that fund’s basket.
The active deployment runs on Robinhood Chain Testnet with the 15/135 ETH launch curve. See Deployment addresses for the current contracts.
Supply and allocation
OTFToken is an 18-decimal ERC-20 named Onchain Traded Funds with symbol OTF. Its constructor mints one billion OTF using ProtocolConstants.OTF_INITIAL_SUPPLY. It has no later mint, tax, blacklist, seizure, or upgrade function. Holders can burn their own OTF; burnFrom requires allowance.
The shared constant records the original issuance; the token exposes only totalSupply() for live supply after burns. The frontend’s issuance constant is generated from the same Solidity definition. The deployment script allocates every token and leaves the deployer with none:
| Destination | OTF | Use |
|---|---|---|
| Team market-cap vesting | 100,000,000 | Ten live-FDV milestones |
| V4 launch manager | 200,000,000 | Bootstrap and permanent liquidity |
| Cumulative rewards distributor | 700,000,000 | 650 million for depositors and 50 million for fund creators, published by multisig |
Canonical V4 launch
The launch manager creates one OTF/WETH Uniswap V4 pool with a fixed 0% LP fee and tick spacing 1. The pool starts at 0.000000015 WETH per OTF, a 15 ETH reference fully diluted valuation (FDV) against the original one-billion-token supply. At the price boundary just below 135 ETH reference FDV, the launch can graduate to permanent liquidity.
Anyone can initialize the launch by approving the manager to spend 200 million OTF and calling
initializeLaunch() from the same wallet. The call pulls the full amount from the caller, initializes
the pool, and creates bootstrap liquidity in one transaction. If any step fails, the transfer also
reverts. OTF already held by the manager does not reduce the caller’s funding requirement. The
deployment script approves exactly REQUIRED_OTF_BALANCE before calling initialization.
The launch has four phases:
| Phase | What happens |
|---|---|
NotInitialized | The bootstrap position has not been created. |
BootstrapActive | Users can buy and sell OTF within the launch price boundaries. |
GraduationReady | The pool has reached the exact final price. Further swaps revert until finalization. |
Graduated | The manager has replaced bootstrap liquidity with a permanently locked full-range position. Normal Uniswap trading resumes. |
Graduation depends on price, with no schedule or countdown. Launch reference FDV uses ProtocolConstants.OTF_INITIAL_SUPPLY, so burns do not change the launch targets and no token supply read is required for this calculation.
OTFLaunchRouter is the supported bootstrap route. It partially fills buys or sells at the boundaries, takes only the input used, and refunds unused native ETH. A purchase that reaches the final boundary also finalizes graduation after PoolManager returns control. Both steps succeed or the entire transaction reverts. Anyone can also call finalization separately once the pool is ready.
Ordinary Uniswap UI trades can succeed within the launch boundaries. Orders that cross a boundary revert because the standard router cannot supply the required price limit.
Finalization removes the bootstrap position and funds a permanent full-range position with the derived principal. Extra WETH stays locked in the manager and cannot enlarge the position. After the permanent mint succeeds, the manager burns its entire remaining OTF balance, normally about 2,582.6037 OTF plus any unsolicited OTF. The manager owns the permanent NFT and has no withdrawal or replacement function.
The exact prices and liquidity amounts account for V4 rounding. The pool price is exact at initialization, while each liquidity boundary comes from V4 TickMath:
| OTF/WETH ordering | Exact initialization sqrtPriceX96 | Bootstrap start tick and boundary | Final tick and boundary |
|---|---|---|---|
| OTF is currency0 | 9703428570912459262669889 | -180161 / 9703508046175219238931631 | -158188 / 29110022932210076965716350 |
| OTF is currency1 | 646895238060830617511325894307352 | 180161 / 646889939753375374376401562675059 | 158188 / 215633692560272871859121182412411 |
The initial price sits just outside the starting position boundary. The final boundary is the closest tick-derived OTF price below the 135 ETH target, at approximately 134.997562702653186573 ETH reference FDV.
Permanent liquidity is fixed at 18371007233046122951295. It pairs just under 50 million OTF with 6.749878135132658333 WETH. This is the greatest integer liquidity that stays within the 50 million OTF cap after V4 rounding.
Bootstrap liquidity is fixed at 27556748080852150400017 and uses approximately 149,997,417.3963 OTF from its 150 million cap. It is the smallest integer liquidity that returns the permanent position’s full WETH principal at graduation. Swap rounding adds 44 or 45 wei of WETH to a purchase that reaches the final boundary, depending on currency order. The security specification defines the rounding requirements.
The launch hook uses beforeInitialize, beforeAddLiquidity, and afterSwap. The afterSwap hook enforces the bootstrap price boundaries and marks GraduationReady only at the exact final sqrt price; tick equality alone is insufficient.
Team market-cap vesting
The team’s 100 million OTF allocation unlocks in ten steps. Each completed $1 million of live USD FDV unlocks 10 million OTF, up to the full allocation at $10 million. Values between milestones round down, and unlocked tokens cannot relock after a price or supply decline.
Only the current beneficiary can record a milestone by calling checkpoint() on TeamMarketCapVesting. The contract calculates live USD FDV from:
canonical OTF/WETH V4 spot price
× current ETH/USD oracle price
× OTF.totalSupply()The calculation handles either currency order with full-precision integer arithmetic. It uses the current spot price, which can be manipulated. Beneficiary-only checkpoints do not remove that risk. The ETH/USD answer must be positive, no older than maxOracleAge, and not from the future. Testnet uses a fixed $2,000 fake oracle; production requires an explicit oracle address.
Team allocation unlocks
10 million OTF per completed $1 million live-FDV milestone
View team milestone data
| Completed live FDV | Cumulative unlocked | Share of supply |
|---|---|---|
| $1M | 10M OTF | 1% |
| $2M | 20M OTF | 2% |
| $3M | 30M OTF | 3% |
| $4M | 40M OTF | 4% |
| $5M | 50M OTF | 5% |
| $6M | 60M OTF | 6% |
| $7M | 70M OTF | 7% |
| $8M | 80M OTF | 8% |
| $9M | 90M OTF | 9% |
| $10M | 100M OTF | 10% |
The beneficiary can claim unlocked tokens minus prior claims and nominate a successor. They can replace or cancel the nomination. Authority transfers only when the nominee accepts, preserving unlocked and claimed amounts.
The beneficiary is the contract’s OpenZeppelin owner(). Call transferOwnership(newOwner) to nominate a successor, transferOwnership(address(0)) to cancel, and acceptOwnership() from the nominee to complete the transfer. Ownership renunciation is disabled so unclaimed tokens cannot be stranded by abandoning the role.
Immutable fund fees
Each vault creator selects three rates at creation:
| Fee | Default in the application | Contract maximum |
|---|---|---|
| Annual creator expense | 0% | 10% / 1,000 bps |
| Mint | 0% | 2% / 200 bps |
| Redeem | 0% | 1% / 100 bps |
The rates and expense beneficiary cannot change. A mint fee increases the deposit needed for a requested share amount. A redeem fee reduces the basket returned. Annual expense increases share supply over time, reducing the backing per share.
The vault collects all three fees by issuing vault shares and records accrued annual expense at checkpoints. Redemptions by the configured collector and redemptions after shutdown have no redeem fee. Redemption previews take the share owner as an argument and use the same arithmetic as execution.
Holding OTF as an accounted vault constituent changes the division of fee shares, not the fee charged to the investor:
creator share = 50% + 40% × sqrt(min(accounted OTF, 10m OTF) / 10m OTF)
buyback share = 100% - creator share| Accounted OTF | Creator | Buyback and burn |
|---|---|---|
| 0 | 50% | 50% |
| 1 million | 62.64% | 37.36% |
| 2.5 million | 70% | 30% |
| 5 million | 78.28% | 21.72% |
| 10 million or more | 90% | 10% |
The contract rounds the creator’s percentage down to whole basis points. Mint and redeem creator portions also round down, leaving the remainder for buyback. Annual expense carries fractional split remainders between checkpoints so their frequency does not change the cumulative split.
The vault records accrued expense before accounted OTF changes. Direct donations do not affect the split. OTF held in the fund remains a constituent and is not burned merely because the fund holds it.
BuybackCollector receives both portions and records their exact share counts in a separate account for each factory-recognized vault. At settlement, it reads the vault’s immutable beneficiary.
Fee settlement and burn
Fee settlement converts the collected fund shares into WETH, pays the creator’s portion to the expense beneficiary, and uses the remainder to buy and burn OTF.
Only the expense beneficiary can start settlement. The collector first records accrued annual fees, then converts all pending creator and buyback shares through one of two routes:
- Sell the combined vault shares through approved adapters to canonical WETH.
- Redeem the shares and convert the returned constituents to canonical WETH.
The share-sale route may use intermediate tokens but must consume the exact pending balance and leave only WETH as transient output. The beneficiary supplies routes, minimum WETH and OTF outputs, and a deadline. The collector does not price assets or choose slippage limits.
The collector divides the WETH using the share counts recorded when fees accrued and rounds the beneficiary’s payment down.
Settlement, beneficiary payment, OTF purchase, and burn all succeed or all revert. Selling shares leaves them outstanding with buyers; redeeming burns them and removes their proportional backing.
The final swap uses only the canonical OTF/WETH V4 pool, enforces the deadline and minimum output, and burns every OTF purchased. Buybacks can execute during bootstrap or after graduation. The collector has no arbitrary-call, withdrawal, or rescue function.
Cumulative rewards and incentive emissions
MerkleRewardsDistributor receives 700 million OTF: 650 million for depositors and 50 million for fund creators, or 65% and 5% of the original supply. The publisher’s policy sets weekly budgets over 208 weeks (four years), then ends emissions. Actual allocations can be lower than these budgets.
The schedule, allocation split, eligibility rules, weight cap, and 10,000% depositor rewards APY cap below are publisher policy. The distributor enforces proof validity and cumulative claims. Its owner can publish an immediately active reward root with no delay or per-period limit, including one that allocates the entire remaining balance ahead of schedule. The owner has no function to withdraw reward principal.
The weekly target starts at 14 million OTF and declines by approximately 1.968% every week:
weeklyEmission(n) = 14,000,000 × 0.9803203^(n - 1)Each week uses the same 65-to-5 split:
depositorEmission(n) = weeklyEmission(n) × 13 / 14
creatorEmission(n) = weeklyEmission(n) - depositorEmission(n)Week 1 budgets 13 million OTF for depositors and 1 million OTF for creators.
n starts at 1. The rounded decay factor leaves a shortfall of about 425.05 OTF over 208 weeks. The shared schedule rounds each weekly decay down to 18-decimal OTF units for weeks 1–207 and budgets the remainder in week 208, approximately 229,144.55 OTF. Its budgets sum to exactly 650 million depositor OTF and 50 million creator OTF; this does not require allocating unused rewards.
| Checkpoint | Approximate weekly emission |
|---|---|
| Week 1 | 14.000 million OTF |
| Week 2 | 13.724 million OTF |
| Week 3 | 13.454 million OTF |
| Week 4 | 13.190 million OTF |
| Week 5 | 12.930 million OTF |
| Week 6 | 12.676 million OTF |
| Week 7 | 12.426 million OTF |
| Week 8 | 12.182 million OTF |
| 3 months, week 13 | 11.03 million OTF |
| 6 months, week 26 | 8.52 million OTF |
| 1 year, week 52 | 5.08 million OTF |
| 2 years, week 104 | 1.81 million OTF |
| 3 years, week 156 | 643,000 OTF |
| Week 208 | 229,000 OTF |
Cumulative incentive budgets
Scheduled depositor and fund creator budgets across 208 weeks
View cumulative checkpoint data
| Checkpoint | Depositors | Fund creators | Total |
|---|---|---|---|
| Start | 0 OTF | 0 OTF | 0 OTF |
| Week 13 | 150.42M OTF | 11.57M OTF | 161.99M OTF |
| Week 26 | 266.58M OTF | 20.51M OTF | 287.09M OTF |
| Week 52 | 425.58M OTF | 32.74M OTF | 458.32M OTF |
| Week 104 | 576.98M OTF | 44.38M OTF | 621.36M OTF |
| Week 156 | 630.84M OTF | 48.53M OTF | 679.37M OTF |
| Week 208 | 650M OTF | 50M OTF | 700M OTF |
Both buckets calculate each fund’s initial allowance using capped pro-rata weights:
cappedWeight(fund) = min(accounted OTF balance(fund), 10,000,000 OTF)
proportionalAllowance(fund) = bucketEmission × cappedWeight(fund) / sum(cappedWeight)Only funds with an accounted protocol OTF balance receive an allowance. Balances above 10 million OTF receive no extra weight. Direct OTF transfers that do not enter accounted balances add no weight. If the total weight is zero, no fund receives an allocation.
Each fund’s depositor rewards have a 10,000% APY maximum, calculated by compounding the weekly return over 52 weeks:
weeklyDepositorAllowance = min(
proportionalDepositorAllowance,
snapshot NAV USD × (101^(1/52) − 1) ÷ chosen OTF price USD
)The publisher supplies one positive weekly average OTF USD price and uses it across all funds. The chosen price values reward tokens; fund NAV stays at its recorded snapshot valuation. For example, a fund with $5,200 NAV and a chosen OTF price of $2 can receive at most 241.3058779198001168 OTF in weekly depositor rewards. A smaller proportional allowance lowers that limit further.
The tooling rounds the weekly rate down to 18 decimal places before calculating allowances, then rounds allowances and participant rewards down to 18-decimal OTF units. Zero NAV or zero OTF weight gives zero depositor rewards. Excess and rounding dust remain unallocated in the distributor, without redistribution or automatic rollover. Creator rewards keep their separate proportional allowance and are outside the depositor APY cap.
The Funds page shows the combined weekly rewards budget. Directory values, sorting, fund details, and the explanation dialog use the shared cap calculation with current prices. Missing valuation or reward data leaves an eligible fund’s estimate unavailable. These estimates do not determine claim entitlements. Published rewards use the selected weekly price, and later market movements can change realized returns.
Rewards accumulate across claims. If your published entitlement is 100 OTF and you have already claimed 40 OTF, your next valid claim pays 60 OTF.
Each standard-tree leaf binds that cumulative entitlement to a chain, distributor, and user. Anyone may submit its proof; payment goes to the named user. Invalid proofs, duplicate claims, and entitlements below the amount already claimed revert.
Prepare a weekly JSON input using this structure. The addresses, block, and price here are examples; supply the actual snapshot and choose the reward-token price for the week:
{
"week": 1,
"otfPriceUsd": "2",
"snapshot": {
"blockNumber": "100",
"blockHash": "0x0000000000000000000000000000000000000000000000000000000000000001",
"timestamp": "2026-09-11T00:00:00.000Z",
"fundAddresses": ["0x00000000000000000000000000000000000000f1"]
},
"funds": [{
"address": "0x00000000000000000000000000000000000000f1",
"accountedOtf": "10000000",
"navUsd": "5200",
"depositors": [
{ "address": "0x00000000000000000000000000000000000000a1", "amount": "1000" },
{ "address": "0x00000000000000000000000000000000000000b2", "amount": "3000" }
],
"creators": [
{ "address": "0x00000000000000000000000000000000000000c3", "amount": "100" }
]
}]
}snapshot.fundAddresses must contain the full factory roster at the snapshot block. Include each fund exactly once, including funds with zero weight or no proposed rewards. Amounts and USD values are unsigned decimal strings with at most 18 decimal places. Missing NAV, balances, or the chosen positive price blocks generation; the script does not fetch a replacement price.
Participant amount values are proposed weekly increments, not cumulative entitlements. The script reduces depositor increments proportionally if their total exceeds the fund’s allowance. In this example, it allocates 60.3264694799500292 OTF and 180.9794084398500876 OTF to the two depositors and preserves the creator’s 100 OTF. Creator increments above the proportional creator allowance are rejected. One account can receive rewards from multiple funds or both buckets; duplicate accounts within one fund’s bucket are rejected.
Generate an artifact with:
corepack pnpm rewards:tree -- \
--input <week.json> \
--output <artifact.json> \
--chain-id <id> \
--distributor <address>For week two onward, add --previous <previous-artifact.json>. Supply the artifact from the immediately preceding week, including weeks with no allocation. The script validates the previous root and cumulative totals, requires advancing snapshot references, and rejects gaps or identity mismatches. It preserves past recipients and adds this week’s rewards to their cumulative entitlements.
Outputs use the otf-weekly-rewards-v2 schema and record the chosen price, snapshot, per-fund allocations, and budget, allocated, unallocated, and cumulative totals. Fields ending in Raw contain integer 18-decimal OTF units. Empty cumulative allocations use a zero root and no entries.
Cumulative-only JSON and CSV inputs are no longer accepted. The output path must be new, so a rerun cannot overwrite an existing artifact. Review the output before publishing its root. The publisher must verify the source snapshot, full roster against the factory, participant eligibility, and that the previous artifact is the latest publication. The script validates supplied data; it does not fetch onchain snapshots or submit a root transaction.
Trusted inputs
- The reward-root publisher can allocate the distributor’s entire remaining balance through a valid root.
- Each expense beneficiary chooses routes, minimums, and deadlines for its own vault’s complete pending fee account.
- The ETH/USD oracle determines one input to live-FDV vesting.
- PoolManager, StateView, PositionManager, Universal Router, Permit2, WETH, adapters, and trading venues execute or report external state used by the protocol.
Production addresses must be supplied explicitly and use official Uniswap V4 deployments. The testnet mirror is accepted only when its runtime code matches the configured hashes.