Deployment Guide

Prerequisites

  • Foundryarrow-up-right 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 verification

Pyth Oracle Addresses

Network
Chain ID
Pyth Core Address

BSC Testnet

97

0xd7308b14BF4008e7C7196eC35610B1427C5702EA

BSC Mainnet

56

0x4D7E825f80bDf85e913E0DD2A2D54927e9dE1594

Deployment Order

Contracts must be deployed in this exact order because of immutable constructor references:

Constructor Arguments

Contract
Constructor Args

Vault(admin)

deployer address

OutcomeToken(admin)

deployer address

FeeModel(admin, feeBps, protocolFeeCollector)

deployer, 20, deployer

OrderBook(admin, vault)

deployer, Vault address

BatchAuction(admin, orderBook, vault, feeModel, outcomeToken)

deployer, OrderBook, Vault, FeeModel, OutcomeToken

MarketFactory(admin, orderBook, outcomeToken, feeCollector)

deployer, OrderBook, OutcomeToken, deployer

PythResolver(pyth, factory)

PYTH_ADDRESS, MarketFactory

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.

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 calls setResolving, setResolved, and payResolverBounty on MarketFactory.

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)

The Deploy.s.sol script deploys a MockPyth instance, wires all roles, and creates a test market automatically.

BSC Testnet

BSC Mainnet

The deploy script auto-detects chain ID 97 (testnet) vs 56 (mainnet) and uses the correct Pyth address.

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

  1. Contract verification -- all contracts verified on BscScan.

  2. Role wiring -- confirm every role grant:

  3. Role checks:

    • OrderBook.hasRole(OPERATOR_ROLE, BatchAuction) -- true

    • OrderBook.hasRole(OPERATOR_ROLE, MarketFactory) -- true

    • Vault.hasRole(PROTOCOL_ROLE, OrderBook) -- true

    • Vault.hasRole(PROTOCOL_ROLE, BatchAuction) -- true

    • Vault.hasRole(PROTOCOL_ROLE, Redemption) -- true

    • OutcomeToken.hasRole(MINTER_ROLE, BatchAuction) -- true

    • OutcomeToken.hasRole(MINTER_ROLE, Redemption) -- true

    • MarketFactory.hasRole(ADMIN_ROLE, PythResolver) -- true

  4. Test market creation -- call MarketFactory.createMarket(...) with a known Pyth price ID (requires MARKET_CREATOR_ROLE) and verify the market appears in activeMarkets.

  5. 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.

  6. Keepers configured -- batch-keeper, market-keeper, and resolution-keeper (in strike-infra) pointing at correct contract addresses.

  7. Indexer configured -- indexer (in strike-infra) pointing at correct RPC and contract addresses, listening for all relevant events.

Last updated