Aavegotchi GBM Skill
/install aavegotchi-gbm-skill
Safety Rules
- Default to
DRY_RUN=1. Never broadcast unless explicitly instructed. - Always verify Base mainnet:
~/.foundry/bin/cast chain-id --rpc-url "${BASE_MAINNET_RPC:-https://mainnet.base.org}"must be8453.
- Always verify key/address alignment:
~/.foundry/bin/cast wallet address --private-key "$PRIVATE_KEY"must equal$FROM_ADDRESS.
- Always refetch from the subgraph immediately before any simulate/broadcast step (auctions can be outbid, ended, claimed, or cancelled).
- Always gate onchain immediately before simulating or broadcasting:
- ensure the onchain
highestBidmatches thehighestBidyou pass intocommitBid/swapAndCommitBid. - ensure token params match (token contract, token id, quantity).
- ensure the onchain
- Never print or log
$PRIVATE_KEY.
Shell Input Safety (Avoid RCE)
This skill includes shell commands. Treat any value you copy from a user or an external source (subgraph responses, chat messages, etc.) as untrusted.
Rules:
- Never execute user-provided strings as shell code (avoid
eval,bash -c,sh -c). - Only substitute addresses that match
0x+ 40 hex chars. - Only substitute uint values that are base-10 digits (no commas, no decimals).
- In the command examples below, auction-specific inputs are written as quoted placeholders like
"\x3CAUCTION_ID>"to avoid accidental shell interpolation. Replace them with literal values only after validation.
Quick validators (replace the placeholder values):
python3 - \x3C\x3C'PY'
import re
auction_id = "\x3CAUCTION_ID>" # digits only
token_contract = "\x3CTOKEN_CONTRACT_ADDRESS>" # 0x + 40 hex chars
token_id = "\x3CTOKEN_ID>" # digits only
amount = "\x3CTOKEN_AMOUNT>" # digits only
if not re.fullmatch(r"[0-9]+", auction_id):
raise SystemExit("AUCTION_ID must be base-10 digits only")
if not re.fullmatch(r"0x[a-fA-F0-9]{40}", token_contract):
raise SystemExit("TOKEN_CONTRACT_ADDRESS must be a 0x + 40-hex address")
if not re.fullmatch(r"[0-9]+", token_id):
raise SystemExit("TOKEN_ID must be base-10 digits only")
if not re.fullmatch(r"[0-9]+", amount):
raise SystemExit("TOKEN_AMOUNT must be base-10 digits only")
print("ok")
PY
Required Setup
Required env vars:
PRIVATE_KEY: EOA private key used forcast send(never print/log).FROM_ADDRESS: EOA address that owns NFTs and will submit txs.BASE_MAINNET_RPC: RPC URL. If unset, usehttps://mainnet.base.org.GBM_SUBGRAPH_URL: Goldsky subgraph endpoint for auctions.
Optional env vars:
DRY_RUN:1(default) to only simulate viacast call. Set to0to broadcast viacast send.RECIPIENT_ADDRESS: for swap flows; receives any excess GHST refunded by the contract. Defaults toFROM_ADDRESS.GOLDSKY_API_KEY: optional; if set, includeAuthorization: Bearer ...header in subgraph calls.SLIPPAGE_PCT: defaults to1(%); used inswapAmountestimate math.GHST_USD_PRICE,ETH_USD_PRICE: optional overrides; if unset, fetch from CoinGecko in the swap math snippets.
Recommended defaults (override via env if needed):
export BASE_MAINNET_RPC="${BASE_MAINNET_RPC:-https://mainnet.base.org}"
export GBM_DIAMOND="${GBM_DIAMOND:-0x80320A0000C7A6a34086E2ACAD6915Ff57FfDA31}"
export GHST="${GHST:-0xcD2F22236DD9Dfe2356D7C543161D4d260FD9BcB}"
export USDC="${USDC:-0x833589fCD6eDb6E08f4c7C32D4f71b54BDA02913}"
export GBM_SUBGRAPH_URL="${GBM_SUBGRAPH_URL:-https://api.goldsky.com/api/public/project_cmh3flagm0001r4p25foufjtt/subgraphs/aavegotchi-gbm-baazaar-base/prod/gn}"
export DRY_RUN="${DRY_RUN:-1}"
export SLIPPAGE_PCT="${SLIPPAGE_PCT:-1}"
Notes:
- Commands below use
~/.foundry/bin/castso they work in cron/non-interactive shells.
View / List Auctions (Subgraph First)
See references/subgraph.md for canonical queries.
Auction by id (quick):
curl -s "$GBM_SUBGRAPH_URL" -H 'content-type: application/json' ${GOLDSKY_API_KEY:+-H "Authorization: Bearer $GOLDSKY_API_KEY"} --data '{
"query":"query($id:ID!){ auction(id:$id){ id type contractAddress tokenId quantity seller highestBid highestBidder totalBids startsAt endsAt claimAt claimed cancelled presetId category buyNowPrice startBidPrice } }",
"variables":{"id":"\x3CAUCTION_ID>"}
}'
Active auctions (ends soonest first):
NOW=$(date +%s)
curl -s "$GBM_SUBGRAPH_URL" -H 'content-type: application/json' ${GOLDSKY_API_KEY:+-H "Authorization: Bearer $GOLDSKY_API_KEY"} --data "{
\"query\":\"query(\$now:BigInt!){ auctions(first:20, orderBy: endsAt, orderDirection: asc, where:{claimed:false, cancelled:false, startsAt_lte:\$now, endsAt_gt:\$now}){ id type contractAddress tokenId quantity highestBid highestBidder totalBids startsAt endsAt claimAt presetId category seller } }\",
\"variables\":{\"now\":\"$NOW\"}
}"
Onchain Verification (Required Before Bids / Sends)
The onchain source of truth is the GBM diamond.
Confirm core auction fields (full struct decode):
~/.foundry/bin/cast call "$GBM_DIAMOND" \
'getAuctionInfo(uint256)((address,uint96,address,uint88,uint88,bool,bool,address,(uint80,uint80,uint56,uint8,bytes4,uint256,uint96,uint96),(uint64,uint64,uint64,uint64,uint256),uint96,uint96))' \
"\x3CAUCTION_ID>" \
--rpc-url "$BASE_MAINNET_RPC"
Useful individual getters:
~/.foundry/bin/cast call "$GBM_DIAMOND" 'getAuctionHighestBid(uint256)(uint256)' "\x3CAUCTION_ID>" --rpc-url "$BASE_MAINNET_RPC"
~/.foundry/bin/cast call "$GBM_DIAMOND" 'getAuctionHighestBidder(uint256)(address)' "\x3CAUCTION_ID>" --rpc-url "$BASE_MAINNET_RPC"
~/.foundry/bin/cast call "$GBM_DIAMOND" 'getAuctionStartTime(uint256)(uint256)' "\x3CAUCTION_ID>" --rpc-url "$BASE_MAINNET_RPC"
~/.foundry/bin/cast call "$GBM_DIAMOND" 'getAuctionEndTime(uint256)(uint256)' "\x3CAUCTION_ID>" --rpc-url "$BASE_MAINNET_RPC"
~/.foundry/bin/cast call "$GBM_DIAMOND" 'getContractAddress(uint256)(address)' "\x3CAUCTION_ID>" --rpc-url "$BASE_MAINNET_RPC"
~/.foundry/bin/cast call "$GBM_DIAMOND" 'getTokenId(uint256)(uint256)' "\x3CAUCTION_ID>" --rpc-url "$BASE_MAINNET_RPC"
~/.foundry/bin/cast call "$GBM_DIAMOND" 'getTokenKind(uint256)(bytes4)' "\x3CAUCTION_ID>" --rpc-url "$BASE_MAINNET_RPC"
Create Auction
Onchain method:
createAuction((uint80,uint80,uint56,uint8,bytes4,uint256,uint96,uint96),address,uint256)(uint256)
High-level steps:
- Ensure the token contract is whitelisted on the GBM diamond (otherwise revert
ContractNotAllowed). - Ensure the token is approved to the GBM diamond:
- ERC721/1155:
setApprovalForAll(GBM_DIAMOND,true)
- ERC721/1155:
- Choose
InitiatorInfo:startTimemust be in the future.endTime - startTimemust be between 3600 and 604800 seconds (1h to 7d).tokenKindis0x73ad2146(ERC721) or0x973bb640(ERC1155).buyItNowPriceoptional;startingBidoptional (if nonzero, you must approve GHST for the 4% prepaid fee).
- Simulate with
cast callusing--from "$FROM_ADDRESS". - Broadcast with
cast sendonly when explicitly instructed (DRY_RUN=0). - Post-tx: query subgraph for newest seller auctions and match
(contractAddress, tokenId).
Simulate create (ERC721 example):
~/.foundry/bin/cast call "$GBM_DIAMOND" \
'createAuction((uint80,uint80,uint56,uint8,bytes4,uint256,uint96,uint96),address,uint256)(uint256)' \
"(\x3CSTART_TIME>,\x3CEND_TIME>,1,\x3CCATEGORY>,0x73ad2146,\x3CTOKEN_ID>,\x3CBUY_NOW_GHST_WEI>,\x3CSTARTING_BID_GHST_WEI>)" \
"\x3CERC721_CONTRACT_ADDRESS>" "\x3CPRESET_ID>" \
--from "$FROM_ADDRESS" \
--rpc-url "$BASE_MAINNET_RPC"
Broadcast create (only when explicitly instructed):
~/.foundry/bin/cast send "$GBM_DIAMOND" \
'createAuction((uint80,uint80,uint56,uint8,bytes4,uint256,uint96,uint96),address,uint256)(uint256)' \
"(\x3CSTART_TIME>,\x3CEND_TIME>,1,\x3CCATEGORY>,0x73ad2146,\x3CTOKEN_ID>,\x3CBUY_NOW_GHST_WEI>,\x3CSTARTING_BID_GHST_WEI>)" \
"\x3CERC721_CONTRACT_ADDRESS>" "\x3CPRESET_ID>" \
--private-key "$PRIVATE_KEY" \
--rpc-url "$BASE_MAINNET_RPC"
Post-create (find your newest auctions and confirm):
curl -s "$GBM_SUBGRAPH_URL" -H 'content-type: application/json' ${GOLDSKY_API_KEY:+-H "Authorization: Bearer $GOLDSKY_API_KEY"} --data '{
"query":"query($seller:Bytes!){ auctions(first:10, orderBy: createdAt, orderDirection: desc, where:{seller:$seller}){ id type contractAddress tokenId quantity createdAt startsAt endsAt claimed cancelled } }",
"variables":{"seller":"\x3CFROM_ADDRESS_LOWERCASE>"}
}'
Cancel Auction
Onchain method:
cancelAuction(uint256)
Steps:
- Subgraph: check
claimed,cancelled,endsAt,highestBid. - Onchain: call
getAuctionInfo(auctionId)to verify ownership and state. - Simulate with
cast call(--from "$FROM_ADDRESS"). - Broadcast only when explicitly instructed.
Simulate:
~/.foundry/bin/cast call "$GBM_DIAMOND" 'cancelAuction(uint256)' "\x3CAUCTION_ID>" \
--from "$FROM_ADDRESS" \
--rpc-url "$BASE_MAINNET_RPC"
Broadcast (only when explicitly instructed):
~/.foundry/bin/cast send "$GBM_DIAMOND" 'cancelAuction(uint256)' "\x3CAUCTION_ID>" \
--private-key "$PRIVATE_KEY" \
--rpc-url "$BASE_MAINNET_RPC"
Bid With GHST (commitBid)
Onchain method:
commitBid(uint256,uint256,uint256,address,uint256,uint256,bytes)(lastbytesis ignored; pass0x)
Steps:
- Subgraph: fetch auction fields (id, contractAddress, tokenId, quantity, highestBid, startsAt, endsAt, claimed/cancelled).
- Onchain: refetch
highestBidand token params; you must pass the exact current onchainhighestBidor it revertsUnmatchedHighestBid. - Compute a safe minimum next bid using
references/bid-math.md(uses onchainbidDecimals+stepMin). - Ensure GHST allowance to the GBM diamond covers
bidAmount. - Simulate via
cast call(optional but recommended). - Broadcast only when explicitly instructed.
Simulate:
~/.foundry/bin/cast call "$GBM_DIAMOND" \
'commitBid(uint256,uint256,uint256,address,uint256,uint256,bytes)' \
"\x3CAUCTION_ID>" "\x3CBID_AMOUNT_GHST_WEI>" "\x3CHIGHEST_BID_GHST_WEI>" "\x3CTOKEN_CONTRACT_ADDRESS>" "\x3CTOKEN_ID>" "\x3CTOKEN_AMOUNT>" 0x \
--from "$FROM_ADDRESS" \
--rpc-url "$BASE_MAINNET_RPC"
Broadcast (only when explicitly instructed):
~/.foundry/bin/cast send "$GBM_DIAMOND" \
'commitBid(uint256,uint256,uint256,address,uint256,uint256,bytes)' \
"\x3CAUCTION_ID>" "\x3CBID_AMOUNT_GHST_WEI>" "\x3CHIGHEST_BID_GHST_WEI>" "\x3CTOKEN_CONTRACT_ADDRESS>" "\x3CTOKEN_ID>" "\x3CTOKEN_AMOUNT>" 0x \
--private-key "$PRIVATE_KEY" \
--rpc-url "$BASE_MAINNET_RPC"
Bid With USDC Swap (swapAndCommitBid)
Onchain method:
swapAndCommitBid((address,uint256,uint256,uint256,address,uint256,uint256,uint256,address,uint256,uint256,bytes))
Struct fields (in order):
tokenIn(USDC)swapAmount(USDC 6dp)minGhstOut(GHST wei; must be >= bidAmount)swapDeadline(unix; must be \x3C= now + 86400)recipient(refund receiver for excess GHST)auctionIDbidAmount(GHST wei)highestBid(must match onchain)tokenContracttokenIDamount(tokenAmount/quantity)_signature(ignored; pass0x)
Compute swapAmount estimate in references/swap-math.md.
Simulate:
~/.foundry/bin/cast call "$GBM_DIAMOND" \
'swapAndCommitBid((address,uint256,uint256,uint256,address,uint256,uint256,uint256,address,uint256,uint256,bytes))' \
"($USDC,\x3CSWAP_AMOUNT_USDC_6DP>,\x3CMIN_GHST_OUT_GHST_WEI>,\x3CSWAP_DEADLINE_UNIX>,${RECIPIENT_ADDRESS:-$FROM_ADDRESS},\x3CAUCTION_ID>,\x3CBID_AMOUNT_GHST_WEI>,\x3CHIGHEST_BID_GHST_WEI>,\x3CTOKEN_CONTRACT_ADDRESS>,\x3CTOKEN_ID>,\x3CTOKEN_AMOUNT>,0x)" \
--from "$FROM_ADDRESS" \
--rpc-url "$BASE_MAINNET_RPC"
Broadcast (only when explicitly instructed):
~/.foundry/bin/cast send "$GBM_DIAMOND" \
'swapAndCommitBid((address,uint256,uint256,uint256,address,uint256,uint256,uint256,address,uint256,uint256,bytes))' \
"($USDC,\x3CSWAP_AMOUNT_USDC_6DP>,\x3CMIN_GHST_OUT_GHST_WEI>,\x3CSWAP_DEADLINE_UNIX>,${RECIPIENT_ADDRESS:-$FROM_ADDRESS},\x3CAUCTION_ID>,\x3CBID_AMOUNT_GHST_WEI>,\x3CHIGHEST_BID_GHST_WEI>,\x3CTOKEN_CONTRACT_ADDRESS>,\x3CTOKEN_ID>,\x3CTOKEN_AMOUNT>,0x)" \
--private-key "$PRIVATE_KEY" \
--rpc-url "$BASE_MAINNET_RPC"
Bid With ETH Swap (swapAndCommitBid)
Same method as above, but:
tokenIn = 0x0000000000000000000000000000000000000000--value \x3CSWAP_AMOUNT_WEI>must equal theswapAmountyou pass inside the tuple.
Broadcast (only when explicitly instructed):
~/.foundry/bin/cast send "$GBM_DIAMOND" \
'swapAndCommitBid((address,uint256,uint256,uint256,address,uint256,uint256,uint256,address,uint256,uint256,bytes))' \
"(0x0000000000000000000000000000000000000000,\x3CSWAP_AMOUNT_WEI>,\x3CMIN_GHST_OUT_GHST_WEI>,\x3CSWAP_DEADLINE_UNIX>,${RECIPIENT_ADDRESS:-$FROM_ADDRESS},\x3CAUCTION_ID>,\x3CBID_AMOUNT_GHST_WEI>,\x3CHIGHEST_BID_GHST_WEI>,\x3CTOKEN_CONTRACT_ADDRESS>,\x3CTOKEN_ID>,\x3CTOKEN_AMOUNT>,0x)" \
--value "\x3CSWAP_AMOUNT_WEI>" \
--private-key "$PRIVATE_KEY" \
--rpc-url "$BASE_MAINNET_RPC"
Claim Auction
Onchain methods:
claim(uint256)batchClaim(uint256[])
Claim readiness:
- Auction owner can claim at
now >= endsAt. - Highest bidder can claim at
now >= endsAt + cancellationTime.cancellationTimeis readable from storage slot 12 (seereferences/recipes.md).- Subgraph may provide
claimAt(if populated), but always verify onchain.
Simulate:
~/.foundry/bin/cast call "$GBM_DIAMOND" 'claim(uint256)' "\x3CAUCTION_ID>" \
--from "$FROM_ADDRESS" \
--rpc-url "$BASE_MAINNET_RPC"
Broadcast (only when explicitly instructed):
~/.foundry/bin/cast send "$GBM_DIAMOND" 'claim(uint256)' "\x3CAUCTION_ID>" \
--private-key "$PRIVATE_KEY" \
--rpc-url "$BASE_MAINNET_RPC"
Optional: Buy Now
Onchain methods:
buyNow(uint256)swapAndBuyNow((address,uint256,uint256,uint256,address,uint256))
These are not required for the primary use case, but are adjacent to bidding flows. If you use them, follow the same safety gating:
- refetch from subgraph
- verify onchain price/state
- simulate (
cast call) - only broadcast when explicitly instructed
Smoke Tests (No Funds Required)
- Subgraph reachable (introspection lists
auction,auctions,bid,bids):
curl -s "$GBM_SUBGRAPH_URL" -H 'content-type: application/json' ${GOLDSKY_API_KEY:+-H "Authorization: Bearer $GOLDSKY_API_KEY"} --data '{ "query":"{ __schema { queryType { fields { name } } } }" }' \
| python3 -c 'import json,sys; f=[x[\"name\"] for x in json.load(sys.stdin)[\"data\"][\"__schema\"][\"queryType\"][\"fields\"]]; print([n for n in f if n in (\"auction\",\"auctions\",\"bid\",\"bids\")])'
- Subgraph data sane:
curl -s "$GBM_SUBGRAPH_URL" -H 'content-type: application/json' ${GOLDSKY_API_KEY:+-H "Authorization: Bearer $GOLDSKY_API_KEY"} --data '{\"query\":\"query($id:ID!){ auction(id:$id){ id contractAddress tokenId } }\",\"variables\":{\"id\":\"0\"}}'
- Onchain reachable + matches subgraph:
~/.foundry/bin/cast call "$GBM_DIAMOND" \
'getAuctionInfo(uint256)((address,uint96,address,uint88,uint88,bool,bool,address,(uint80,uint80,uint56,uint8,bytes4,uint256,uint96,uint96),(uint64,uint64,uint64,uint64,uint256),uint96,uint96))' \
0 \
--rpc-url "$BASE_MAINNET_RPC"
Common Failure Modes
UnmatchedHighestBid: you passed a stalehighestBidparam. Refetch onchain and retry.InvalidAuctionParams: token contract / id / amount mismatch. Refetch and verify.AuctionNotStarted/AuctionEnded: timing mismatch. CheckstartsAt/endsAt(subgraph + onchain).AuctionClaimed: already claimed or cancelled. Checkclaimed(subgraph + onchain).BiddingNotAllowed: diamond paused, contract bidding disabled, or re-entrancy lock. Refetch onchain state.- Swap errors:
LibTokenSwap: swapAmount must be > 0LibTokenSwap: deadline expiredLibTokenSwap: Insufficient output amount(increaseswapAmountor slippage)
- Make sure OpenClaw is installed (local or Docker)
- Run the install command in chat:
/install aavegotchi-gbm-skill - After installation, invoke the skill by name or use
/aavegotchi-gbm-skill - Provide required inputs per the skill's parameter spec and get structured output
What is Aavegotchi GBM Skill?
View, create, cancel, bid, and claim Aavegotchi GBM auctions on Base mainnet (8453). Subgraph-first discovery (Goldsky), with onchain verification + executio... It is an AI Agent Skill for Claude Code / OpenClaw, with 664 downloads so far.
How do I install Aavegotchi GBM Skill?
Run "/install aavegotchi-gbm-skill" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.
Is Aavegotchi GBM Skill free?
Yes, Aavegotchi GBM Skill is completely free (open-source). You can download, install and use it at no cost.
Which platforms does Aavegotchi GBM Skill support?
Aavegotchi GBM Skill is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).
Who created Aavegotchi GBM Skill?
It is built and maintained by cinnabarhorse (@cinnabarhorse); the current version is v0.1.0.