Back to skills
SkillHub ClubResearch & OpsFull StackTesting

aavegotchi-gbm-skill

View, create, cancel, bid, and claim Aavegotchi GBM auctions on Base mainnet (8453). Subgraph-first discovery (Goldsky), with onchain verification + execution via Foundry cast. Safety-first: DRY_RUN defaults to 1 (simulate with cast call; only broadcast with cast send when DRY_RUN=0 and explicitly instructed).

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
3,108
Hot score
99
Updated
March 20, 2026
Overall rating
C0.0
Composite score
0.0
Best-practice grade
C61.1

Install command

npx @skill-hub/cli install openclaw-skills-aavegotchi-gbm-skill

Repository

openclaw/skills

Skill path: skills/cinnabarhorse/aavegotchi-gbm-skill

View, create, cancel, bid, and claim Aavegotchi GBM auctions on Base mainnet (8453). Subgraph-first discovery (Goldsky), with onchain verification + execution via Foundry cast. Safety-first: DRY_RUN defaults to 1 (simulate with cast call; only broadcast with cast send when DRY_RUN=0 and explicitly instructed).

Open repository

Best for

Primary workflow: Research & Ops.

Technical facets: Full Stack, Testing.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: openclaw.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install aavegotchi-gbm-skill into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/openclaw/skills before adding aavegotchi-gbm-skill to shared team environments
  • Use aavegotchi-gbm-skill for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: aavegotchi-gbm-skill
description: >
  View, create, cancel, bid, and claim Aavegotchi GBM auctions on Base mainnet (8453).
  Subgraph-first discovery (Goldsky), with onchain verification + execution via Foundry cast.
  Safety-first: DRY_RUN defaults to 1 (simulate with cast call; only broadcast with cast send when DRY_RUN=0 and explicitly instructed).
homepage: https://github.com/aavegotchi/aavegotchi-gbm-skill
metadata:
  openclaw:
    requires:
      bins:
        - cast
        - curl
        - python3
      env:
        - FROM_ADDRESS
        - PRIVATE_KEY
        - BASE_MAINNET_RPC
        - DRY_RUN
        - RECIPIENT_ADDRESS
        - GBM_SUBGRAPH_URL
        - GOLDSKY_API_KEY
        - GBM_DIAMOND
        - GHST
        - USDC
        - SLIPPAGE_PCT
        - GHST_USD_PRICE
        - ETH_USD_PRICE
    primaryEnv: PRIVATE_KEY
---

## 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 be `8453`.
- 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 `highestBid` matches the `highestBid` you pass into `commitBid` / `swapAndCommitBid`.
  - ensure token params match (token contract, token id, quantity).
- 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 `"<AUCTION_ID>"` to avoid accidental shell interpolation. Replace them with literal values only after validation.

Quick validators (replace the placeholder values):
```bash
python3 - <<'PY'
import re

auction_id = "<AUCTION_ID>"                 # digits only
token_contract = "<TOKEN_CONTRACT_ADDRESS>" # 0x + 40 hex chars
token_id = "<TOKEN_ID>"                     # digits only
amount = "<TOKEN_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 for `cast send` (never print/log).
- `FROM_ADDRESS`: EOA address that owns NFTs and will submit txs.
- `BASE_MAINNET_RPC`: RPC URL. If unset, use `https://mainnet.base.org`.
- `GBM_SUBGRAPH_URL`: Goldsky subgraph endpoint for auctions.

Optional env vars:
- `DRY_RUN`: `1` (default) to only simulate via `cast call`. Set to `0` to broadcast via `cast send`.
- `RECIPIENT_ADDRESS`: for swap flows; receives any excess GHST refunded by the contract. Defaults to `FROM_ADDRESS`.
- `GOLDSKY_API_KEY`: optional; if set, include `Authorization: Bearer ...` header in subgraph calls.
- `SLIPPAGE_PCT`: defaults to `1` (%); used in `swapAmount` estimate 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):
```bash
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/cast` so they work in cron/non-interactive shells.

## View / List Auctions (Subgraph First)

See `references/subgraph.md` for canonical queries.

Auction by id (quick):
```bash
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":"<AUCTION_ID>"}
}'
```

Active auctions (ends soonest first):
```bash
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):
```bash
~/.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))' \
  "<AUCTION_ID>" \
  --rpc-url "$BASE_MAINNET_RPC"
```

Useful individual getters:
```bash
~/.foundry/bin/cast call "$GBM_DIAMOND" 'getAuctionHighestBid(uint256)(uint256)' "<AUCTION_ID>" --rpc-url "$BASE_MAINNET_RPC"
~/.foundry/bin/cast call "$GBM_DIAMOND" 'getAuctionHighestBidder(uint256)(address)' "<AUCTION_ID>" --rpc-url "$BASE_MAINNET_RPC"
~/.foundry/bin/cast call "$GBM_DIAMOND" 'getAuctionStartTime(uint256)(uint256)' "<AUCTION_ID>" --rpc-url "$BASE_MAINNET_RPC"
~/.foundry/bin/cast call "$GBM_DIAMOND" 'getAuctionEndTime(uint256)(uint256)' "<AUCTION_ID>" --rpc-url "$BASE_MAINNET_RPC"
~/.foundry/bin/cast call "$GBM_DIAMOND" 'getContractAddress(uint256)(address)' "<AUCTION_ID>" --rpc-url "$BASE_MAINNET_RPC"
~/.foundry/bin/cast call "$GBM_DIAMOND" 'getTokenId(uint256)(uint256)' "<AUCTION_ID>" --rpc-url "$BASE_MAINNET_RPC"
~/.foundry/bin/cast call "$GBM_DIAMOND" 'getTokenKind(uint256)(bytes4)' "<AUCTION_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:
1. Ensure the token contract is whitelisted on the GBM diamond (otherwise revert `ContractNotAllowed`).
2. Ensure the token is approved to the GBM diamond:
   - ERC721/1155: `setApprovalForAll(GBM_DIAMOND,true)`
3. Choose `InitiatorInfo`:
   - `startTime` must be in the future.
   - `endTime - startTime` must be between 3600 and 604800 seconds (1h to 7d).
   - `tokenKind` is `0x73ad2146` (ERC721) or `0x973bb640` (ERC1155).
   - `buyItNowPrice` optional; `startingBid` optional (if nonzero, you must approve GHST for the 4% prepaid fee).
4. Simulate with `cast call` using `--from "$FROM_ADDRESS"`.
5. Broadcast with `cast send` only when explicitly instructed (`DRY_RUN=0`).
6. Post-tx: query subgraph for newest seller auctions and match `(contractAddress, tokenId)`.

Simulate create (ERC721 example):
```bash
~/.foundry/bin/cast call "$GBM_DIAMOND" \
  'createAuction((uint80,uint80,uint56,uint8,bytes4,uint256,uint96,uint96),address,uint256)(uint256)' \
  "(<START_TIME>,<END_TIME>,1,<CATEGORY>,0x73ad2146,<TOKEN_ID>,<BUY_NOW_GHST_WEI>,<STARTING_BID_GHST_WEI>)" \
  "<ERC721_CONTRACT_ADDRESS>" "<PRESET_ID>" \
  --from "$FROM_ADDRESS" \
  --rpc-url "$BASE_MAINNET_RPC"
```

Broadcast create (only when explicitly instructed):
```bash
~/.foundry/bin/cast send "$GBM_DIAMOND" \
  'createAuction((uint80,uint80,uint56,uint8,bytes4,uint256,uint96,uint96),address,uint256)(uint256)' \
  "(<START_TIME>,<END_TIME>,1,<CATEGORY>,0x73ad2146,<TOKEN_ID>,<BUY_NOW_GHST_WEI>,<STARTING_BID_GHST_WEI>)" \
  "<ERC721_CONTRACT_ADDRESS>" "<PRESET_ID>" \
  --private-key "$PRIVATE_KEY" \
  --rpc-url "$BASE_MAINNET_RPC"
```

Post-create (find your newest auctions and confirm):
```bash
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":"<FROM_ADDRESS_LOWERCASE>"}
}'
```

## Cancel Auction

Onchain method:
- `cancelAuction(uint256)`

Steps:
1. Subgraph: check `claimed`, `cancelled`, `endsAt`, `highestBid`.
2. Onchain: call `getAuctionInfo(auctionId)` to verify ownership and state.
3. Simulate with `cast call` (`--from "$FROM_ADDRESS"`).
4. Broadcast only when explicitly instructed.

Simulate:
```bash
~/.foundry/bin/cast call "$GBM_DIAMOND" 'cancelAuction(uint256)' "<AUCTION_ID>" \
  --from "$FROM_ADDRESS" \
  --rpc-url "$BASE_MAINNET_RPC"
```

Broadcast (only when explicitly instructed):
```bash
~/.foundry/bin/cast send "$GBM_DIAMOND" 'cancelAuction(uint256)' "<AUCTION_ID>" \
  --private-key "$PRIVATE_KEY" \
  --rpc-url "$BASE_MAINNET_RPC"
```

## Bid With GHST (commitBid)

Onchain method:
- `commitBid(uint256,uint256,uint256,address,uint256,uint256,bytes)` (last `bytes` is ignored; pass `0x`)

Steps:
1. Subgraph: fetch auction fields (id, contractAddress, tokenId, quantity, highestBid, startsAt, endsAt, claimed/cancelled).
2. Onchain: refetch `highestBid` and token params; you must pass the exact current onchain `highestBid` or it reverts `UnmatchedHighestBid`.
3. Compute a safe minimum next bid using `references/bid-math.md` (uses onchain `bidDecimals` + `stepMin`).
4. Ensure GHST allowance to the GBM diamond covers `bidAmount`.
5. Simulate via `cast call` (optional but recommended).
6. Broadcast only when explicitly instructed.

Simulate:
```bash
~/.foundry/bin/cast call "$GBM_DIAMOND" \
  'commitBid(uint256,uint256,uint256,address,uint256,uint256,bytes)' \
  "<AUCTION_ID>" "<BID_AMOUNT_GHST_WEI>" "<HIGHEST_BID_GHST_WEI>" "<TOKEN_CONTRACT_ADDRESS>" "<TOKEN_ID>" "<TOKEN_AMOUNT>" 0x \
  --from "$FROM_ADDRESS" \
  --rpc-url "$BASE_MAINNET_RPC"
```

Broadcast (only when explicitly instructed):
```bash
~/.foundry/bin/cast send "$GBM_DIAMOND" \
  'commitBid(uint256,uint256,uint256,address,uint256,uint256,bytes)' \
  "<AUCTION_ID>" "<BID_AMOUNT_GHST_WEI>" "<HIGHEST_BID_GHST_WEI>" "<TOKEN_CONTRACT_ADDRESS>" "<TOKEN_ID>" "<TOKEN_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):
1. `tokenIn` (USDC)
2. `swapAmount` (USDC 6dp)
3. `minGhstOut` (GHST wei; must be >= bidAmount)
4. `swapDeadline` (unix; must be <= now + 86400)
5. `recipient` (refund receiver for excess GHST)
6. `auctionID`
7. `bidAmount` (GHST wei)
8. `highestBid` (must match onchain)
9. `tokenContract`
10. `tokenID`
11. `amount` (tokenAmount/quantity)
12. `_signature` (ignored; pass `0x`)

Compute `swapAmount` estimate in `references/swap-math.md`.

Simulate:
```bash
~/.foundry/bin/cast call "$GBM_DIAMOND" \
  'swapAndCommitBid((address,uint256,uint256,uint256,address,uint256,uint256,uint256,address,uint256,uint256,bytes))' \
  "($USDC,<SWAP_AMOUNT_USDC_6DP>,<MIN_GHST_OUT_GHST_WEI>,<SWAP_DEADLINE_UNIX>,${RECIPIENT_ADDRESS:-$FROM_ADDRESS},<AUCTION_ID>,<BID_AMOUNT_GHST_WEI>,<HIGHEST_BID_GHST_WEI>,<TOKEN_CONTRACT_ADDRESS>,<TOKEN_ID>,<TOKEN_AMOUNT>,0x)" \
  --from "$FROM_ADDRESS" \
  --rpc-url "$BASE_MAINNET_RPC"
```

Broadcast (only when explicitly instructed):
```bash
~/.foundry/bin/cast send "$GBM_DIAMOND" \
  'swapAndCommitBid((address,uint256,uint256,uint256,address,uint256,uint256,uint256,address,uint256,uint256,bytes))' \
  "($USDC,<SWAP_AMOUNT_USDC_6DP>,<MIN_GHST_OUT_GHST_WEI>,<SWAP_DEADLINE_UNIX>,${RECIPIENT_ADDRESS:-$FROM_ADDRESS},<AUCTION_ID>,<BID_AMOUNT_GHST_WEI>,<HIGHEST_BID_GHST_WEI>,<TOKEN_CONTRACT_ADDRESS>,<TOKEN_ID>,<TOKEN_AMOUNT>,0x)" \
  --private-key "$PRIVATE_KEY" \
  --rpc-url "$BASE_MAINNET_RPC"
```

## Bid With ETH Swap (swapAndCommitBid)

Same method as above, but:
- `tokenIn = 0x0000000000000000000000000000000000000000`
- `--value <SWAP_AMOUNT_WEI>` must equal the `swapAmount` you pass inside the tuple.

Broadcast (only when explicitly instructed):
```bash
~/.foundry/bin/cast send "$GBM_DIAMOND" \
  'swapAndCommitBid((address,uint256,uint256,uint256,address,uint256,uint256,uint256,address,uint256,uint256,bytes))' \
  "(0x0000000000000000000000000000000000000000,<SWAP_AMOUNT_WEI>,<MIN_GHST_OUT_GHST_WEI>,<SWAP_DEADLINE_UNIX>,${RECIPIENT_ADDRESS:-$FROM_ADDRESS},<AUCTION_ID>,<BID_AMOUNT_GHST_WEI>,<HIGHEST_BID_GHST_WEI>,<TOKEN_CONTRACT_ADDRESS>,<TOKEN_ID>,<TOKEN_AMOUNT>,0x)" \
  --value "<SWAP_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`.
  - `cancellationTime` is readable from storage slot 12 (see `references/recipes.md`).
  - Subgraph may provide `claimAt` (if populated), but always verify onchain.

Simulate:
```bash
~/.foundry/bin/cast call "$GBM_DIAMOND" 'claim(uint256)' "<AUCTION_ID>" \
  --from "$FROM_ADDRESS" \
  --rpc-url "$BASE_MAINNET_RPC"
```

Broadcast (only when explicitly instructed):
```bash
~/.foundry/bin/cast send "$GBM_DIAMOND" 'claim(uint256)' "<AUCTION_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)

1. Subgraph reachable (introspection lists `auction`, `auctions`, `bid`, `bids`):
```bash
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\")])'
```

2. Subgraph data sane:
```bash
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\"}}'
```

3. Onchain reachable + matches subgraph:
```bash
~/.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 stale `highestBid` param. Refetch onchain and retry.
- `InvalidAuctionParams`: token contract / id / amount mismatch. Refetch and verify.
- `AuctionNotStarted` / `AuctionEnded`: timing mismatch. Check `startsAt`/`endsAt` (subgraph + onchain).
- `AuctionClaimed`: already claimed or cancelled. Check `claimed` (subgraph + onchain).
- `BiddingNotAllowed`: diamond paused, contract bidding disabled, or re-entrancy lock. Refetch onchain state.
- Swap errors:
  - `LibTokenSwap: swapAmount must be > 0`
  - `LibTokenSwap: deadline expired`
  - `LibTokenSwap: Insufficient output amount` (increase `swapAmount` or slippage)


---

## Referenced Files

> The following files are referenced in this skill and included for context.

### references/subgraph.md

```markdown
# Subgraph Queries (Base GBM Auctions)

Endpoint:
- `GBM_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_cmh3flagm0001r4p25foufjtt/subgraphs/aavegotchi-gbm-baazaar-base/prod/gn`

Notes:
- `Bytes` fields (addresses) are lowercase in responses; when filtering, use lowercase addresses.
- Treat `Auction.id` as the canonical `auctionId` you pass to `cast` methods.
- Goldsky API key is optional for the public endpoint. If you set `GOLDSKY_API_KEY`, add:
  - `-H "Authorization: Bearer $GOLDSKY_API_KEY"`

## Auction By ID
```bash
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 lastBidTime startsAt endsAt claimAt claimed cancelled presetId category buyNowPrice startBidPrice bidDecimals stepMin incMin incMax bidMultiplier dueIncentives auctionDebt } }",
  "variables":{"id":"<AUCTION_ID>"}
}'
```

## Active Auctions (Now Between startsAt and endsAt)
```bash
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\"}
}"
```

## Your Auctions (seller)
```bash
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:50, orderBy: createdAt, orderDirection: desc, where:{seller:$seller}){ id type contractAddress tokenId quantity highestBid highestBidder totalBids startsAt endsAt claimAt claimed cancelled } }",
  "variables":{"seller":"<FROM_ADDRESS_LOWERCASE>"}
}'
```

## Bids For An Auction
```bash
curl -s "$GBM_SUBGRAPH_URL" -H 'content-type: application/json' ${GOLDSKY_API_KEY:+-H "Authorization: Bearer $GOLDSKY_API_KEY"} --data '{
  "query":"query($aid:String!){ bids(first:50, orderBy: bidTime, orderDirection: desc, where:{auction:$aid}){ id bidder amount bidTime outbid previousBid previousBidder } }",
  "variables":{"aid":"<AUCTION_ID>"}
}'
```

## Your Bids (bidder)
```bash
curl -s "$GBM_SUBGRAPH_URL" -H 'content-type: application/json' ${GOLDSKY_API_KEY:+-H "Authorization: Bearer $GOLDSKY_API_KEY"} --data '{
  "query":"query($bidder:Bytes!){ bids(first:50, orderBy: bidTime, orderDirection: desc, where:{bidder:$bidder}){ id auction { id type contractAddress tokenId quantity endsAt claimAt claimed cancelled } amount bidTime outbid } }",
  "variables":{"bidder":"<FROM_ADDRESS_LOWERCASE>"}
}'
```

## Subgraph Reachability Smoke Test (Introspection)
```bash
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")])'
```

```

### references/bid-math.md

```markdown
# Bid Math (Minimum Next Bid)

When bidding (`commitBid` / `swapAndCommitBid`), you must:
- Pass the exact current onchain `highestBid` as the `_highestBid` argument (else revert `UnmatchedHighestBid`).
- Bid at or above the contract's effective minimum step, based on preset `stepMin` and `bidDecimals`.

## Effective Minimum Next Bid (Matches Onchain Behavior)

The incentives math uses:
```
baseBid = highestBid * (bidDecimals + stepMin) / bidDecimals
```

If `newBid < baseBid`, the incentives calculation underflows and the bid reverts.

Additionally, if the auction has `startingBid` set, the bid must be:
- `bidAmount >= startingBid`

So the safe minimum is:
```
minNextBid = max(startingBid, baseBid)   (and baseBid is forced to >= 1 when highestBid is 0)
```

### Python Helper (Recommended)

Provide:
- `highestBid` (from onchain `getAuctionHighestBid`)
- `startingBid` (from onchain `getAuctionInfo`, or from subgraph `startBidPrice`)
- `bidDecimals` and `stepMin` (from onchain getters or subgraph fields)

```bash
python3 - <<'PY'
highest_bid = int("<HIGHEST_BID_GHST_WEI>")     # replace
starting_bid = int("<STARTING_BID_GHST_WEI>")   # replace (0 if none)
bid_decimals = int("<BID_DECIMALS>")            # e.g. 100000
step_min = int("<STEP_MIN>")                    # e.g. 5000

base_bid = (highest_bid * (bid_decimals + step_min)) // bid_decimals
if base_bid == 0:
    base_bid = 1

min_next = max(starting_bid, base_bid)
print("minNextBid (GHST wei):", min_next)
PY
```

## Interpreting Presets (Rule of Thumb)

On Base mainnet, presets typically use:
- `bidDecimals = 100000`
- `stepMin` of `1000`, `5000`, or `10000`

This corresponds to a minimum step of roughly:
- `1%`, `5%`, or `10%` (because `stepMin / bidDecimals`)

Verify per-auction via subgraph fields or onchain getters:
- `getAuctionBidDecimals(auctionId)(uint256)`
- `getAuctionStepMin(auctionId)(uint64)`

```

### references/swap-math.md

```markdown
# Swap Amount Math (USDC / ETH -> GHST)

This file defines how to estimate the `swapAmount` argument for:
- `swapAndCommitBid((...))`
- `swapAndBuyNow((...))`

Important notes:
- `swapAmount` is the amount of `tokenIn` you will spend (USDC 6dp or ETH wei).
- `minGhstOut` is a GHST wei minimum output (slippage protection). For bidding and buy-now, set it to the exact required GHST amount:
  - bid: `minGhstOut = bidAmount`
  - buy-now: `minGhstOut = buyNowPrice`
- Swaps can still fail due to price impact or route conditions (`LibTokenSwap: Insufficient output amount`). If that happens, increase `swapAmount` and/or `SLIPPAGE_PCT`.

Defaults:
- `SLIPPAGE_PCT=1` (1%)

## Price Sources (CoinGecko)

If `GHST_USD_PRICE` / `ETH_USD_PRICE` are unset, fetch them:
```bash
curl -s 'https://api.coingecko.com/api/v3/simple/price?ids=aavegotchi,ethereum&vs_currencies=usd' \
  | python3 -c 'import json,sys; j=json.load(sys.stdin); print(\"GHST_USD\", j[\"aavegotchi\"][\"usd\"]); print(\"ETH_USD\", j[\"ethereum\"][\"usd\"])'
```

## USDC swapAmount (6 decimals)

Given:
- `min_ghst_out_wei` (bidAmount or buyNowPrice)
- `ghst_usd_price`

Compute:
1. `ghst = min_ghst_out_wei / 1e18`
2. `usd = ghst * ghst_usd_price`
3. `base_usdc_6dp = usd * 1e6`
4. `swapAmount = ceil(base_usdc_6dp * (1 + SLIPPAGE_PCT/100))`

Python reference:
```bash
python3 - <<'PY'
from decimal import Decimal, getcontext, ROUND_CEILING

getcontext().prec = 80

min_ghst_out_wei = Decimal("<MIN_GHST_OUT_GHST_WEI>")  # replace
ghst_usd_price = Decimal("<GHST_USD_PRICE>")           # replace
slippage_pct = Decimal("<SLIPPAGE_PCT>")               # default 1

ghst = min_ghst_out_wei / (Decimal(10) ** 18)
usd = ghst * ghst_usd_price
base_usdc = usd * (Decimal(10) ** 6)

swap_amount = (base_usdc * (Decimal(1) + slippage_pct / Decimal(100))).to_integral_value(rounding=ROUND_CEILING)
print("swapAmount (USDC 6dp):", int(swap_amount))
PY
```

## ETH swapAmount (wei)

Given:
- `min_ghst_out_wei`
- `ghst_usd_price`
- `eth_usd_price`

Compute:
1. `ghst = min_ghst_out_wei / 1e18`
2. `usd = ghst * ghst_usd_price`
3. `eth = usd / eth_usd_price`
4. `base_eth_wei = eth * 1e18`
5. `swapAmountWei = ceil(base_eth_wei * (1 + SLIPPAGE_PCT/100))`

Python reference:
```bash
python3 - <<'PY'
from decimal import Decimal, getcontext, ROUND_CEILING

getcontext().prec = 80

min_ghst_out_wei = Decimal("<MIN_GHST_OUT_GHST_WEI>")  # replace
ghst_usd_price = Decimal("<GHST_USD_PRICE>")           # replace
eth_usd_price = Decimal("<ETH_USD_PRICE>")             # replace
slippage_pct = Decimal("<SLIPPAGE_PCT>")               # default 1

ghst = min_ghst_out_wei / (Decimal(10) ** 18)
usd = ghst * ghst_usd_price
eth = usd / eth_usd_price
base_eth_wei = eth * (Decimal(10) ** 18)

swap_amount = (base_eth_wei * (Decimal(1) + slippage_pct / Decimal(100))).to_integral_value(rounding=ROUND_CEILING)
print("swapAmount (ETH wei):", int(swap_amount))
PY
```

```

### references/recipes.md

```markdown
# Common Recipes (Foundry cast + Subgraph)

Commands below use `~/.foundry/bin/cast` so they work in cron/non-interactive shells. If `cast` is on `PATH`, you can replace `~/.foundry/bin/cast` with `cast`.

Assumes you set defaults from `references/addresses.md`.

## Safety Checks

Verify chain id is Base mainnet (must be `8453`):
```bash
~/.foundry/bin/cast chain-id --rpc-url "${BASE_MAINNET_RPC:-https://mainnet.base.org}"
```

Verify private key corresponds to FROM_ADDRESS (must match exactly):
```bash
~/.foundry/bin/cast wallet address --private-key "$PRIVATE_KEY"
```

Lowercase your address for subgraph filters:
```bash
python3 - <<'PY'
addr = "<FROM_ADDRESS>"
print(addr.lower())
PY
```

## Subgraph Convenience: Auction By ID
```bash
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":"<AUCTION_ID>"}
}'
```

## ERC20: Balances / Allowances

GHST balance:
```bash
~/.foundry/bin/cast call "$GHST" 'balanceOf(address)(uint256)' "$FROM_ADDRESS" --rpc-url "$BASE_MAINNET_RPC"
```

USDC balance:
```bash
~/.foundry/bin/cast call "$USDC" 'balanceOf(address)(uint256)' "$FROM_ADDRESS" --rpc-url "$BASE_MAINNET_RPC"
```

GHST allowance to GBM diamond:
```bash
~/.foundry/bin/cast call "$GHST" 'allowance(address,address)(uint256)' "$FROM_ADDRESS" "$GBM_DIAMOND" --rpc-url "$BASE_MAINNET_RPC"
```

USDC allowance to GBM diamond:
```bash
~/.foundry/bin/cast call "$USDC" 'allowance(address,address)(uint256)' "$FROM_ADDRESS" "$GBM_DIAMOND" --rpc-url "$BASE_MAINNET_RPC"
```

Approve GHST (broadcast; do this only when explicitly instructed):
```bash
~/.foundry/bin/cast send "$GHST" 'approve(address,uint256)' "$GBM_DIAMOND" "<AMOUNT_GHST_WEI>" \
  --private-key "$PRIVATE_KEY" \
  --rpc-url "$BASE_MAINNET_RPC"
```

Approve USDC (broadcast; do this only when explicitly instructed):
```bash
~/.foundry/bin/cast send "$USDC" 'approve(address,uint256)' "$GBM_DIAMOND" "<AMOUNT_USDC_6DP>" \
  --private-key "$PRIVATE_KEY" \
  --rpc-url "$BASE_MAINNET_RPC"
```

## ERC721 / ERC1155: Approval For All

Check (ERC721 or ERC1155 contract):
```bash
~/.foundry/bin/cast call "<NFT_CONTRACT_ADDRESS>" 'isApprovedForAll(address,address)(bool)' "$FROM_ADDRESS" "$GBM_DIAMOND" \
  --rpc-url "$BASE_MAINNET_RPC"
```

Set approval (broadcast; do this only when explicitly instructed):
```bash
~/.foundry/bin/cast send "<NFT_CONTRACT_ADDRESS>" 'setApprovalForAll(address,bool)' "$GBM_DIAMOND" true \
  --private-key "$PRIVATE_KEY" \
  --rpc-url "$BASE_MAINNET_RPC"
```

## Auction Time Helpers

Compute start/end times (example: start in 60s, duration 24h):
```bash
python3 - <<'PY'
import time
now = int(time.time())
start = now + 60
end = start + 24*60*60
print("startTime:", start)
print("endTime:  ", end)
PY
```

Swap deadline (now + 600):
```bash
python3 - <<'PY'
import time
print(int(time.time()) + 600)
PY
```

## Read hammerTimeDuration / cancellationTime (Storage Slot 12)

Storage slot `12` packs two uint128 values:
- low 128 bits: `hammerTimeDuration`
- high 128 bits: `cancellationTime`

Fetch raw slot:
```bash
~/.foundry/bin/cast storage "$GBM_DIAMOND" 12 --rpc-url "$BASE_MAINNET_RPC"
```

Decode:
```bash
python3 - <<'PY'
slot_hex = "<SLOT_12_HEX>"  # replace output of cast storage
v = int(slot_hex, 16)
mask = (1 << 128) - 1
hammer = v & mask
cancellation = v >> 128
print("hammerTimeDuration:", hammer)
print("cancellationTime:  ", cancellation)
PY
```

## Auction Nonce (Optional Onchain Discovery)

Storage slot `13` is `auctionNonce` (next auction id):
```bash
~/.foundry/bin/cast storage "$GBM_DIAMOND" 13 --rpc-url "$BASE_MAINNET_RPC"
```

In general, prefer the subgraph for listing and discovery.

```



---

## Skill Companion Files

> Additional files collected from the skill directory layout.

### _meta.json

```json
{
  "owner": "cinnabarhorse",
  "slug": "aavegotchi-gbm-skill",
  "displayName": "Aavegotchi GBM Skill",
  "latest": {
    "version": "0.1.0",
    "publishedAt": 1771147668598,
    "commit": "https://github.com/openclaw/skills/commit/6c85b7b01bee756b654c08e0f0e3da182869d0a8"
  },
  "history": []
}

```

### references/addresses.md

```markdown
# Addresses / Constants (Base Mainnet)

Chain:
- Chain ID: `8453` (Base mainnet)
- Default RPC: `https://mainnet.base.org` (override via `BASE_MAINNET_RPC`)

GBM diamond (entrypoint for auctions):
- `GBM_DIAMOND=0x80320A0000C7A6a34086E2ACAD6915Ff57FfDA31`

ERC20s:
- GHST (18 decimals): `GHST=0xcD2F22236DD9Dfe2356D7C543161D4d260FD9BcB`
- USDC (6 decimals): `USDC=0x833589fCD6eDb6E08f4c7C32D4f71b54BDA02913`

Subgraph (Goldsky, no auth required):
- `GBM_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_cmh3flagm0001r4p25foufjtt/subgraphs/aavegotchi-gbm-baazaar-base/prod/gn`

GBM Diamond deploy block (useful for log scans):
- `DEPLOY_BLOCK=33276452` (Base mainnet)

Token kind constants (used in `createAuction` InitiatorInfo):
- `ERC721=0x73ad2146`
- `ERC1155=0x973bb640`

Likely-whitelisted token contracts on Base mainnet (from the GBM repo deployment config):
- Aavegotchi diamond (ERC721): `0xA99c4B08201F2913Db8D28e71d020c4298F29dBF`
- Forge diamond (ERC1155): `0x50aF2d63b839aA32b4166FD1Cb247129b715186C`
- Fake Gotchi Card diamond (ERC721): `0xe46B8902dAD841476d9Fee081F1d62aE317206A9`
- Fake Gotchi Art diamond (ERC721): `0xAb59CA4A16925b0a4BaC5026C94bEB20A29Df479`

Recommended shell defaults (allow overrides):
```bash
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}"
```

```

### references/logs.md

```markdown
# Logs / Event Scans (Optional)

You can discover auctions and activity via events, but for day-to-day listing and filtering, prefer the subgraph (`references/subgraph.md`).

If you do use logs:
- Some RPCs restrict `eth_getLogs` to a max block range (commonly 10,000 blocks).
- Some RPCs intermittently 503 on large log queries.
- Chunk your requests.

Constants:
- GBM diamond: `0x80320A0000C7A6a34086E2ACAD6915Ff57FfDA31`
- Deploy block (Base mainnet): `33276452`

## Common Events

- `Auction_Initialized(uint256 indexed _auctionID,uint256 indexed _tokenID,uint256 indexed _tokenAmount,address _contractAddress,bytes4 _tokenKind,uint256 _presetID)`
- `Auction_BidPlaced(uint256 indexed _auctionID,address indexed _bidder,uint256 _bidAmount)`
- `AuctionCancelled(uint256 indexed _auctionId,uint256 _tokenId)`
- `Auction_ItemClaimed(uint256 indexed _auctionID)`

## Example: Fetch Recent Auction_Initialized Logs (Chunked)

```bash
python3 - <<'PY'
import subprocess

rpc = "https://1rpc.io/base"  # override as needed
addr = "0x80320A0000C7A6a34086E2ACAD6915Ff57FfDA31"
event = "Auction_Initialized(uint256,uint256,uint256,address,bytes4,uint256)"

# Keep chunk <= 10k blocks for providers that enforce that limit.
start = 33276452
end = int(subprocess.check_output(["cast", "block-number", "--rpc-url", rpc]).decode().strip())
chunk = 8000

for a in range(start, end + 1, chunk):
    b = min(a + chunk - 1, end)
    cmd = [
        "cast", "logs", event,
        "--from-block", str(a),
        "--to-block", str(b),
        "--address", addr,
        "--rpc-url", rpc,
        "--json",
    ]
    out = subprocess.check_output(cmd)
    if out.strip() not in (b"", b"[]"):
        print(f"range {a}-{b}:", out.decode().strip()[:300], "...")
PY
```

```

### references/presets.md

```markdown
# GBM Auction Presets (Base)

Presets are stored onchain and copied into each auction at creation time.

Read a preset:
```bash
~/.foundry/bin/cast call "$GBM_DIAMOND" 'getAuctionPresets(uint256)((uint64,uint64,uint64,uint64,uint256))' 0 --rpc-url "$BASE_MAINNET_RPC"
```

Base mainnet presets (from the GBM repo deployment config; verify onchain):

Preset `0` (low):
- `incMin=500`
- `incMax=1000`
- `bidMultiplier=500`
- `stepMin=1000`
- `bidDecimals=100000`
- Interpreting `stepMin/bidDecimals`: ~`1%` minimum step (used in bid math)

Preset `1` (medium):
- `incMin=500`
- `incMax=5000`
- `bidMultiplier=4970`
- `stepMin=5000`
- `bidDecimals=100000`
- Interpreting `stepMin/bidDecimals`: ~`5%` minimum step

Preset `2` (high):
- `incMin=1000`
- `incMax=10000`
- `bidMultiplier=11000`
- `stepMin=10000`
- `bidDecimals=100000`
- Interpreting `stepMin/bidDecimals`: ~`10%` minimum step

Tip:
- If you are creating an auction for a specific contract and you want to match platform defaults, query recent auctions for that contract in the subgraph and copy the `presetId` used.

```