Modular prediction-market settlement and publishing system. On-chain custody, settlement, and fees with off-chain orchestration via Chainlink CRE workflows.
RetroPick is a production-ready prediction market protocol that separates on-chain primitives (custody, settlement, fees, registry, publishing) from off-chain orchestration (draft proposals, publishing triggers, resolution data). All oracle flows enter through Chainlink CRE (Chainlink Request-and-Execute), ensuring a single trusted entry point for resolution and checkpoint settlement.
| Aspect | Description |
|---|---|
| Core flow | Curated drafts → claimAndSeed → Publish via CRE → Off-chain trading → Checkpoint settlement (V3: OutcomeToken1155 + V3-Escrow) → Oracle resolution → Redeem |
| Trading model | Off-chain trading with your relayer; on-chain checkpoint settlement with operator + user signatures |
| Oracle | Chainlink Forwarder → CREReceiver → OracleCoordinator → SettlementRouter → MarketRegistry / ChannelSettlement |
| Deployed | Avalanche Fuji (43113); DeployBetaTestnet: 24 verified contracts on Snowscan |
| Framework | Foundry; Solidity 0.8.24; OpenZeppelin |
| Differentiator | Description |
|---|---|
| Chainlink CRE-native | All oracle and settlement flows enter via Chainlink Forwarder; single trusted entry point |
| Modular architecture | Custody, settlement, fees, and curation are separate contracts; upgradeable wiring |
| Off-chain trading, on-chain custody | Your relayer for gasless trading; on-chain checkpoints for finality via ChannelSettlement |
| Curated supply | AI-proposed drafts → creator claimAndSeed → CRE publish; quality gate at market creation |
| ERC-1155 outcome tokens (V3) | Polymarket-like positions; transfer-locked until resolved; canonical redeem path |
| V3-Escrow vaults | 3-bucket accounting; reserve on checkpoint submit, release on finalize/cancel (6h escape hatch) |
| ERC-4626 LP vaults | Per-draft liquidity vaults; protocol/LP/creator fee split; MarketRiskManager caps LP payout |
| Production-deployed | 24 verified contracts on Avalanche Fuji (DeployBetaTestnet); full E2E test suite mirrors deployment |
flowchart TB
subgraph ingress["ORACLE INGRESS (CRE)"]
Forwarder[Chainlink Forwarder]
CRE[CREReceiver]
OC[OracleCoordinator]
RV[ReportValidator]
SR[SettlementRouter]
Forwarder --> CRE
CRE --> OC
RV -.->|validate| OC
OC --> SR
SR -->|settleMarket 0x01| MR
SR -->|finalizeSession 0x03| CS
end
subgraph exec["EXECUTION PIPELINE (V3)"]
MR[MarketRegistry]
CS[ChannelSettlement]
OT[OutcomeToken1155]
RM[MarketRiskManager]
MAV[MultiAssetVault]
CV[CollateralVault]
FM[FeeManager]
FP[FeePool]
TP[TreasuryPool]
LV[LiquidityVault4626]
MR <--> CS
CS -->|mint/burn| OT
CS -->|reserveLpPayout| RM
MR -->|balanceOf+burn| OT
MAV --> MR
CV --> MR
MAV --> CS
CV --> CS
FM --> FP --> TP
LV --> MAV
LV --> CV
end
flowchart LR
subgraph curation["CURATED PIPELINE"]
CREP[CREPublishReceiver]
MF[MarketFactory]
MR[MarketRegistry]
MDB[MarketDraftBoard]
DCM[DraftClaimManager]
LVF[LiquidityVaultFactory]
MDB --> DCM --> LVF
CREP --> MF --> MR
CREP -.->|publish trigger| MDB
MF -.->|from draft| DCM
MR -.->|registry| MF
end
flowchart TB
subgraph ext["External"]
CL[Chainlink Forwarder]
end
subgraph oracle["Oracle Ingress (CRE)"]
CRE[CREReceiver]
OC[OracleCoordinator]
RV[ReportValidator]
SR[SettlementRouter]
end
subgraph exec["Execution Pipeline (V3)"]
MR[MarketRegistry]
CS[ChannelSettlement]
OT[OutcomeToken1155]
RM[MarketRiskManager]
MAV[MultiAssetVault / CollateralVault]
FM[FeeManager → FeePool → TreasuryPool]
LV[LiquidityVault4626]
end
subgraph curated["Curated Pipeline"]
CREP[CREPublishReceiver]
MF[MarketFactory]
MDB[MarketDraftBoard]
DCM[DraftClaimManager]
LVF[LiquidityVaultFactory]
end
CL --> CRE --> OC
RV -.-> OC
OC --> SR
SR -->|0x01| MR
SR -->|0x03| CS
MR <--> CS
CS --> OT
CS --> RM
MR --> OT
MAV --> MR
MAV --> CS
LV --> MAV
CREP --> MF --> MR
MDB --> DCM --> LVF
MF -.-> DCM
- Curated publish — AI proposes drafts → Creator claims and seeds → CRE publish → Market created with bound LP vault
- Oracle resolution — CRE sends outcome reports → CREReceiver → OracleCoordinator → SettlementRouter → MarketRegistry
- Checkpoint settlement — Your relayer builds signed checkpoints → CRE sends
0x03session payload → ChannelSettlement
DeployBetaTestnet (V3, active): 24 contracts including OutcomeToken1155, MarketRiskManager, Faucet.
DeployTestnet (legacy): ExecutionLedger path; different addresses.
| Contract | Role |
|---|---|
| OutcomeToken1155 | ERC-1155 outcome positions (V3 canonical); transfer-locked until resolved; mint/burn by ChannelSettlement |
| MarketRiskManager | LP payout cap per market; reserveLpPayout enforces cap before LP pays |
| ChannelSettlement | Checkpoint verification (V3-Escrow: reserve on submit, release on finalize); operator + user signatures |
| MultiAssetVault | Per-asset 3-bucket custody; freeBalance, reservedBalance, availableBalance |
| CollateralVault | Single-token 3-bucket fallback; MarketRegistry VAULT for redeem path |
| SettlementRouter | Routes outcome reports and session payloads |
| MarketRegistry | Market metadata, resolution, redeem (V3: burn OutcomeToken1155, payout from vault) |
| ExecutionLedger | Deprecated — legacy path when outcomeToken == 0; DeployTestnet only |
| Contract | Role |
|---|---|
| FeeManager | Protocol/LP/creator fee split (bps) |
| FeePool | Protocol fee collection |
| TreasuryPool | LP fee fallback when vault has zero supply |
| Contract | Role |
|---|---|
| ReportValidator | Minimum confidence threshold for resolution reports |
| CREReceiver | CRE entrypoint; routes outcome (0x01) and session (0x03) reports |
| OracleCoordinator | Validates confidence, forwards to SettlementRouter |
| SettlementRouter | Routes to MarketRegistry (settle) or ChannelSettlement (session) |
| Contract | Role |
|---|---|
| MarketPolicy | Policy checks (e.g. min creator seed) |
| MarketDraftBoard | Draft lifecycle: Proposed → Claimed → Published |
| DraftClaimManager | claimAndSeed (primary); custody of locked seed shares until unlock |
| LiquidityVaultFactory | Per-draft ERC-4626 vault deployment |
| MarketFactory | createFromDraft; binds liquidity vault to market |
| CREPublishReceiver | CRE entrypoint for publish-from-draft reports |
| Parameter | Value |
|---|---|
| Chain | Avalanche Fuji (C-Chain) |
| Chain ID | 43113 |
| Explorer | testnet.snowtrace.io |
| Deployer | 0x38A8AB6EE17EB531d86eb877e56005587bC078e7 |
| Compiler | v0.8.24+commit.e11b9ed9 |
| RPC | https://avalanche-fuji.infura.io/v3/... |
Script: DeployBetaTestnet.s.sol — Mock tokens, Faucet, V3-Escrow. Use for beta testers and relayer.
Relayer: CHANNEL_SETTLEMENT_ADDRESS=0xFA5D0e64B0B21374690345d4A88a9748C7E22182
| Component | Technology |
|---|---|
| Framework | Foundry (forge, cast, anvil) |
| Solidity | 0.8.24 |
| Dependencies | OpenZeppelin Contracts |
| Compiler | via_ir, optimizer_runs=200 (EIP-170 compliance) |
| Networks | Avalanche Fuji, Base Sepolia |
- Foundry:
curl -L https://foundry.paradigm.xyz | bash && foundryup
forge build# Full suite
forge test
# E2E tests (production path)
forge test --match-contract E2EDeployTestnetTest
# With verbosity
forge test -vvvDeployTestnet (production-style, real Fuji USDC):
# Copy and configure environment
cp .env.example .env.fuji # or use scripts/env/.env.fuji
# Required: OPERATOR, SETTLEMENT_TOKEN, CHAINLINK_FORWARDER
# Required: MIN_CONFIDENCE, PROTOCOL_FEE_BPS, LP_FEE_SHARE_BPS, CREATOR_FEE_SHARE_BPS
forge script script/DeployTestnet.s.sol:DeployTestnet \
--rpc-url $RPC_URL \
--broadcast \
--private-key $PRIVATE_KEYDeployBetaTestnet (beta testers, mock tokens + Faucet):
source scripts/env/.env.fuji
# Required: OPERATOR, CHAINLINK_FORWARDER, MIN_CONFIDENCE, fee bps
# No SETTLEMENT_TOKEN — uses mock USDC
forge script script/DeployBetaTestnet.s.sol:DeployBetaTestnet \
--rpc-url $RPC_URL \
--broadcast \
--private-key $PRIVATE_KEYDeployTestnet (hardcoded addresses):
source scripts/env/.env.fuji # or .env.fuji at root
chmod +x scripts/verify_fuji_snowtrace_stable.sh
RETRIES=10 SLEEP=12 WATCH=1 scripts/verify_fuji_snowtrace_stable.shDeployBetaTestnet or generic broadcast-based:
source scripts/env/.env.fuji
chmod +x scripts/verify_beta_fuji.sh
WATCH=0 scripts/verify_beta_fuji.sh
# Verify all 24 contracts + export ABIs to docs/abi/:
./scripts/verify_and_export_abis_fuji.sh
# Or ABI export only (no verification):
./scripts/export_abis_to_docs.sh
# Or use godmode for any broadcast:
BROADCAST_FILE=broadcast/DeployBetaTestnet.s.sol/43113/run-latest.json scripts/verify_fuji_godmode.shPropose draft (AI_ORACLE_ROLE) → claimAndSeed (creator EIP-712) →
CREPublishReceiver.onReport → MarketFactory.createFromDraft →
MarketRegistry + setLiquidityVault → markPublished
- Draft must have
settlementAssetandminSeed - claimAndSeed locks seed shares in DraftClaimManager until
tradingClose - Publish requires creator signature; CRE workflow sends report via Forwarder
Off-chain trading (your relayer) → Build checkpoint + deltas → Operator + user signatures →
CRE workflow fetches payload → CREReceiver.onReport(0x03 || payload) →
OracleCoordinator.submitSession → SettlementRouter.finalizeSession →
ChannelSettlement.submitCheckpointFromPayload →
V3-Escrow: reserve(user, netDebit) per debtor; store reserveUsers, reserveAmts →
30min challenge window → finalizeCheckpoint →
OutcomeToken1155 mint/burn sharesDelta → MarketRiskManager.reserveLpPayout (if LP pays) →
applyCashDeltasAndFees → release reserves → MultiAssetVault/CollateralVault + FeeManager
- Relayer config:
CHANNEL_SETTLEMENT_ADDRESS,OPERATOR_PRIVATE_KEY - Checkpoint:
(marketId, sessionId, nonce, stateHash, deltasHash)+Delta[] - Delta:
(user, outcomeIndex, sharesDelta, cashDelta)— sharesDelta drives OutcomeToken1155 mint/burn
CRE outcome report → CREReceiver.onReport → OracleCoordinator.submitResult →
ReportValidator.validate(confidence) → SettlementRouter.settleMarket →
MarketRegistry.onReport(0x01 || ...) → _doResolve(marketId, outcomeIndex, confidence)
- User calls
MarketRegistry.redeem(marketId)when resolved - V3: Reads
OutcomeToken1155.balanceOf(user, tokenId); burns winning shares viaburnForRedeem; payout from MultiAssetVault or CollateralVault - One-shot per (marketId, user)
| Boundary | Enforcement |
|---|---|
| Forwarder | CREReceiver, CREPublishReceiver, MarketFactory: only Forwarder can call onReport |
| Coordinator | OracleCoordinator: only CREReceiver can call submitResult / submitSession |
| Router | SettlementRouter: only OracleCoordinator can call settleMarket / finalizeSession |
| Resolver | MarketRegistry: only SettlementRouter can call resolve / onReport |
| Checkpoint | ChannelSettlement: operator + every delta user must sign; nonce monotonicity; challenge window |
| Publish | MarketFactory: only approved publish receivers; creator EIP-712 signature |
- Every delta user must sign the checkpoint
- Nonce strictly increasing; replay protection
lastTradeAt <= tradingCloseat finalize- Total fee bps capped (2%)
- Seed shares custody-locked in DraftClaimManager until
unlockSeedShares - V3: Accounting invariant
rawSum == netTraderDelta + feesTotal - V3: LP solvency check before LP pays;
LpVaultInsolventrevert - V3-Escrow:
withdraw <= availableBalance; reserve/release only by ChannelSettlement
SecurityHardening.t.sol— unsigned delta, unauthorized resolve, post-close tradeCheckpointFlow.t.sol— hash mismatch, bad sigs, nonce, challenge window (V3: OutcomeToken)CurationFlow.t.sol— seeded publish, draft-time mismatch, share lock custodyInvariantSolvency.t.sol— LP vault requirement, settlement solvencyOutcomeTokenFlow.t.sol— V3: mint/burn, transfer lock, redeem burnRiskManagerFlow.t.sol— V3: reserve within/exceed capEscrowFlow.t.sol— V3-Escrow: reserve, release, withdraw blocked, cancelE2EDeployTestnet.t.sol— V3 full production path end-to-end
| Document | Description |
|---|---|
| docs/deployment/deploymentAvalancheFuji.md | Fuji deployment, addresses, parameters |
| docs/abi/docs/CurrentSmartContract.md | Authoritative V3 architecture, flows, trust model, data structures |
| docs/e2e/e2eAvalanceFujiTest.md | E2E tests, checkpoint flow, wiring |
| docs/abi/docs/ | ABI index, CRE, relayer, frontend integration |
| docs/abi/docs/frontend/ | Frontend — README, Frontend.md, DeploymentConfig |
| docs/abi/docs/cre/ | Chainlink CRE — workflows, report formats, pipeline |
| docs/abi/docs/relayer/ | Relayer — checkpoint format, EIP-712, API |
| Component | Status |
|---|---|
| Execution lane (V3: OutcomeToken1155, MarketRiskManager, ChannelSettlement, vaults) | ✅ Production |
| Oracle + routing (CREReceiver, OracleCoordinator, SettlementRouter) | ✅ Production |
| Curated pipeline (DraftBoard, DraftClaimManager.claimAndSeed, CREPublishReceiver, MarketFactory) | ✅ Production |
| Fee split (protocol/LP/creator) | ✅ Production |
| Checkpoint settlement (V3-Escrow: reserve/release) | ✅ Production |
| Avalanche Fuji deployment (DeployBetaTestnet) | ✅ Verified |
| E2E test suite | ✅ Passing |
| ExecutionLedger | |
| Formal audit | ⏳ Pending |
Set in your relayer config:
| Variable | Purpose |
|---|---|
CHANNEL_SETTLEMENT_ADDRESS |
ChannelSettlement contract (on-chain checkpoint target) |
OPERATOR_PRIVATE_KEY |
Key for checkpoint signing (must match OPERATOR) |
Your relayer builds signed checkpoints; CRE workflow fetches payloads and sends 0x03 reports to CREReceiver. See docs/abi/docs/relayer/ for checkpoint format and EIP-712 signing.
MIT