Install
openclaw skills install committee-prediction-market-skillsCall guide and state-machine conventions for the committee-based prediction market built from GouGouBiMarketFactory, GouGouBiMarketProposal, and GouGouBiMarketCondition, including how to create proposals and conditions, run activation/settlement/dispute voting, and perform CPMM trading and redemption. Use this skill when an Agent needs to handle operations like "create proposal", "committee", "condition", "activation vote", "settlement vote", "dispute", "supreme committee", "redeem", or "buy YES/NO", and when the next call depends on the condition status.
openclaw skills install committee-prediction-market-skillschainId = 56)GouGouBiMarketFactory.sol0x7b0B72e620368d8037406AaDB416e62b6e20f6ac0xb05678Ed0c9559955559DE864829a0c8AF574444 — DOGE is 狗狗币 (Dogecoin). All proposal/supreme committee stakes and vote locks use this token (18 decimals). Caller must approve the Factory (or transfer DOGE) before proposeMarketCreation and stakeForProposalCommittee.Assumptions when calling:
https://bsc-dataseed.binance.org)| Role | Contract file | Description |
|---|---|---|
| Factory | GouGouBiMarketFactory.sol | Create proposals, committee/supreme committee staking, dispute arbitration, reward claiming |
| Proposal | GouGouBiMarketProposal.sol | One clone per proposal; condition creation, activation/settlement voting, dispute, state transitions |
| Condition | GouGouBiMarketCondition.sol | One clone per condition; trading, liquidity, redeem |
Convention: Factory / Proposal / Condition addresses are supplied by upper-layer config (e.g. OpenClaw parameters, environment variables).
All stake and lock amounts below are in DOGE(狗狗币 / Dogecoin) (18 decimals). Values are taken from the deployed Factory and Proposal contracts.
| Constant | Value | Meaning |
|---|---|---|
| MIN_STAKE_AMOUNT | 10 * 1e18 (10 DOGE) | Minimum stake for proposeMarketCreation(..., stakeAmount) and minimum per stakeForProposalCommittee(proposal, amount) when committee has < 3 members. |
| COMMITTEE_MIN_SIZE | 3 | Minimum number of committee members before the proposal can create conditions. |
| Committee stake when full | amount >= avgStake * 2 | When the committee already has ≥ 3 members, a new joiner must stake at least twice the current average stake per member. Use factory.getProposalCommitteeMinStakeToJoin(proposal) to get (minStakeToJoin, isFull). |
| SETTLEMENT_BOND_MIN | 10 * 1e18 (10 DOGE) | Minimum lockAmount for conditionSettlementVoteLock(conditionContract, result, lockAmount) and voteOnConditionResult(..., lockAmount). |
| DISPUTE_BOND_MIN | 10 * 1e18 (10 DOGE) | Minimum lockAmount for initiateDispute(conditionContract, evidence, lockAmount). |
| SUPREME_GOVERNANCE_MIN_LOCK_AMOUNT | 10 * 1e18 (10 DOGE) | Minimum lockAmount for voteConditionDisputeSupreme(conditionContract, result, lockAmount). |
| SUPREME_MIN_STAKE_AMOUNT | 100 * 1e18 (100 DOGE) | Minimum stake for stakeForSupremeCommittee(amount). |
| GOVERNANCE_SIZE | 21 | Number of supreme committee governance members (top 21 by stake) who can call voteConditionDisputeSupreme. |
| Constant | Value | Meaning |
|---|---|---|
| SETTLEMENT_VOTE_WINDOW_SECONDS | 600 (10 min) | Settlement vote is allowed until conditionDeadline + 600. After that, if there are votes, status can move to DISPUTED. |
| DISPUTE_WINDOW_SECONDS | 600 (10 min) | Dispute can be initiated until conditionDeadline + SETTLEMENT_VOTE_WINDOW_SECONDS + DISPUTE_WINDOW_SECONDS. After that, checkConditionStatus can set SETTLED or DISPUTED_INITIATED. |
| Activation threshold | 2/3 | Condition activation: voteOnConditionActivation(conditionContract, approve) — need 2/3 of committee to approve to reach ACTIVE, or 2/3 to reject for REJECTED. |
| Dispute → DISPUTED_INITIATED | Total dispute bonds ≥ 1/10 of winning side’s settlement bonds | After the dispute window ends, if disputeInitiatorTotalBondAmount >= (settlementYesTotalBonds or settlementNoTotalBonds, depending on committee result) / 10, status becomes DISPUTED_INITIATED; otherwise SETTLED (dispute bonds released). |
| Constant | Value | Meaning |
|---|---|---|
| TRADING_FEE_BPS | 30 (0.30%) | Buy fee (buyYes / buyNo). |
| SELL_FEE_BPS | 100 (1%) | Sell fee (sellYes / sellNo). |
| COMMITTEE_REDEEM_FEE_BPS | 100 (1%) | Share of redeem pool to committee winners. |
| SUPREME_COMMITTEE_REDEEM_FEE_BPS | 30 (0.30%) | Share of redeem pool to supreme committee. |
| LpType | 0 = FEE (稳健), 1 = RISK (风险) | For addLiquidity(amount, lpType). |
[1] Factory.proposeMarketCreation(...) → get proposalAddress
[2] Factory.stakeForProposalCommittee(proposalAddress, amount) → at least 3 members
[3] Proposal.createConditions(...) → get conditionContract from events/conditionContracts
[4] Proposal.voteOnConditionActivation(conditionContract, approve) → 2/3 approve → status=ACTIVE(1)
│
▼
[5] If status==ACTIVE and tradeDeadline>now:
Condition.addLiquidity(amount, lpType) / buyYes / buyNo / sellYes / sellNo / swap*
If deadline passed: go to [6]
[6] Committee Proposal.conditionSettlementVoteLock or voteOnConditionResult
Anyone Proposal.checkConditionStatus(conditionContract)
├─ Past settlement window with votes → status=DISPUTED(4)
└─ Still ACTIVE → continue [5] or wait
[7] If status==DISPUTED, within dispute window:
Proposal.initiateDispute(conditionContract, evidence, lockAmount)
Anyone checkConditionStatus(conditionContract)
├─ Past dispute window, no dispute → SETTLED(7)
├─ Past dispute window, dispute stake≥1/10 → DISPUTED_INITIATED(5)
└─ Otherwise keep waiting
[8] If status==DISPUTED_INITIATED:
Factory.voteConditionDisputeSupreme(conditionContract, result, lockAmount)
When satisfied, internally calls Proposal.resolveConditionByFactory → SETTLED(7)
[9] If status==SETTLED:
Condition.redeem() / Condition.claimLp()
Claim committee/supreme committee rewards on Factory
Decision points:
Proposal.conditionStatus(cond)==1 and Condition.tradeDeadline()>block.timestamp.conditionDeadline + 600 (10 min).conditionDeadline + 600 + 600 (20 min after condition deadline).| Enum | Name | Allowed actions |
|---|---|---|
| 0 | CREATED | Activation vote only; 2/3 approve→ACTIVE, reject→REJECTED |
| 1 | ACTIVE | Trading, add/remove LP, committee settlement vote; past settlement window + votes→DISPUTED |
| 2 | REJECTED | No longer used |
| 4 | DISPUTED | initiateDispute; after dispute window checkConditionStatus → SETTLED or DISPUTED_INITIATED |
| 5 | DISPUTED_INITIATED | Supreme committee voteConditionDisputeSupreme; when satisfied → SETTLED |
| 7 | SETTLED | redeem, claimLp; committee/supreme committee claim rewards |
| Task | Contract | Method | Constraints |
|---|---|---|---|
| Create proposal | Factory | proposeMarketCreation(liquidityToken, proposalName, deadline, imageUrl, rules, timezone, language, groupUrl, tags, stakeAmount) | stakeAmount ≥ 10 DOGE (1e19); approve Factory for DOGE first; returns proposalAddress |
| Committee expand | Factory | stakeForProposalCommittee(proposal, amount) | amount ≥ 10 DOGE; if committee already ≥3, amount ≥ 2× avg stake (use getProposalCommitteeMinStakeToJoin) |
| Create condition | Proposal | createConditions(conditionName, deadline, tradeDeadline, conditionImageUrl, rules, isNormalized) | Caller must be proposal committee member; committee ≥ 3 |
| Activation vote | Proposal | voteOnConditionActivation(conditionContract, approve) | status==CREATED; 2/3 approves → ACTIVE, 2/3 rejects → REJECTED |
| Read status | Proposal | conditionStatus(conditionContract) | Authoritative; read first then decide next call |
| Advance status | Proposal | checkConditionStatus(conditionContract) | Anyone can call; updates status by time and votes |
| Settlement vote | Proposal | conditionSettlementVoteLock(conditionContract, result, lockAmount) or voteOnConditionResult(conditionContract, result, evidence, lockAmount) | result: 1=YES, 2=NO; lockAmount ≥ 10 DOGE; within conditionDeadline+600 |
| Initiate dispute | Proposal | initiateDispute(conditionContract, evidence, lockAmount) | status==DISPUTED; lockAmount ≥ 10 DOGE; within dispute window (deadline+1200) |
| Supreme committee vote | Factory | voteConditionDisputeSupreme(conditionContract, result, lockAmount) | Caller in top 21 governance; result 1=YES, 2=NO; lockAmount ≥ 10 DOGE |
| Add liquidity | Condition | addLiquidity(amount, lpType) | status==ACTIVE, tradeDeadline>now; lpType 0=FEE, 1=RISK |
| Buy/sell/swap | Condition | buyYes(tokenIn, minYesOut)/buyNo/sellYes/sellNo/swapYesForNo/swapNoForYes | status==ACTIVE, tradeDeadline>now |
| Redeem | Condition | redeem() / claimLp() | status==SETTLED |
conditionDeadline + 600 (10 min); dispute window: +600 (10 min) after that.factory.dogeToken(); approve Factory before proposeMarketCreation and stakeForProposalCommittee.Full ABI (recommended for production/subgraph):
subgraph/abis/GouGouBiMarketFactory.jsonsubgraph/abis/GouGouBiMarketProposal.jsonsubgraph/abis/GouGouBiMarketCondition.jsonBelow is a minimal ABI of commonly used methods and key events for Agents; use with ethers/viem (deduplicate when merging with full ABI).
[
{"type":"function","name":"proposeMarketCreation","inputs":[{"name":"liquidityToken","type":"address"},{"name":"proposalName","type":"string"},{"name":"deadline","type":"uint256"},{"name":"imageUrl","type":"string"},{"name":"rules","type":"string"},{"name":"timezone","type":"string"},{"name":"language","type":"string"},{"name":"groupUrl","type":"string"},{"name":"tags","type":"string[]"},{"name":"stakeAmount","type":"uint256"}],"outputs":[{"name":"proposalAddress","type":"address"}],"stateMutability":"nonpayable"},
{"type":"function","name":"stakeForProposalCommittee","inputs":[{"name":"proposal","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},
{"type":"function","name":"getProposalCommitteeMembers","inputs":[{"name":"proposal","type":"address"}],"outputs":[{"name":"","type":"address[]"}],"stateMutability":"view"},
{"type":"function","name":"voteConditionDisputeSupreme","inputs":[{"name":"conditionContract","type":"address"},{"name":"result","type":"uint8"},{"name":"amount","type":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},
{"type":"function","name":"MIN_STAKE_AMOUNT","inputs":[],"outputs":[{"type":"uint256"}],"stateMutability":"view"},
{"type":"function","name":"COMMITTEE_MIN_SIZE","inputs":[],"outputs":[{"type":"uint256"}],"stateMutability":"view"},
{"type":"function","name":"getProposalCommitteeMinStakeToJoin","inputs":[{"name":"proposal","type":"address"}],"outputs":[{"name":"minStakeToJoin","type":"uint256"},{"name":"isFull","type":"bool"}],"stateMutability":"view"},
{"type":"function","name":"dogeToken","inputs":[],"outputs":[{"type":"address"}],"stateMutability":"view"},
{"type":"event","name":"ProposalCreatedWithStake","inputs":[{"indexed":true,"name":"proposer","type":"address"},{"indexed":true,"name":"proposal","type":"address"},{"indexed":false,"name":"stakeAmount","type":"uint256"}]}
]
[
{"type":"function","name":"createConditions","inputs":[{"name":"_conditionName","type":"string"},{"name":"_deadline","type":"uint256"},{"name":"_tradeDeadline","type":"uint256"},{"name":"_conditionImageUrl","type":"string"},{"name":"_rules","type":"string"},{"name":"_isNormalized","type":"bool"}],"outputs":[],"stateMutability":"nonpayable"},
{"type":"function","name":"voteOnConditionActivation","inputs":[{"name":"conditionContract","type":"address"},{"name":"approve","type":"bool"}],"outputs":[],"stateMutability":"nonpayable"},
{"type":"function","name":"conditionStatus","inputs":[{"name":"conditionContract","type":"address"}],"outputs":[{"name":"","type":"uint8"}],"stateMutability":"view"},
{"type":"function","name":"conditionResult","inputs":[{"name":"conditionContract","type":"address"}],"outputs":[{"name":"","type":"uint8"}],"stateMutability":"view"},
{"type":"function","name":"conditionDeadline","inputs":[{"name":"conditionContract","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
{"type":"function","name":"checkConditionStatus","inputs":[{"name":"conditionContract","type":"address"}],"outputs":[],"stateMutability":"nonpayable"},
{"type":"function","name":"conditionSettlementVoteLock","inputs":[{"name":"conditionContract","type":"address"},{"name":"result","type":"uint8"},{"name":"lockAmount","type":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},
{"type":"function","name":"voteOnConditionResult","inputs":[{"name":"conditionContract","type":"address"},{"name":"result","type":"uint8"},{"name":"evidence","type":"string"},{"name":"lockAmount","type":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},
{"type":"function","name":"initiateDispute","inputs":[{"name":"conditionContract","type":"address"},{"name":"evidence","type":"string"},{"name":"lockAmount","type":"uint256"}],"outputs":[],"stateMutability":"payable"},
{"type":"function","name":"conditionContracts","inputs":[{"name":"","type":"uint256"}],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
{"type":"event","name":"ConditionCreated","inputs":[{"indexed":true,"name":"conditionContract","type":"address"},{"indexed":false,"name":"conditionName","type":"string"},{"indexed":false,"name":"deadline","type":"uint256"},{"indexed":false,"name":"tradeDeadline","type":"uint256"},{"indexed":false,"name":"yesToken","type":"address"},{"indexed":false,"name":"noToken","type":"address"}]},
{"type":"event","name":"ConditionStatusUpdated","inputs":[{"indexed":true,"name":"conditionContract","type":"address"},{"indexed":false,"name":"status","type":"uint8"}]}
]
[
{"type":"function","name":"addLiquidity","inputs":[{"name":"amount","type":"uint256"},{"name":"lpType","type":"uint8"}],"outputs":[],"stateMutability":"payable"},
{"type":"function","name":"buyYes","inputs":[{"name":"tokenIn","type":"uint256"},{"name":"minYesOut","type":"uint256"}],"outputs":[],"stateMutability":"payable"},
{"type":"function","name":"buyNo","inputs":[{"name":"tokenIn","type":"uint256"},{"name":"minNoOut","type":"uint256"}],"outputs":[],"stateMutability":"payable"},
{"type":"function","name":"sellYes","inputs":[{"name":"amountIn","type":"uint256"},{"name":"minAmountOut","type":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},
{"type":"function","name":"sellNo","inputs":[{"name":"amountIn","type":"uint256"},{"name":"minAmountOut","type":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},
{"type":"function","name":"swapYesForNo","inputs":[{"name":"amountIn","type":"uint256"},{"name":"minAmountOut","type":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},
{"type":"function","name":"swapNoForYes","inputs":[{"name":"amountIn","type":"uint256"},{"name":"minAmountOut","type":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},
{"type":"function","name":"redeem","inputs":[],"outputs":[],"stateMutability":"nonpayable"},
{"type":"function","name":"claimLp","inputs":[],"outputs":[],"stateMutability":"nonpayable"},
{"type":"function","name":"tradeDeadline","inputs":[],"outputs":[{"name":"","type":"uint256"}],"stateMutability":"view"},
{"type":"function","name":"liquidityToken","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
{"type":"function","name":"yesToken","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
{"type":"function","name":"noToken","inputs":[],"outputs":[{"name":"","type":"address"}],"stateMutability":"view"},
{"type":"event","name":"BuyYes","inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":false,"name":"tokenIn","type":"uint256"},{"indexed":false,"name":"totalYesOut","type":"uint256"}]},
{"type":"event","name":"Redeem","inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":false,"name":"userShare","type":"uint256"},{"indexed":false,"name":"totalShare","type":"uint256"},{"indexed":false,"name":"payout","type":"uint256"}]}
]
Usage examples (ethers v6):
const status = await proposalContract.conditionStatus(conditionAddress).const tx = await factoryContract.proposeMarketCreation(...); const rec = await tx.wait(); get proposalAddress from events or return value.conditionContract from event ConditionCreated or proposalContract.conditionContracts(index).