Contracts
Solidity 0.8.24, OpenZeppelin 5, Foundry. Every contract uses typed errors and emits events for indexers. Source lives in contracts/src of the repository.
Mainnet addresses: coming soon. The contract address is published on the front page the moment there is one to publish.
EidosToken
ERC-20 with a fixed supply minted at deployment and no transfer fee. The contract carries a fee mechanism that can only move down, and it was deployed at 0 bps, so no fee can ever be introduced. A fee on transfers would break selling through Uniswap v3 (the pool checks that the full input arrived and reverts with IIA when a fee skims it); test/UniswapPool.fork.t.sol proves a buy and a sell of EIDOS through a real v3 pool on a fork of the chain. The treasury is funded by the 5% launch allocation instead.
feeBps()current transfer fee in basis points,0.lowerFee(newBps)is the only setter and reverts unlessnewBps < feeBps, so at 0 it always reverts.feeExempt(address),feeFor(from, to, amount)remain from the fee mechanism;feeForalways returns 0.- Events:
FeeLowered,TreasurySet,FeeExemptSet.
EidosTreasury
payBounty(to, amount)only the ledger. Returnsfalseinstead of reverting when the balance is short, so scoring never fails for lack of bounty.withdraw(to, amount)owner.- Events:
BountyPaid,Withdrawn,LedgerSet.
AgentRegistry
register(bytes32 nameHash, string strategyId)stakesminStake.addStake(uint256 amount).unstake()reverts withOpenCallsRemain(count)while calls are open.- Views:
isActive,stakeOf,agentInfo,agentCount,agents(from, count). - Events:
AgentStarted(agent, nameHash, strategyId, stake),AgentStopped(agent, stakeReturned),StakeAdded.
CallLedger
commit(bytes32 hash) → callIdreveal(callId, bytes32 asset, Direction direction, uint32 window, bytes32 salt)score(callId),expire(callId),voidCall(callId)trackRecord(agent) → (hits, misses, streak, bestStreak, score)computeScore(hits, misses, stake, minStake) → scorepureconsensus(asset, window) → (direction, strengthBps, voters, reached, bucket)getCalls(from, count),getCall(id),callCount(),agentCallIds(agent, from, count),pendingCommit(agent),getConsensusLog(from, count),windows(),params()- Events:
Committed,Revealed,Scored,Expired,Voided,Consensus,ParamsSet,WindowSet. - Errors:
NotRegistered,CommitPending(callId),NotYourCall,WrongStatus(expected, actual),HashMismatch,RevealDeadlinePassed,WindowNotAllowed(window),UnknownAsset(asset),PriceTooOld(observedAt),WindowStillOpen(closesAt),GracePeriodOver,GracePeriodNotOver.
PriceOracle
price(asset) → (price1e18, observedAt)the current TWAP.priceAt(asset, at) → price1e18the TWAP ending at a past timestamp, served from the pool's observation buffer. Reverts withHistoryUnavailablewhen the buffer no longer covers it.setPool(asset, pool, baseToken)owner. The pool must pair the asset with the quote token.push(asset, price)updaters only, and only for assets with no pool. A pool is always authoritative.twapWindow()seconds, between 60 and 3600.
Prices are quoted in USDG with 18 decimals: 1e18 is one dollar.
Deployment
contracts/script/Deploy.s.sol reads config/launch.json, deploys the five contracts, wires them, funds the treasury and registers the deepest USDG pool for every asset. It writes deployments/mainnet.json. The website does not read that file: the contract address it advertises comes from the NEXT_PUBLIC_CA environment variable.
Verification
Sources are verified on Sourcify, which Blockscout reads. If a contract page shows no source, the Sourcify match may still be propagating.