Contracts & Addresses
The protocol core is deployed via CREATE3, so the addresses are identical on testnet and mainnet:
| Contract | Address (testnet 50312 = mainnet 5031) |
|---|---|
| BinaryMarketsModule | 0x3ecC694Cef705358864a646142ac17A90E29e388 |
| MarketsCore | 0x2802504314685D89bF6C992CA5a8e7cC78bc0294 |
| BinarySettlement | 0xbF4a49e0Dfd092e5FBE8E5761064C49533e6Ed23 |
| OutcomeToken6909 | 0xB52c5934113Af5c0Bb20eb3C72290C8215f755b9 |
| OracleHub | 0xe40db387cC98601Dd11bd634fF2f3AD5686dE32b |
| CollateralRouter | 0xbC0C9834B15ACE38bB50dDaa7d7f7C7CC4DC183C |
Per-market contracts (the market and its pool) are read from the module registry — markets(marketId) — or from the SDK; never hardcode them, since pools are recycled across windows.
Collateral is per-venue: USDso (0x00000022dA000002656c64D9eA6011ea952D008A, 18 decimals) on mainnet; a faucet-enabled test USDC (6 decimals) on testnet.
These are proxies, so each one's implementation can roll forward while the address stays put. Check any of them on the Somnia explorer: mainnet and testnet.
Working from a non-JS stack? The SDK package exports the ABIs you need directly (binaryModuleReadAbi, binaryModuleWriteAbi, binarySettlementAbi, erc6909Abi, oracleHubAbi), so you can pull them out of the package and drive the contracts with any RPC client.
Confirm the addresses on-chain before trading real funds, and never hardcode a market or pool address: those are per-window, and pools are recycled across windows. Read them from the module registry or the SDK instead.