Contracts
Inference Markets is one set of Solidity contracts, built with Foundry on Solidity 0.8.26 and deployed to Base. There are fourteen of them, they own everything the protocol holds, and there is no operator among them: no key can set a price or pay a holder. The interesting behavior is in five: the InferenceIndex that writes the price of intelligence, the PegManager that keeps a coin at that price, the Launchpad that owns every market's liquidity, the LaunchToken that pays its own holders, and the RedemptionVault that pays out at the index.
| Chain | Base, chain ID 8453, OP-stack L2, ETH for gas |
| RPC | https://mainnet.base.org |
| Explorer | https://basescan.org |
| Addresses | contracts/deployments/8453.json, written by the deploy script and read by the site |
Inference Markets contracts
| Contract | Role | Who may call what |
|---|---|---|
PriceFeed |
USD prices for the catalogue under keccak256(symbol), USD × 1e18 per coin. Chainlink and Aerodrome TWAP assets are read live at call time; the three class prices are pushed. |
owner: registerPushed, registerChainlink, registerTwap, setPusher, setActive. pusher (the InferenceIndex): push, and only for pushed assets. anyone: getPrice, peek, isFresh. |
InferenceIndex |
Stores hourly OpenRouter samples in a 168-slot ring and publishes the median as INT, OPEN and AGENT. The program and the model lists live on-chain, so a submitted sample can be recomputed and checked. |
anyone: publish. sampler only: submitSample (55-minute spacing). owner: setSampler, proposeConfig → 24 h → applyConfig. reads: median, latestSample, count, head, config, pendingConfig, sampler, nextSampleAt. |
InferenceCoin |
One ERC-20 per synthetic unit, 18 decimals. Two fixed addresses: the minter and the burner. | minter (PegManager): mint, burn. burner (RedemptionVault): burn. owner: setMinter, setBurner. |
PegManager |
Owns each synthetic coin's single-sided V3 ask and bid, forwards dollars above the bid target to the vault. Sole minter. | anyone: reprice, refill. owner: registerCoin, setBidTarget, setVault (once). reads: needsReprice, needsRefill, askCoin, bidUsd, feedBand, pegOf, usdReserve. |
LaunchTokenFactory |
Deploys LaunchTokens for the launchpad, so the launchpad's own bytecode stays under the EIP-170 size limit. |
launchpad only: create. setLaunchpad is bound once at deployment, by the deployer only. |
LaunchToken |
A market's ERC-20: 18 decimals, 1,000,000,000 fixed supply minted to the launchpad, immutable metadataURI, and the per-share fee accumulator that pays its holders every block. |
distributor only: notifyFees, harvest. launchpad only: setExcluded. anyone: transfers, pendingOf, excluded, eligibleSupply, accCoinPerShare, accTokenPerShare. |
Launchpad |
Creates markets, owns both liquidity positions, collects fees and routes them: coin side 50 / 30 / 20, token side to holders. Holds the pair allowlist. Has no liquidity-removal function. | anyone: launch, collectFees. router only: launchFor. owner: setPair, setExcluded, setRouter, setTreasury, setDistributor. reads: marketOf, marketAt, marketCount, pairInfoOf, ledgerOf, collectedOf, splitCoin. |
Distributor |
Holds every market's holder share and pays it on claim, in the holder's chosen asset, converting through the router in the same transaction. Holds refused deliveries. | holder: claim, claimMany, claimHeld, setPayoutPreference. launchpad only: notify. owner: setRouter. reads: pendingOf, preferenceOf, heldOf. |
Treasury |
Ledger of the protocol's buyback and protocol shares per market, and the permissionless sweeps that realize them with feed-derived floors. | anyone: sweepToBuyback, sweepProtocol, topUpVault (only under 100% coverage). launchpad only: notifyCollected. owner: setRouter, setVault, setBuyback, setProtocolWallet. reads: ledgerOf, minEthOut, minUsdOut. |
RedemptionVault |
Holds USDC and DIEM per synthetic coin, burns coin on redemption and pays at the index in the same transaction. Computes coverage. Keeps its DIEM share in band. | anyone: redeem, fund, rebalance. router only: redeemFor. owner: configure, sweepSurplus (above 110%), setAdapter, setRouter, setTrancheUsd. reads: quoteRedeem, canRedeem, coverageBps, outstanding, usdOf, diemOf, diemShareBps, needsRebalance, redeemedToday, diemDelivered, configOf. |
LaunchRouter |
One-transaction routes between ETH, USDC, pair coin, market token, DIEM and payout assets; vault-first sells for synthetics; quotes. Stateless, holds nothing between calls. | anyone: buyWithEth/Usd/Coin, sellForEth/Usd/Coin, sellForDiem, launchWithEth/Usd, swapUsdForCoin, swapCoinForUsd, swapCoinForEth, swapCoinForAsset, quoteBuy, quoteSell, quoteCoinForAsset. distributor only: swapCoinForAssetFor (a claim's conversion, with the vault's caps charged to the claiming wallet). No owner. |
AerodromeAdapter |
Owner-set routes made of legs. The one route in use is USDC → WETH → VVV → DIEM and back: three Aerodrome v2 pools sent to the Aerodrome Router as one call (the USDC/VVV v2 pool is nearly empty; the VVV/WETH pool is the deep one). A second leg kind, a concentrated pool swapped directly with the Uniswap V3 callback, exists in the contract but is not used by any route today. Holds no funds between calls. quoteExactIn walks the same legs, using the router's getAmountsOut, so a quote equals execution in the same block. |
owner: setRoute, which checks that legs chain. anyone: swapExactIn (pulls the input from the caller), quoteExactIn, routeOf, hasRoute. |
INFERENCE |
The exchange token: ERC-20, 18 decimals, 1,000,000,000 fixed supply, burnable, no mint path after construction. | anyone: burn their own. No owner. |
Buyback |
Receives ETH from the Treasury, spends its whole balance on $INFERENCE in a bound native-ETH v4 pool, and burns what it buys. | executor only: execute. owner: setExecutor, setPool (once). reads: totalBurned, totalEthSpent, poolSet, executor. |
External contracts on Base
| Contract | Address | Notes |
|---|---|---|
| USDC | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
Circle native USDC, 6 decimals |
| WETH | 0x4200000000000000000000000000000000000006 |
OP-stack predeploy |
| Uniswap V3 factory | 0x33128a8fC17869897dcE68Ed026d694621f6FDfD |
peg pools, 0.30% tier, tick spacing 60 |
| WETH/USDC V3 pool | 0xd0b53D9277642d899DF5C87A3966A349A798F224 |
0.05% fee; the ETH ↔ USD leg of every route |
| Uniswap v4 PoolManager | 0x498581fF718922c3f8e6A244956aF099B2652b2b |
every market pool, and $INFERENCE pool |
| Uniswap v4 PositionManager | 0x7C5f5A4bBd8fD63184577525326123B519429bDc |
not used for launchpad positions |
| Uniswap v4 StateView | 0xA3c0c9b65baD0b08107Aa264b0f3dB444b867A71 |
the site reads pool state through it |
| Uniswap v4 Quoter | 0x0d5e0F971ED27FBfF6c2837bf31316121532048D |
reads |
| Uniswap v4 UniversalRouter | 0x6fF5693b99212Da76ad316178A184AB56D299b43 |
|
| Permit2 | 0x000000000022D473030F116dDEE9F6B43aC78BA3 |
canonical |
| Chainlink ETH/USD | 0x71041dddad3595F9CEd3DcCFBe3D1F4b0a16Bb70 |
8 decimals, 20-minute heartbeat; read live, stale after 2 hours; prices ETH for sweeps and the VVV/WETH leg |
| DIEM | 0xF4d97F2da56e8c3098f3a8D538DB630A2606a024 |
Venice AI, ERC-20, 18 decimals |
| VVV | 0xacfE6019Ed1A7Dc6f7B508C02d1b04ec88cC21bf |
Venice AI; the middle hop of the DIEM route |
| Aerodrome VVV/WETH pool | 0x01784ef301D79e4B2DF3a21ad9a536d4cF09A5Ce |
volatile, about $14M; the VVV price source, quote(VVV, 1e18, 12) |
| Aerodrome VVV/DIEM pool | 0xbB345D35450BF9Ee76F3D2cE214E8e7AC5e1071d |
volatile, about 2,350 DIEM of depth; the DIEM price source, quote(DIEM, 1e18, 12), and the DIEM venue |
| Aerodrome Router | 0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43 |
verified 2026-09-16; executes the v2 DIEM legs; its defaultFactory() is the PoolFactory below |
| Aerodrome PoolFactory | 0x420DD381b31aEf6683db6B902084cB0FFECe40Da |
verified 2026-09-16; getPool(VVV, DIEM, false) is the VVV/DIEM pool above; the factory field of every v2 leg |
Ownership and trust
Every contract with an owner uses OpenZeppelin Ownable2Step, so a transfer has to be accepted by the new owner. There is no operator role anywhere. The only non-owner privileged addresses are the PriceFeed's pusher, which is the InferenceIndex contract and not a person, and the Buyback executor.
| Who | Can |
|---|---|
| nobody | set a price by hand, pay a holder, mint a launch token or $INFERENCE after construction, remove a market's liquidity |
| the chain | price ETH (Chainlink, live), VVV and DIEM (Aerodrome TWAPs, live), and the three class prices (the median of the InferenceIndex window) |
| owner | register feed sources and switch assets on or off; set adapter routes (Aerodrome v2 legs through the Aerodrome Router); set the pair allowlist; allow payout assets; configure the vault (caps, fee, spread, tranche size); set bid targets; exclude a protocol contract from accrual; propose and, 24 hours later, apply a new index config (source, model lists); rotate the index sampler; sweep vault surplus above 110% coverage; set the executor; bind the buyback pool once |
| executor | Buyback.execute, which spends the Buyback's ETH on $INFERENCE and burns it, with a floor it supplies |
| sampler | InferenceIndex.submitSample, one reading an hour into a 168-slot window. It cannot publish, cannot push a price, and cannot touch funds; moving the published median takes 83 consecutive submissions, over three days, all on-chain |
| launchpad | Distributor.notify, Treasury.notifyCollected, LaunchToken.setExcluded, LaunchTokenFactory.create |
| router | Launchpad.launchFor, RedemptionVault.redeemFor |
| distributor | LaunchToken.notifyFees, LaunchToken.harvest |
| a holder | claim, claimMany, claimHeld, setPayoutPreference |
| anyone | launch, trade, redeem, fund, and every maintenance call in Automation: request, publish, reprice, refill, collectFees, the three Treasury sweeps, rebalance |
The owner's powers are configuration and nothing else: feed sources, adapter routes, the pair and payout allowlists, the vault's parameters and the index config. A change to the index config carries a built-in 24-hour delay and is readable in full through pendingConfig() the whole time. The plan before mainnet, recorded in SPEC.md §7, is to hand OWNER to a TimelockController so that every owner action is visible on-chain before it takes effect. What the owner has no function for is the part that matters: it cannot set a price, pay or skip a holder, mint a launch token or $INFERENCE, or remove a market's liquidity. The executor's reach is the ETH sitting in the Buyback at the moment it acts, and it can only spend that ETH on $INFERENCE and burn what it buys.
Decimals
| Asset | Decimals |
|---|---|
| Inference coins, launch tokens, DIEM, VVV, $INFERENCE | 18 |
| USDC | 6 |
| Feed prices | USD × 1e18 per whole coin |
| Index samples | USD × 1e18 per million tokens |
| Vault USD accounting | 6, USDC's own |
| Accumulator precision | 1e36 per share |
The launchpad reads decimals() from the pair coin rather than assuming it, though every pair coin in the catalogue is 18-decimal. The recurring conversion in the vault is usdValue = amount × price / 1e30, which takes an 18-decimal amount and an 18-decimal price to a 6-decimal dollar figure.
Tests
The suite is 184 tests across 20 suites, hermetic: no fork and no RPC. The v4 PoolManager and the V3 factory are deployed locally from vendored artifacts; USDC (with a pause and a blocklist, to exercise held payouts), WETH, DIEM, VVV, Aerodrome v2 pools with a quote TWAP behind a mock router and Chainlink aggregators are all mocked. The fixture's maintenance helpers are called by a stranger to prove nothing needs an operator, and an invariant suite drives launches, trades, collections, claims, sweeps and repricings from an unprivileged handler. contracts/TESTING.md maps every suite to what it covers.