# Deployment Guide

## Prerequisites

* [Foundry](https://book.getfoundry.sh/) installed (`forge`, `anvil`, `cast`)
* BNB for gas fees
* Deployer EOA private key
* BscScan API key (for contract verification)

## Environment Variables

```bash
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       | `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:

```
1. Vault              -- no dependencies
2. OutcomeToken        -- no dependencies
3. FeeModel            -- no dependencies
4. OrderBook           -- needs Vault
5. BatchAuction        -- needs OrderBook, Vault, FeeModel, OutcomeToken
6. MarketFactory       -- needs OrderBook, OutcomeToken
7. PythResolver        -- needs Pyth oracle address, MarketFactory
8. Redemption          -- needs MarketFactory, OutcomeToken, Vault
```

### Constructor Arguments

| Contract                                              | Constructor Args                                                |
| ----------------------------------------------------- | --------------------------------------------------------------- |
| `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

```solidity
orderBook.grantRole(OPERATOR_ROLE, address(batchAuction));
orderBook.grantRole(OPERATOR_ROLE, address(marketFactory));
```

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

```solidity
vault.grantRole(PROTOCOL_ROLE, address(orderBook));
vault.grantRole(PROTOCOL_ROLE, address(batchAuction));
vault.grantRole(PROTOCOL_ROLE, address(redemption));
```

OrderBook calls `lock` and `unlock`. BatchAuction calls `settleFill` and `unlock`. Redemption calls `redeemFromPool`.

### OutcomeToken.MINTER\_ROLE

```solidity
outcomeToken.grantRole(MINTER_ROLE, address(batchAuction));
outcomeToken.grantRole(MINTER_ROLE, address(redemption));
```

BatchAuction calls `mintSingle` during inline settlement. Redemption calls `redeem` (burns winning tokens).

### MarketFactory.ADMIN\_ROLE

```solidity
factory.grantRole(ADMIN_ROLE, address(pythResolver));
factory.grantRole(ADMIN_ROLE, address(aiResolver));
factory.grantRole(ADMIN_ROLE, keeper);
factory.grantRole(ADMIN_ROLE, resolutionKeeper);
factory.grantRole(MARKET_CREATOR_ROLE, deployer);
factory.grantRole(MARKET_CREATOR_ROLE, keeper);
factory.setAIResolver(address(aiResolver));
```

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

```solidity
aiResolver.grantRole(KEEPER_ROLE, keeper);
aiResolver.grantRole(KEEPER_ROLE, resolutionKeeper);
```

### 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:

```solidity
pythResolver.setPendingAdmin(newAdmin);   // called by current admin
pythResolver.acceptAdmin();               // called by newAdmin
```

## Deploy Commands

### Local Devnet (Anvil)

For local development and testing:

```bash
anvil --chain-id 31337

forge script script/Deploy.s.sol \
  --rpc-url http://localhost:8545 \
  --broadcast
```

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

### BSC Testnet / Mainnet

```bash
forge script script/DeployTestnet.s.sol:DeployTestnetScript \
  --rpc-url $RPC_URL \
  --broadcast \
  --verify \
  --etherscan-api-key $ETHERSCAN_API_KEY
```

`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:

1. `ParimutuelFactory`
2. `ParimutuelVault`
3. `ParimutuelPoolManager`
4. `ParimutuelRedemption`
5. `ParimutuelAIResolver`
6. `ParimutuelPythResolver`

Required env:

```bash
export PRIVATE_KEY=0x...          # or DEPLOYER_PRIVATE_KEY
export USDT_ADDRESS=0x...         # BSC mainnet USDT or testnet mock USDT
export PYTH_ADDRESS=0x...         # Pyth Core for the target chain
```

Recommended mainnet role env:

```bash
export PARIMUTUEL_FINAL_ADMIN=0xDA680a19C8E5a43a5B6280d2a1e1A5E2E8ACD874
export PARIMUTUEL_FEE_RECIPIENT=$PARIMUTUEL_FINAL_ADMIN
export PARIMUTUEL_MARKET_CREATOR=0x73f173D43Fa5284e85d8c4F20453E9bA2629Dd9A
export PARIMUTUEL_KEEPER=0x439d5804Bf14e97f1DA3449304f4167621ff9Cfe
```

`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:

```bash
forge script script/DeployParimutuel.s.sol:DeployParimutuelScript \
  --rpc-url $RPC_URL \
  --broadcast \
  --verify \
  --etherscan-api-key $ETHERSCAN_API_KEY
```

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:

```bash
forge verify-contract <CONTRACT_ADDRESS> src/MarketFactory.sol:MarketFactory \
  --chain-id 56 \
  --etherscan-api-key $ETHERSCAN_API_KEY \
  --constructor-args $(cast abi-encode \
    "constructor(address,address,address,address)" \
    $DEPLOYER $ORDERBOOK $OUTCOMETOKEN $FEECOLLECTOR)
```

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:

   ```bash
   cast call $ORDERBOOK "hasRole(bytes32,address)(bool)" \
     $(cast keccak "OPERATOR_ROLE") $BATCH_AUCTION
   # Repeat for every grant listed above
   ```
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.
8. **SDK / docs updated** -- update SDK defaults and published deployment docs/README so integrators pick up the new mainnet and testnet addresses.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.strike.pm/guides/deployment-guide.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
