INDEXon docs

INDEXon keeps a portfolio of Ondo tokenized stocks and ETFs at the weights you choose, and trades it back to target through Uniswap when prices pull it off.

What you get

  • Ondo stocks and ETFs on Ethereum. Any Ondo token with a Uniswap USDC pool (NVDAon, SPYon, TSLAon, QQQon, AAPLon and more), plus USDC as cash. Most Ondo tokens have no Uniswap pool yet; more become available as liquidity is added.
  • Your weights, your band. Whole-percent weights that add up to 100, and a drift band of 3%, 5% or 10%.
  • Hands-off or hands-on. Let the keeper rebalance when a holding leaves its band, or press Rebalance yourself, for free.
  • Custody stays with your wallet. Only your wallet can deposit, change the mix or withdraw, any time, without the keeper.

The parts

Fig. 1Everything meets in one vault. Your wallet moves funds in and out; the keeper may only call rebalance(), inside limits the vault enforces; trades fill on Uniswap and must land within 2% of an onchain price.
PartWhat it does
IndexonVaultOne contract holding every portfolio, with per-portfolio balances, weights and band.
Uniswap v4 and v3Each trade routes to the deepest USDC pool for that asset. v4 legs share one PoolManager unlock.
ChainlinkOndo price feeds bound fills onchain for the assets that have one.
KeeperA bot that checks drift every 5 minutes, around the clock, and rebalances opted-in portfolios. Anyone can run one.

Who it's for

Ondo tokenized stocks are offered only outside the United States. INDEXon is not available to US persons, and you need to be allowed to hold Ondo tokens where you live.

Start with How it works.

How it works

A portfolio is a set of target weights, a drift band, and the tokens that currently fill it.

  1. 01CreateWeights, band, keeper on or off
  2. 02DepositUSDC in, the mix bought in one tx
  3. 03DriftPrices pull weights off target
  4. 04RebalanceSells, then buys, back to target
  5. 05WithdrawAs tokens or USDC, any time
Fig. 2A portfolio's life. Drift and rebalance repeat for as long as you hold it.

1. Create a portfolio

Pick up to 24 Ondo assets and give each a whole-percent weight. You can keep part of the portfolio in USDC as cash; cash is never traded away. Weights must add up to 100%.

Choose a drift band: how far a holding may move away from its target, in percentage points of the portfolio, before a rebalance is due. With a 5% band, a holding targeted at 30% can range from 25% to 35%.

Decide whether the keeper may rebalance for you. You can change this later.

2. Deposit

Deposit USDC and INDEXon buys the mix in the same transaction: the app splits your deposit by weight, quotes every leg on Uniswap, and sends the trades with a minimum output on each. You can also keep the deposit as cash, or move in Ondo tokens you already hold.

3. Drift

Prices move every trading day, so the actual weights drift from the targets. The app shows this as the level line: each holding's distance from its target, with its band shaded. A bar past the band turns red.

Fig. 3One holding with a 30% target and a ±5% band. It may wander between 25% and 35%; past 35% a rebalance is due, and one transaction brings it back to 30%.

4. Rebalance

When any holding leaves its band, a rebalance:

  1. sells what is overweight into USDC,
  2. then buys what is underweight with that USDC,

in a single transaction. Sells always come before buys, which the contract enforces. Trades smaller than $5 are skipped as dust.

One transactionrebalance(portfolio, trades)

1 Sell what is over

  • NVDAonUSDC$1,008

2 Buy what is under

  • USDCSPYon$353
  • USDCTSLAon$202
  • USDCAAPLon$121
  • QQQon$3, under $5: skipped
Fig. 4An example rebalance: NVDA ran 10 points over target. The sells fill the USDC the buys spend, all in one transaction; anything under $5 is skipped.

The keeper rebalances opted-in portfolios at most once an hour. You can rebalance your own portfolio at any time; it costs only gas and pool fees.

5. Withdraw

Withdraw 25%, 50% or 100%:

  • As tokens: you receive that share of every holding.
  • As USDC: the app sells that share of each holding and sends you USDC. Any holding with no usable pool is sent to you as the token.

Withdrawals never need the keeper, and they work even while the vault is paused for new activity.

Assets and routing

The vault can list every Ondo tokenized stock and ETF on Ethereum, but a portfolio can only buy what trades on Uniswap. Only some Ondo tokens have a usable USDC pool, and fewer can fill a $250 trade within 3% price impact; the rest have no USDC pool, or only junk pools with 10–90% fees that the vault refuses. As liquidity is added, more tokens qualify.

Where the liquidity is

Ondo tokens trade against USDC on both Uniswap v3 and v4. For many assets the deepest pool is on v3 (for example NVDAon, SPYon and TSLAon at the time of writing); for others it is on v4 (QQQon's 0.65% pool). When you pick assets for a portfolio, the app rates each one:

RatingMeaning
DeepA $1,000 buy moves the price less than 0.5%.
FairLess than 2%.
ThinMore than 2%, or the quote failed. Size weights carefully.
No routeNo USDC pool can fill $250 within 3%. Can't be added.

How a trade is routed

For each leg, the app quotes every eligible USDC pool for that asset (all v3 fee tiers and every v4 pool) and picks the one that returns the most. The vault then checks the route itself:

Leg

Buy NVDAon with $1,000 USDC

  • v30.3%canonical pool4.3121 NVDAon best
  • v40.65%no hook4.2967 NVDAon
  • v31%canonical pool4.2825 NVDAon
  • v30.05%no liquidity–
  • v490%fee over the 1% cap– refused
Fig. 5Illustrative quotes for one leg. The app quotes every eligible USDC pool and picks the best output; the vault itself refuses pools it doesn't allow, like v4 pools charging junk fees.
  • v4: the PoolKey must pair the asset with USDC, use a static fee of at most 1%, and either have no hook or a hook the vault has approved. This refuses the junk pools charging 80–90% fees that exist for some Ondo tokens.
  • v3: the pool must be the canonical Uniswap v3 pool for that pair and fee tier.

One unlock for every v4 leg

When a rebalance includes v4 legs, the vault opens a single PoolManager.unlock, runs every swap inside it, and settles each token once at the end (v4 flash accounting). v3 legs in the same rebalance swap inside that call too. The result: one transaction, one settlement per currency, however many v4 legs there are.

Prices

The app values holdings at the Chainlink Ondo feed when one exists and is fresh, and otherwise at the mid price of the asset's best pool. Chainlink publishes Ondo feeds on Ethereum for SPYon, QQQon, TSLAon, IAUon, SGOVon, BILon, USFRon, FLHYon and STRCon. For keeper trades the vault needs an onchain price for every holding: the Chainlink feed when fresh, otherwise the asset's 30-minute Uniswap v3 average price, and every keeper fill must land within 2% of it.

Fees

ActionINDEXon fee
Create a portfolio, change the mix, deposit, withdrawNone (gas only)
Rebalance yourselfNone (gas only)
Keeper rebalance0.1% of the traded amount + 0.50 USDC

Every trade also pays the Uniswap pool's fee (typically 0.3%–1% for Ondo pairs), and some price impact in thin pools.

Keeper rebalance, $1,000 traded$4.500.45% of the traded amount
  • Uniswap pool fees0.3% of $1,000$3.00
  • Keeper fee0.1% of $1,000$1.00
  • Keeper gasflat$0.50
  • Rebalance yourselfpool fees only, plus gas$3.00
Fig. 6A keeper rebalance that trades $1,000 through 0.3% pools. Rebalance yourself and only the pool fees (and gas) remain.

Hard caps

The contract owner can change the keeper fees, but never above limits written into the contract:

  • at most 0.5% of the traded amount, and
  • at most 5 USDC flat per keeper rebalance.

Keeper fees are taken from the portfolio's USDC after the trades. The 0.50 USDC goes to the keeper to cover gas; the percentage goes to the INDEXon treasury.

Keeper and trust

What the keeper does

The keeper is a bot that runs every 5 minutes, around the clock. For each portfolio that opted in, it:

  1. values every holding the same way the vault will (Chainlink where fresh, else the asset's 30-minute Uniswap v3 average price), and cross-checks against an independent off-chain price,
  2. skips the portfolio if nothing is past its band, if it was rebalanced in the last hour, or if any holding has no onchain price reference,
  3. plans sells and buys back to target and quotes each leg, using only routes the vault has approved,
  4. simulates the transaction, then sends it privately through Flashbots Protect so it can't be sandwiched.

What the contract enforces on the keeper

The keeper is not a custodian, and the vault doesn't simply trust it. A keeper rebalance:

  • trades only inside the portfolio it names, and only if that portfolio opted in, at most once per cooldown (1 hour minimum, written into the contract),
  • only through approved routes: specific Uniswap pools the vault lists, never a pool the keeper creates,
  • only when the portfolio is actually past its band, valued onchain (Chainlink or a 30-minute v3 average price for every holding), and only if the trades end inside the band or at least halve the excess drift,
  • with every fill within 2% of that onchain price.

It can't deposit, withdraw, change your mix or move tokens out of the vault.

Keepercalls rebalance()
  1. Opted in, and cooled downThe portfolio allows the keeper, and an hour has passed since its last keeper run.
  2. Approved pools onlyEvery leg uses a Uniswap pool the vault lists; never one the keeper made.
  3. Actually past its bandValued onchain; the trades must end in band or halve the excess drift.
  4. Fills within 2%Each fill lands within 2% of the onchain price (Chainlink, or a 30-minute v3 average).

All pass: the trades run

Any fails: reverts

The keeper can never deposit, withdraw, change your mix or move tokens out.

Fig. 7The vault checks every keeper rebalance against these rules onchain. If any one fails, the whole transaction reverts and nothing trades.

What you are still trusting

Within those limits, the keeper chooses when to trade and the minimum outputs. The worst a faulty keeper can do is trade a portfolio up to about 2% away from the reference price, once an hour, on trades that must reduce drift. If you'd rather not, switch the keeper off and rebalance yourself.

When a Chainlink feed pauses (for example around a stock split), the vault falls back to the asset's 30-minute Uniswap v3 average price. An asset with neither reference can't be keeper-rebalanced until one is available; you can always rebalance it yourself.

The contract owner

The owner can list assets, approve routes and price sources, change the keeper and treasury, set fees within hard caps, and pause new deposits and rebalances. Every change that could loosen the keeper's limits (new keeper, new routes, price sources, higher fees or slippage, shorter cooldown) waits behind a 48-hour public timelock, announced onchain with the exact call, so you have time to withdraw first. Tightening changes and pausing apply at once. There is no function that moves your holdings, and pausing never blocks withdrawals.

If the keeper stops

Rebalancing pauses. Everything else keeps working: you can rebalance and withdraw yourself.

Risks

Read this before depositing.

  • Market risk. Ondo tokens track real share prices and can fall. Rebalancing keeps your mix; it does not protect its value.
  • Smart contract risk. INDEXon's vault is tested against forks of Ethereum mainnet, but bugs are possible. Only deposit what you can afford to lose.
  • Liquidity risk. Many Ondo tokens trade in thin pools. Trades may cost more than expected, be skipped, or fail; withdrawing as USDC may not be possible for every holding at every moment (you can always withdraw as tokens).
  • Issuer risk. Ondo tokens are issued by Ondo Global Markets. The token contracts are upgradeable, can be paused, run a compliance check on every transfer, and let Ondo burn tokens from any address. A pause or compliance change could block trades or withdrawals of that token.
  • Oracle risk. Chainlink Ondo feeds pause around corporate actions such as splits and update less often when the underlying market is shut. The vault refuses keeper trades on a stale feed; prices shown in the app can lag.
  • Keeper risk. The contract bounds keeper trades to approved pools and to within 2% of an onchain price, but within that the keeper decides when and how to trade (see Keeper and trust).
  • Regulatory risk. Ondo tokenized stocks are not offered to US persons and are restricted elsewhere. Make sure you're allowed to hold them.

Nothing here is investment, legal or tax advice.

Contracts

Key functions

function createPortfolio(bytes32 name, address[] tokens, uint16[] weights, uint16 bandBps, bool keeperEnabled) returns (uint256 id);
function deposit(uint256 id, uint256 usdcAmount, Trade[] buys);
function rebalance(uint256 id, Trade[] trades);          // owner (free) or keeper (opted in, cooldown, fees)
function withdraw(uint256 id, uint16 shareBps, Trade[] sells, address to);
function setMix(uint256 id, address[] tokens, uint16[] weights);
function getPortfolio(uint256 id) view returns (Portfolio, address[] assets, uint16[] weights, uint256[] balances);

A Trade names the token, direction, exact input, minimum output and route:

struct Trade {
    address token;     // the Ondo token
    bool sell;         // true: token -> USDC
    uint256 amountIn;
    uint256 minOut;    // must be > 0
    Venue venue;       // V3 or V4
    uint24 fee;        // <= 1%
    int24 tickSpacing; // v4 only
    address hooks;     // v4 only: zero or an approved hook
}

Limits written into the contract

LimitValue
Assets per portfolio24
Pool feeat most 1%
Keeper feeat most 0.5% + 5 USDC per rebalance
Keeper cooldown1 hour to 1 day
Keeper fill vs. onchain priceat most 5% (set to 2%)
Drift band1% to 20%
Timelock on loosening admin changes48 hours

The vault deploys a small stateless helper, IndexonPricer, that reads Chainlink and Uniswap v3 average prices.

Source and tests live in the contracts/ folder of the repository.

Deployed contracts

On Ethereum mainnet, with source verified on Etherscan:

ContractAddress
IndexonVault0xF49E9F6820652d2a9b7c9867edD81BEaEDa070E4
IndexonPricer0xaf2F868E0a8e82194f6AEDB3D5D9b9D0dD212fcF
IndexonLaunch (deployment helper)0xDdD1ce8de04da0578E2a7B891F980d4129d5e9e2

A local mainnet fork writes its addresses to contracts/deployments/fork.json instead.