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 |
Chainlink Functions consumer. Stores hourly OpenRouter samples in a 168-slot ring and publishes the median as INT, OPEN and AGENT. Config (source, model lists, subscription, DON) lives on-chain. |
anyone: request (55-minute spacing), publish. Functions router only: the fulfillment callback. owner: proposeConfig → 24 h → applyConfig. reads: median, latestSample, count, head, config, pendingConfig. |
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: setPayoutAsset, setRouter. reads: pendingOf, preferenceOf, heldOf, payoutAssetAllowed. |
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 two kinds of leg. V2: an Aerodrome v2 pool through the Aerodrome Router, used for USDC → WETH → VVV → DIEM and back (the USDC/VVV v2 pool is nearly empty; the VVV/WETH pool is the deep one). CL: an Aerodrome Slipstream concentrated pool swapped directly with the V3-style callback, no router trusted, used for USDC ↔ each stock. Holds no funds between calls. quoteExactIn is not a view: CL legs are simulated so a quote equals execution in the same block. |
owner: setRoute, which checks that legs chain and that a CL pool holds exactly the leg's two tokens. anyone: swapExactIn (pulls the input from the caller), quoteExactIn, routeOf, hasRoute. |
PAIDIN |
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 the protocol token 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 the protocol token 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 |
| Chainlink Functions router | 0xf9B8fc078197181C841c296C876945aaa425B278 |
DON id fun-base-mainnet-1; the InferenceIndex is a consumer of a funded subscription |
| 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 |
| Aerodrome Slipstream USDC/stock pools | six, one per stock | concentrated, tick spacing 10, on an Aerodrome-approved CL factory; swapped directly by the adapter |
The six B20 stock tokens, their Chainlink feeds and their Slipstream pools are listed in AI stocks.
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 the protocol token after construction, remove a market's liquidity |
| the chain | price stocks and ETH (Chainlink, live), VVV and DIEM (Aerodrome TWAPs, live), and the three class prices (Chainlink Functions through the InferenceIndex) |
| owner | register feed sources and switch assets on or off; set adapter routes (v2 legs through the Aerodrome Router, Slipstream legs on a named pool); 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, subscription, DON); sweep vault surplus above 110% coverage; set the executor; bind the buyback pool once |
| executor | Buyback.execute, which spends the Buyback's ETH on the protocol token and burns it, with a floor it supplies |
| 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 several of them matter: a changed feed source changes what every contract believes a coin is worth, a changed adapter route changes where DIEM and stock trades execute, and a changed model list changes the index over the following three and a half days. The index change is the only one with a built-in delay. The recommendation before mainnet, recorded in SPEC.md §7, is to hand OWNER to a TimelockController so that every owner action is visible before it takes effect. The executor is a single key, and its blast radius is the ETH sitting in the Buyback at the moment it acts. Risks states all of this again.
Decimals
| Asset | Decimals |
|---|---|
| Inference coins, launch tokens, DIEM, VVV, the protocol token | 18 |
| USDC | 6 |
| B20 stocks | 8 |
| 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, which is what lets an 8-decimal stock be a pair. 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 186 tests across 20 suites, hermetic: no fork and no RPC. The v4 PoolManager and the V3 factory are deployed locally from vendored artifacts; USDC, WETH, DIEM, VVV, a B20 stock with a policy block, a pause and a multiplier, Aerodrome v2 pools with a quote TWAP behind a mock router, a Slipstream-style concentrated pool for the stock, Chainlink aggregators and the Chainlink Functions router 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.