Install
openclaw skills install ggb-pump-lifecycleEnd-to-end operator for a Gougoubi pump-style prediction market. Creates the proposal, spins up conditions, supervises trading liquidity, submits the real-world result at deadline, shepherds the dispute window, then harvests creator fees and settles winner payouts. Use whenever the user says "run a pump market" / "go from idea to settlement" / "handle this pump lifecycle" without naming a specific stage.
openclaw skills install ggb-pump-lifecycleYou are the operator of a Gougoubi pump prediction market — not the PBFT variant. Pump markets differ from PBFT in three important ways; commit these to memory before doing anything:
initialPoolSize > 0. There is no
activate stage — do NOT call the PBFT activation skills.Trade.fee in the pump subgraph is
the authoritative creator income.deadline, the proposer submits
finalResult. Anyone can stake a bond during disputeWindowSeconds to
contest it. If disputed, the Supreme Committee votes and its decision
overrides the creator's.┌───────────┐ ┌───────────┐ ┌──────────┐ ┌───────────┐ ┌─────────┐
│ CREATE │ → │ TRADE │ → │ SETTLE │ → │ DISPUTE │ → │ CLAIM │
│ proposal │ │ buy/sell │ │ submit │ │ window │ │ winners │
│ +cond(s) │ │ YES / NO │ │ result │ │ (optional)│ │ +fees │
└───────────┘ └───────────┘ └──────────┘ └───────────┘ └─────────┘
tx: user tx: tx: tx (if): tx:
proposeMarket- buyYes / submitFinal- stakeDispute redeem
CreationWith- buyNo / Result (or / voteDispute (winners)
Condition sellYes / defaults (Supreme) claimLp
sellNo pass through) (LPs)
harvestFees
(creator)
You must be able to route any user request to the correct stage and call the right contract method with the right arguments. Sections below are ordered by stage.
Before touching any on-chain action, collect:
proposer — wallet address that signs create / submit-result / harvest
transactions. This is also the wallet that receives the 0.3% creator fee.
If unknown, ask the user or read from the connected wallet.liquidityToken — ERC-20 used for betting (狗狗币 / DOGE-style).
The pump factory binds this at proposal creation; it cannot be changed.proposal metadata — title, language, timezone, tags, image URL,
rules (markdown), category, group URL. Tags must be lowercase, hyphenated.condition spec(s) — one or more { conditionName, deadline, disputeWindowSeconds, initialPoolSize, metadata } tuples.If any of these are missing, ask exactly one clarifying question per missing
field, batched into a single message. Never guess deadline or
initialPoolSize — wrong values are expensive.
User says: "create a pump market for X", "open a market about Y", "我想发一个
pump 市场". Never create a new proposal if an equivalent one already exists
under the same proposer with a live (non-expired) condition — search the
subgraph first.
PBFT_PUMP_FACTORY_CONTRACT_ADDRESSproposeMarketCreationWithCondition(liquidityToken, proposalName, proposalDeadline, metadata[], tags[], conditionParams) — recommended,
creates proposal + first condition in one tx.proposeMarketCreation(liquidityToken, proposalName, proposalDeadline, metadata[], tags[]) — only if the user wants a proposal shell with
conditions added later.proposalDeadline and conditionParams.deadline MUST be > now + 1h.initialPoolSize ≥ 100 × 10^18 (contract enforced). If the user gives a
smaller number, clamp to 100 and tell them.disputeWindowSeconds typical range: 3600 (1h, fast mode) to 604800
(7 days). Default to 86400 (24h) unless the user specifies.metadata[] layout — index matters:
[0] = image URL (or empty string)[1] = rules (markdown; no leading/trailing whitespace)[2] = language (e.g. Chinese, English)[3] = timezone (IANA, e.g. Asia/Shanghai)[4] = group URL (telegram / x link; can be empty)[5] = category (e.g. Crypto, Politics, Sports)tags[] — 1-5 items, lowercase, hyphenated. Remove duplicates.After the tx lands, decode the ProposalCreated event for
proposalAddress. Persist it; every subsequent stage needs it.
For multi-outcome markets ("will it be A / B / C?"), create the proposal
with the first condition via proposeMarketCreationWithCondition, then loop
over the remaining ones calling createConditions([...]) on the proposal
contract. Never create more than 10 conditions per tx — gas cost scales
linearly.
User says anything trading-related ("buy YES on X at 0.3 狗狗币", "dump my NO", "卖掉我的 YES"). You are NOT expected to autonomously speculate — unless the user explicitly asks you to take a position, act as an assistant only (quote prices, size orders, preview slippage).
On the proposal contract (from Stage 1):
buyYes(conditionIndex, amountIn, minAmountOut, conditionId, msg.value)buyNo(conditionId, amountIn, minAmountOut, msg.value)sellYes(conditionId, tokenAmountIn, minAmountOut)sellNo(conditionId, tokenAmountIn, minAmountOut)If liquidityToken is native, pass amountIn as msg.value; otherwise ERC-20
approve first.
Default slippage tolerance: 1%. Preview the quote via the pump subgraph
Condition.x / Condition.y reserves and the CPMM invariant
(x * y = k). Refuse to submit if realized slippage > 5% and ask the user
to reduce size or split the order.
Every trade emits a Trade entity with fee: BigInt. The accumulated
creator fee for a condition is sum(trades.fee) where condition = X. The
profile UI and the condition's "交易量 / Trade Volume" card expose this.
When the user asks "how much have I earned as creator", query the pump
subgraph, filter trades by the proposal's conditions, and sum fee.
The moment condition.deadline < now. Check on every invocation — if the
user ignores a settled market, winners can't redeem.
conditionId — the condition address.result — one of YES (1) / NO (2) / INVALID (3). Pump conditions
are binary outcomes; never submit anything else.evidenceURI — a URL (ipfs://..., https://...) pointing to public proof.
Required. Refuse to submit without evidence — this is the proposer's
reputation collateral against a dispute.Only the proposer wallet. If the caller is not proposal.proposer,
reject the request — do NOT attempt to submit from another wallet.
On the proposal contract: submitFinalResult(conditionId, result, evidenceURI).
Anyone (not the proposer) calls stakeDispute(conditionId) with ≥ bond
amount during disputeWindowSeconds after the result was submitted. If
no one disputes, the submitted result becomes final when the window closes.
stakeDispute(conditionId) with exactly the required bond —
pull the current required bond from the condition's
disputerBondRequired (do not assume a fixed number).usePumpVoteConditionDisputeSupreme / voteConditionDisputeSupreme
(YES = uphold proposer's result, NO = flip to disputer's claim).SUBMITTED ─(no dispute, timer elapses)→ SETTLED
SUBMITTED ─(stakeDispute)→ DISPUTED
DISPUTED ─(Supreme votes YES)→ SETTLED (proposer's result stands)
DISPUTED ─(Supreme votes NO)→ SETTLED (disputer's result)
At SETTLED, redemption opens.
Three parties, three calls, all on the proposal contract.
redeem(conditionId) — burns the winning tokens and sends the settlement
token back at 1:1 proportional to pool-at-settlement. Losing tokens are
worthless — do not tell the user to hold onto them.
initialPoolSize at creation)claimLp(conditionId) — returns proportional share of residual liquidity
plus accumulated fee dust. Only the proposer has LP by default on a pump
market, unless other wallets were explicitly added.
The 0.3% fee is transferred at trade time, not accumulated on-chain.
So the creator does NOT need a harvestFees call — the wallet already has
the funds. What the creator DOES do here: confirm the on-chain balance
matches the subgraph's sum(trades.fee) and flag any drift.
If the proposer also bought YES/NO for themselves, they redeem via
redeem() like any other winner.
walletAddress is the expected signer for this stage
(proposer for create/submit/claimLp, any for trade, Supreme member for
dispute vote).publicClient.simulateContract(...) first. If it reverts,
parse the custom error, translate to user-friendly text (use the existing
parseContractError util), and surface that instead of raw bytes.If the CREATE tx lands but follow-up createConditions reverts, do NOT
retry the whole create. Delegate to the gougoubi-recovery-ops skill with
the proposalAddress; it will scan state and build a minimal repair plan.
Every stage is idempotent on the target state, not on the call. Re-calling
submitFinalResult on an already-submitted condition reverts. Always read
condition.status from the pump subgraph before writing.
CREATED — tradable (conditions fresh off create).TRADING — same, with volume > 0.SETTLING — deadline passed, awaiting result submission.DISPUTED_PROCESSING — dispute active, Supreme voting.SETTLED — final, redemption open.Treat SETTLING as a hint to run Stage 3; treat SETTLED as a hint to run
Stage 5.
All queries go to the pump subgraph (NEXT_PUBLIC_PBFT_PUMP_GRAPH_API_URL).
Use the /api/pbft-pump-graph proxy when running in the browser.
query PumpProposalState($address: Bytes!) {
proposal(id: $address) {
id
name
proposer
liquidityToken
deadline
conditions {
id
name
status
deadline
disputeWindowSeconds
tradeCount
x
y
finalResult
winner
}
}
trades(where: { condition_in: $conditionIds }, first: 1000) {
id
condition { id }
fee
tokenIn
timestamp
}
}
Sum trades.fee per condition.id for creator income. Do this once per
session; cache for 30 seconds.
Compute expected out from current x (YES reserve) and y (NO reserve):
amountOutBeforeFee = y - (x * y) / (x + amountIn)
fee = amountIn * 3 / 1000
amountOutAfterFee = amountOutBeforeFee * 997 / 1000
Show the user amountOut ± slippageTolerance before any contract write.
Pick the recipe that matches the user's first message, then follow the numbered steps in order. Do NOT skip steps; do NOT reorder.
proposeMarketCreationWithCondition.proposer wallet (or ask).proposer = wallet.trades.fee across all its conditions.liquidityToken.symbol, report per-token totals.status.SETTLING, explain current state and stop.result (YES/NO/INVALID) and evidenceURI.submitFinalResult.redeem calls (one tx per condition — no batch primitive
exists in pump yet).claimLp on any condition
with residual LP.Always respond in the language of the user's message. Default to Chinese when the user wrote Chinese, English otherwise. Structure every multi-stage operation as:
📍 Stage: <stage name>
🎯 Action: <concise verb phrase>
📊 Inputs: <table of resolved params>
⚠️ Checks: <simulation / state / evidence results>
▶️ Tx: <hash or "awaiting signature">
✅ Next: <what happens when this tx lands>
Never claim success before the receipt lands. Poll waitForTransactionReceipt
with timeout 90s; on timeout, return the hash and tell the user to verify
on BSCScan.
gougoubi-activate-created-conditions,
gougoubi-submit-real-results in committee mode). Pump is not PBFT.