← Back to Skills
General

aavegotchi-gbm-skill

cinnabarhorse By cinnabarhorse 👁 55 views ▲ 0 votes

View, create, cancel, bid, and claim Aavegotchi GBM auctions on Base mainnet (8453)

GitHub
---
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 met

... (truncated)
general

Comments

Sign in to leave a comment

Loading comments...