Deployment Guide
Prerequisites
Foundry installed (
forge,anvil,cast)BNB for gas fees
Deployer EOA private key
BscScan API key (for contract verification)
Environment Variables
export PRIVATE_KEY=0x... # Deployer private key
export RPC_URL=https://... # BSC RPC endpoint
export PYTH_ADDRESS=0x... # Pyth Core contract address (see table below)
export ETHERSCAN_API_KEY=... # BscScan API key for verificationPyth Oracle Addresses
BSC Testnet
97
0x5744Cbf430D99456a0A8771208b674F27f8EF0Fb
BSC Mainnet
56
0x4D7E825f80bDf85e913E0DD2A2D54927e9dE1594
Deployment Order
The canonical BSC deploy entrypoint is script/DeployTestnet.s.sol:DeployTestnetScript. Despite the name, it is chain-aware and is the script currently used for both BSC testnet (chainid=97) and BSC mainnet (chainid=56). It also deploys and wires AIResolver.
Contracts must be deployed in this exact order because of immutable constructor references:
Constructor Arguments
Vault(admin, collateralToken)
deployer address, USDT address
OutcomeToken(admin)
deployer address
FeeModel(admin, feeBps, protocolFeeCollector)
deployer, 20, deployer
OrderBook(admin, vault, feeModel, outcomeToken)
deployer, Vault address, FeeModel address, OutcomeToken address
BatchAuction(admin, orderBook, vault, outcomeToken)
deployer, OrderBook, Vault, OutcomeToken
MarketFactory(admin, orderBook, outcomeToken)
deployer, OrderBook, OutcomeToken
PythResolver(pyth, factory)
PYTH_ADDRESS, MarketFactory
AIResolver(factory, treasury)
MarketFactory, deployer or configured treasury
Redemption(factory, outcomeToken, vault)
MarketFactory, OutcomeToken, Vault
Role Wiring
After all contracts are deployed, grant the following roles. The deployer holds DEFAULT_ADMIN_ROLE on every AccessControl contract and can call grantRole.
OrderBook.OPERATOR_ROLE
BatchAuction needs OPERATOR_ROLE to call reduceOrderLots, updateTreeVolume, and advanceBatch. MarketFactory needs it to call registerMarket and deactivateMarket. In production, the keeper is also granted OPERATOR_ROLE so it can drive batch clearing.
Vault.PROTOCOL_ROLE
OrderBook calls lock and unlock. BatchAuction calls settleFill and unlock. Redemption calls redeemFromPool.
OutcomeToken.MINTER_ROLE
BatchAuction calls mintSingle during inline settlement. Redemption calls redeem (burns winning tokens).
MarketFactory.ADMIN_ROLE
PythResolver and AIResolver call resolution functions on MarketFactory. Production deployments also grant keeper and resolution-keeper admin access on the factory, plus market-creation rights for the deployer and keeper.
AIResolver Keeper Wiring
PythResolver Admin
PythResolver uses simple ownership (not AccessControl). The admin is set to msg.sender in the constructor (the deployer). Transfer via two-step process:
Deploy Commands
Local Devnet (Anvil)
For local development and testing:
The local-only Deploy.s.sol script deploys a MockPyth instance, wires all roles, and creates a test market automatically.
BSC Testnet / Mainnet
DeployTestnetScript auto-detects block.chainid, chooses the correct real Pyth address for BSC testnet or mainnet, deploys AIResolver, and wires the production role set.
Note: script/DeployMainnet.s.sol still exists in the repo, but the canonical production path is the chain-aware DeployTestnet.s.sol:DeployTestnetScript flow above.
Parimutuel Contract Deployment
The parimutuel stack is intentionally isolated from the binary CLOB contracts and is deployed with script/DeployParimutuel.s.sol:DeployParimutuelScript.
It deploys and wires:
ParimutuelFactoryParimutuelVaultParimutuelPoolManagerParimutuelRedemptionParimutuelAIResolverParimutuelPythResolver
Required env:
Recommended mainnet role env:
PARIMUTUEL_MARKET_CREATOR should be the keeper/admin-server signer so production admin tooling can create markets. PARIMUTUEL_KEEPER should be the resolution keeper because the infra lifecycle task drives AI/Pyth parimutuel resolution with the resolution sender.
Deploy:
After deployment, update the address registry, strike-infra Ansible group vars, and strike-frontend/src/lib/contracts.ts before enabling mainnet UI/keeper flows.
Contract Verification
Deploy scripts pass --verify to auto-verify on BscScan. To verify a contract manually:
For contracts with complex constructor args, use cast abi-encode to produce the correct encoding.
Post-Deploy Validation Checklist
Contract verification -- all contracts verified on BscScan.
Role wiring -- confirm every role grant:
Role checks:
OrderBook.hasRole(OPERATOR_ROLE, BatchAuction)-- trueOrderBook.hasRole(OPERATOR_ROLE, MarketFactory)-- trueVault.hasRole(PROTOCOL_ROLE, OrderBook)-- trueVault.hasRole(PROTOCOL_ROLE, BatchAuction)-- trueVault.hasRole(PROTOCOL_ROLE, Redemption)-- trueOutcomeToken.hasRole(MINTER_ROLE, BatchAuction)-- trueOutcomeToken.hasRole(MINTER_ROLE, Redemption)-- trueMarketFactory.hasRole(ADMIN_ROLE, PythResolver)-- true
Test market creation -- call
MarketFactory.createMarket(...)with a known Pyth price ID (requires MARKET_CREATOR_ROLE) and verify the market appears inactiveMarkets.Test place/cancel cycle -- approve Vault for USDT, call
OrderBook.placeOrder(...)and verify USDT collateral is escrowed in Vault. Cancel the order and verify USDT is returned to wallet.Keepers configured -- batch-keeper, market-keeper, and resolution-keeper (in strike-infra) pointing at correct contract addresses.
Indexer configured -- indexer (in strike-infra) pointing at correct RPC and contract addresses, listening for all relevant events.
SDK / docs updated -- update SDK defaults and published deployment docs/README so integrators pick up the new mainnet and testnet addresses.
Last updated