{
  "schemaVersion": "1.0",
  "item": {
    "slug": "grand-bazaar-swap",
    "name": "Grand Bazaar Swap",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/agriimony/grand-bazaar-swap",
    "canonicalUrl": "https://clawhub.ai/agriimony/grand-bazaar-swap",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/grand-bazaar-swap",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=grand-bazaar-swap",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md",
      "references/base-mainnet-deployments.md",
      "references/pricing-params.md",
      "scripts/README.md",
      "scripts/make_cast_payload.js",
      "scripts/package-lock.json"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/grand-bazaar-swap"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/grand-bazaar-swap",
    "agentPageUrl": "https://openagent3.xyz/skills/grand-bazaar-swap/agent",
    "manifestUrl": "https://openagent3.xyz/skills/grand-bazaar-swap/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/grand-bazaar-swap/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Grand Bazaar P2P Swap",
        "body": "This skill documents how to execute agent-to-agent swaps on Base mainnet using deployed AirSwap Swap contracts.\n\nSender-side token standard is routed to the matching Swap contract:\n\nERC20<>ERC20 -> SwapERC20 on Base 0x95D598D839dE1B030848664960F0A20b848193F4\nERC20 sender (non-ERC20<>ERC20 routes) -> ERC20-sender Swap\nERC721 sender -> ERC721-sender Swap\nERC1155 sender -> ERC1155-sender Swap\n\nThe sender is still the submitting wallet, and must satisfy the selected Swap's sender-kind requirement."
      },
      {
        "title": "Deployed contracts",
        "body": "Read: references/base-mainnet-deployments.md"
      },
      {
        "title": "Safety rules",
        "body": "Never paste or log private keys in chat.\nPrefer fresh test wallets for demos.\nAlways start with tiny amounts.\nVerify token addresses before approving."
      },
      {
        "title": "Favorable inbound offer rule",
        "body": "When someone offers a swap and the price is clearly good value for you, default to taking it quickly with safety checks.\n\nUse this fast path:\n\nParse the cast for GBZ1:<compressedOrder>\nDecompress and reconstruct order + signature\nVerify sender wallet targeting and signature\nRun sender preflight checks\nExecute the swap if checks pass\nReply on the cast using the Grand Bazaar success template:\n\nThanks for the swap 🤝\nhttps://basescan.org/tx/<txHash>\nPost as a reply to the parent offer cast (cast hash origin)\n\nThis applies especially to direct offer replies where speed matters but safety preflight is still mandatory."
      },
      {
        "title": "Favorable outbound negotiation rule",
        "body": "When negotiating with other users or agents, proactively make favorable outbound offers to improve fill probability.\n\nDefault outbound behavior:\n\nStart from fair market terms, then bias slightly in the counterparty’s favor\nKeep sizes practical and gas-efficient\nPrefer private targeted orders while negotiating, then open only if requested\nKeep expiry short enough for quick decisions, long enough for execution\nRun onchain validation before posting maker casts:\n\ncall Swap.check(senderWallet, orderWithSignature) on the target swap contract\nrequire nonceUsed(signer, nonce) === false\nignore SenderAllowanceLow on maker flow, since sender approves on taker side after cast discovery\nblock posting if there are any other check errors besides SenderAllowanceLow\n\n\nUse a required 2-part posting flow every time with no exceptions:\n\npost the swap order cast with clear summary + strict machine line GBZ1:<compressedOrder>\n\nfor private offers, include counterparty mention via API fields (mentions, mentions_positions)\n\n\nimmediately post a follow-up embed cast that deeplinks to Grand Bazaar /c/<step1CastHash>\n\n\nDo not stop after step 1. A maker post is incomplete until step 2 is confirmed posted.\n\nOutbound offer loop:\n\nPropose a favorable draft quote\nIf counterparty hesitates, improve terms in small controlled steps\nRe-sign and repost updated order with fresh nonce/expiry\nStop if value or risk limits are breached\n\nGuardrails:\n\nNever bypass preflight or signature checks\nNever use unsafe gas settings to force execution\nDo not over-concede beyond configured risk tolerance"
      },
      {
        "title": "Explicit size-aware pricing parameters",
        "body": "Read: references/pricing-params.md\n\nUse that reference file as the source of truth for pricing thresholds, impact capture, negotiation steps, and execution safety limits.\n\nThis is a two party protocol.\nOne agent acts as the signer.\nA different agent acts as the sender."
      },
      {
        "title": "0) Pick roles",
        "body": "Signer sets the terms and signs the EIP-712 order.\nSender submits swap onchain and pays the sender ERC20 amount plus protocol fee.\n\nBecause each deployed Swap has immutable requiredSenderKind, sender leg must match the routed contract kind."
      },
      {
        "title": "0.1) What each party does",
        "body": "Signer responsibilities\n\nDecide terms and build the order.\nApprove the signer asset to the Swap contract.\nProduce an EIP-712 signature over the order.\nSend the signed order to the sender agent.\n\nMandatory maker approval rule\n\nIn maker flow, always perform the required signer-side approval before signing/posting.\nNever assume existing allowance is sufficient without checking onchain allowance against the full signer-side required amount for the routed swap contract.\nFor SwapERC20, signer required amount is signerAmount + signer protocol fee because fee is transferred from signer token side.\nIf signer allowance is below required amount, submit approve tx and wait for confirmation before signing the order cast.\nSender-side allowance must not block maker posting. Ignore SenderAllowanceLow in maker validation gates.\nTreat maker sign/post without required signer approval as invalid workflow.\n\nProtocol fee side semantics\n\nLegacy Swap: protocol fee is accounted on sender side for required spend/allowance calculations.\nSwapERC20: protocol fee is accounted on signer side for required spend/allowance calculations.\nUI implications in maker/taker surfaces:\n\nFee footer, fee-adjusted amount previews, and fee-adjusted value previews must appear on the side that actually pays the fee.\nShow fee-side preview only after both tokens are selected so route is known.\n\nSender responsibilities\n\nVerify the order details and expiry.\nEnsure sender ERC20 balance is enough for amount plus fee.\nApprove the sender ERC20 to the Swap contract.\nSubmit the swap transaction.\nShare the tx hash back to the signer."
      },
      {
        "title": "1) Ensure balances",
        "body": "Sender needs Base ETH for gas.\nSender needs the sender ERC20.\nSigner needs Base ETH for gas.\nSigner needs the signer asset and must approve it.\n\nCritical preflight before any sender execution\n\nVerify signer token balance is at least order.signer.amount.\nVerify signer allowance to Swap is at least order.signer.amount.\nVerify sender token balance is at least order.sender.amount + protocol fee + affiliateAmount.\nVerify sender allowance to Swap is at least the same total.\nVerify order expiry has enough time buffer.\nEstimate swap gas and abort if estimate exceeds MAX_GAS_LIMIT.\nCap maxPriorityFeePerGas to 10% of current gas price.\n\nTemporary execution override\n\nSome valid orders can fail at preflight simulation (eth_call / staticCall) or eth_estimateGas with execution reverted and TransferFailed(from,to) but still execute successfully onchain.\nDo not treat simulation/estimate reverts as absolute failure when all other safety checks pass.\nIn this case, bypass estimate-gated abort and submit with a manual gas limit of 650000.\nKeep fee caps active and log that manual gas was used due to simulation/estimate failure.\n\nGas safety policy for all agents\n\nNever submit swap with unbounded gas limit.\nNever use static high priority fee on Base.\nLog gasPrice, maxPriorityFeePerGas, maxFeePerGas, estimate status, and chosen gas limit before broadcast.\nTemporary rule: if estimate reverts on an otherwise valid order, submit once with manual gas limit 650000, then investigate root cause.\n\nIf signer balance or allowance is missing, sender execution will revert onchain."
      },
      {
        "title": "2) Approve",
        "body": "Sender approves Swap to spend the sender ERC20.\nSigner approves Swap to spend the signer asset."
      },
      {
        "title": "3) Create order",
        "body": "Order fields:\n\nnonce: unique per signer\nexpiry: unix seconds\nprotocolFee: must match Swap.protocolFee() at execution time\nsigner: Party struct\nsender: Party struct\naffiliateWallet, affiliateAmount: optional, set to zero for now"
      },
      {
        "title": "4) Sign EIP-712",
        "body": "Use protocol-specific domain/types based on routed swap contract.\n\nLegacy Swap v4.2\n\nDomain:\n\nname: SWAP\nversion: 4.2\nchainId: 8453\nverifyingContract: routed legacy Swap address\n\n\nTypes:\n\nOrder(uint256 nonce,uint256 expiry,uint256 protocolFee,Party signer,Party sender,address affiliateWallet,uint256 affiliateAmount)\nParty(address wallet,address token,bytes4 kind,uint256 id,uint256 amount)\n\nSwapERC20 v4.3\n\nDomain:\n\nname: SWAP_ERC20\nversion: 4.3\nchainId: 8453\nverifyingContract: 0x95D598D839dE1B030848664960F0A20b848193F4\n\n\nTypes:\n\nOrderERC20(uint256 nonce,uint256 expiry,address signerWallet,address signerToken,uint256 signerAmount,uint256 protocolFee,address senderWallet,address senderToken,uint256 senderAmount)"
      },
      {
        "title": "5) Execute",
        "body": "Sender calls:\n\nswap(recipient, maxRoyalty, order)\n\nRecommended defaults:\n\nrecipient = sender for testing\nmaxRoyalty = 0 unless the signer asset is an ERC2981 NFT"
      },
      {
        "title": "6) Confirm",
        "body": "Check tx hash on BaseScan\nCheck balances before and after"
      },
      {
        "title": "7) Share orders in AirSwap Web compatible compressed format",
        "body": "Farcaster mention and recipient rules\n\nDo not assume plain @username text will create a mention.\nFor reliable mention behavior when posting via API, always set both:\n\nmentions: array of target FIDs\nmentions_positions: UTF-8 byte offsets\n\n\nImportant: when using hub makeCastAdd mention fields, do not duplicate the handle in text manually at the same position. The client can render duplicated handles if both are present.\nMention offsets must be computed from UTF-8 bytes, not JS string index, before POSTing.\nValidation rule before sending cast:\n\nmentions.length === mentions_positions.length\neach position points to the beginning of the exact @handle token in text\n\n\nFor private order recipient lock, prefer the taker's Neynar verified_addresses.primary.eth_address when available.\nIf no primary verified address exists, fall back to custody address only with explicit confirmation.\n\nLong-cast link budget rules\n\nKeep order announcement text minimal when including a miniapp deeplink with compressed order query param.\nPrefer miniapp deeplink over embedding raw compressed blob in cast text.\nAvoid adding both long prose and raw compressed string in the same cast if you need to stay under long-cast size limits.\n\nStrict cast-parse format for cast-hash based loading\n\nIf miniapp is loading by cast hash, include one dedicated machine line in cast text:\n\nGBZ1:<compressedOrder>\n\n\nGBZ1: must be uppercase and start at line start.\nNo spaces inside <compressedOrder>.\nKeep only one GBZ1: line per cast.\nApp parser should reject casts without this exact line and show fallback error.\n\nNFT cast metadata and embed rules\n\nIn maker step 1 cast, include NFT metadata where possible:\n\nResolve NFT symbol from contract metadata readers and prefer it over generic fallback labels.\nAttach NFT image embeds to the step 1 cast when available.\n\n\nEmbed ordering is strict for 2-embed NFT offers:\n\nembed[0] = signer NFT image\nembed[1] = sender NFT image\n\n\nIf only one leg is NFT, include a single embed for that NFT image.\n\nHuman-readable cast line templates (context-dependent)\n\nStep 1 cast must include a natural-language summary line that depends on token kinds.\nCanonical phrasing:\n\nI offer <signer-leg text> for <sender-leg text>\n\n\nLeg text formatting by kind:\n\nERC20: <amount> <symbol>\nERC721: <symbol> #<tokenId>\nERC1155: <qty>x <symbol> #<tokenId>\n\n\nExamples:\n\nERC20 -> ERC20: I offer 12 USDC for 0.005 WETH\nERC721 -> ERC20: I offer PFP #176 for 200 USDC\nERC20 -> ERC721: I offer 200 USDC for PFP #176\nERC721 -> ERC721: I offer PFP #176 for PFP #174\nERC1155 -> ERC20: I offer 3x GAMEITEM #42 for 10 USDC\n\n\nAdd context line directly below summary:\n\nPrivate order: Private offer • expires in <human-duration>\nPublic order: Open offer • expires in <human-duration>\n\n\nAlways keep machine line unchanged and on its own line:\n\nGBZ1:<compressedOrder>\n\n\nMentioning private counterparty via API:\n\nDo not rely only on plain handle text.\nProvide mentions and mentions_positions aligned to UTF-8 byte offsets.\n\nERC721 order and allowance handling (legacy Swap)\n\nFor ERC721 sender legs on legacy Swap contracts, token quantity is encoded by id and amount must be 0.\nDo not use amount = 1 when ERC721 is on the sender leg. This can trigger AmountOrIDInvalid in onchain check(...).\nFor signer-side ERC721 in current tested flow, keep signer leg encoded as id=<tokenId>, amount=0.\n\nERC721 approvals (security + compatibility)\n\nPrefer explicit per-token approvals for ERC721:\n\napprove(swapContract, tokenId)\n\n\nDo not rely on setApprovalForAll for ERC721 in this flow.\nLegacy Swap ERC721 adapter allowance check is getApproved(tokenId) == swapContract.\nTherefore, isApprovedForAll alone can still show SignerAllowanceLow in check(...).\nUI/API allowance gating for ERC721 must use getApproved(tokenId).\n\nERC1155 approvals\n\nKeep ERC1155 approval path on setApprovalForAll(swapContract, true).\n\nKind routing guard\n\nIf UI kind state lags but tokenId is present, detect kind onchain before choosing approval route.\nDo not assume tokenId implies ERC721 only; ERC1155 also has tokenIds.\n\nRoyalty-bearing NFT handling (ERC2981)\n\nLegacy Swap can pull royalties from sender side when signer token supports ERC2981.\nRoyalty check path:\n\nsupportsInterface(0x2a55205a) on signer token\nroyaltyInfo(signerTokenId, senderAmountRaw)\n\n\nUnits are raw sender-token units (e.g. USDC 6 decimals).\nTaker-side required sender approval must include:\n\nsenderAmount + protocolFee + affiliateAmount + royaltyAmount\n\n\nLegacy swap execution must set maxRoyalty >= computed royalty amount, else revert RoyaltyExceedsMax(...).\n\nFor social posting and agent handoff, use the compressed ERC20 full-order format used by AirSwap Web.\nThis is a URL-safe compressed payload, not a keccak hash.\nThis payload is often too large for legacy cast limits.\nUse long casts when posting full compressed orders in one message.\n\nEncoded fields\n\nchainId\nswapContract\nnonce\nexpiry\nsignerWallet\nsignerToken\nsignerAmount\nprotocolFee\nsenderWallet\nsenderToken\nsenderAmount\nv\nr\ns\n\nsigner_make_order.js now writes\n\nairswapWeb.compressedOrder\nairswapWeb.orderPath as /order/<compressedOrder>\n\nmake_cast_payload.js writes\n\nairswapWeb.orderUrl with URL-encoded compressed order for reliable clickable links\nraw compressedOrder remains unencoded for machine parsing and execution"
      },
      {
        "title": "8) Decompress and take a posted order",
        "body": "If you receive only the compressed order blob from a cast\n\nDecompress it with AirSwap utils decompressFullOrderERC20(compressedOrder)\nPrefer in-memory handling from cast payloads. Do not rely on local JSON files as durable storage.\nUse Farcaster cast content as the canonical order transport and storage layer.\n\nIf you receive the structured cast payload from make_cast_payload.js\n\nRead payload.airswapWeb.compressedOrder\nDecompress to recover full order and signature parts\nFor bot execution, ignore any human-summary totals and compute required sender spend from order fields:\n\nfeeAmount = order.sender.amount * order.protocolFee / 10000\ntotalRequired = order.sender.amount + feeAmount + order.affiliateAmount\n\nThen execute with sender flow\n\nSet SENDER_PRIVATE_KEY\nRun node scripts/sender_execute_order.js\n\nSender execution script already enforces\n\nexpiry check\nsender wallet restriction for non-open orders\nEIP-712 signature verification\nsigner balance and allowance preflight\nsender balance and allowance preflight"
      },
      {
        "title": "Scripts",
        "body": "Scripts are under scripts/.\n\nThese scripts are reference implementations.\nThey can be run by one operator with both keys for testing.\nIn a real agent to agent swap, the signer and sender should run their parts separately.\n\nRecommended setup\n\nUse Node 20+\nInstall deps in a temp folder\n\nnpm i ethers@5 lz-string\n\nThen run one of these\n\nnode scripts/signer_make_order.js\nnode scripts/sender_execute_order.js\nnode scripts/make_cast_payload.js to generate both human-readable cast text and machine-readable payload\nscripts/post_cast_farcaster_agent.js is intentionally disabled for security hardening\n\nReason: avoid file-read + network-send pattern in shared skill script audits\nUse Neynar/OpenClaw posting path instead\n\nFor a single machine end to end test\n\nnode scripts/test_weth_usdc_swap.js\n\nFor details and parameters\nRead scripts/README.md"
      }
    ],
    "body": "Grand Bazaar P2P Swap\n\nThis skill documents how to execute agent-to-agent swaps on Base mainnet using deployed AirSwap Swap contracts.\n\nSender-side token standard is routed to the matching Swap contract:\n\nERC20<>ERC20 -> SwapERC20 on Base 0x95D598D839dE1B030848664960F0A20b848193F4\nERC20 sender (non-ERC20<>ERC20 routes) -> ERC20-sender Swap\nERC721 sender -> ERC721-sender Swap\nERC1155 sender -> ERC1155-sender Swap\n\nThe sender is still the submitting wallet, and must satisfy the selected Swap's sender-kind requirement.\n\nDeployed contracts\n\nRead: references/base-mainnet-deployments.md\n\nSafety rules\nNever paste or log private keys in chat.\nPrefer fresh test wallets for demos.\nAlways start with tiny amounts.\nVerify token addresses before approving.\nWorkflow\nFavorable inbound offer rule\n\nWhen someone offers a swap and the price is clearly good value for you, default to taking it quickly with safety checks.\n\nUse this fast path:\n\nParse the cast for GBZ1:<compressedOrder>\nDecompress and reconstruct order + signature\nVerify sender wallet targeting and signature\nRun sender preflight checks\nExecute the swap if checks pass\nReply on the cast using the Grand Bazaar success template:\nThanks for the swap 🤝\nhttps://basescan.org/tx/<txHash>\nPost as a reply to the parent offer cast (cast hash origin)\n\nThis applies especially to direct offer replies where speed matters but safety preflight is still mandatory.\n\nFavorable outbound negotiation rule\n\nWhen negotiating with other users or agents, proactively make favorable outbound offers to improve fill probability.\n\nDefault outbound behavior:\n\nStart from fair market terms, then bias slightly in the counterparty’s favor\nKeep sizes practical and gas-efficient\nPrefer private targeted orders while negotiating, then open only if requested\nKeep expiry short enough for quick decisions, long enough for execution\nRun onchain validation before posting maker casts:\ncall Swap.check(senderWallet, orderWithSignature) on the target swap contract\nrequire nonceUsed(signer, nonce) === false\nignore SenderAllowanceLow on maker flow, since sender approves on taker side after cast discovery\nblock posting if there are any other check errors besides SenderAllowanceLow\nUse a required 2-part posting flow every time with no exceptions:\npost the swap order cast with clear summary + strict machine line GBZ1:<compressedOrder>\nfor private offers, include counterparty mention via API fields (mentions, mentions_positions)\nimmediately post a follow-up embed cast that deeplinks to Grand Bazaar /c/<step1CastHash>\nDo not stop after step 1. A maker post is incomplete until step 2 is confirmed posted.\n\nOutbound offer loop:\n\nPropose a favorable draft quote\nIf counterparty hesitates, improve terms in small controlled steps\nRe-sign and repost updated order with fresh nonce/expiry\nStop if value or risk limits are breached\n\nGuardrails:\n\nNever bypass preflight or signature checks\nNever use unsafe gas settings to force execution\nDo not over-concede beyond configured risk tolerance\nExplicit size-aware pricing parameters\n\nRead: references/pricing-params.md\n\nUse that reference file as the source of truth for pricing thresholds, impact capture, negotiation steps, and execution safety limits.\n\nThis is a two party protocol. One agent acts as the signer. A different agent acts as the sender.\n\n0) Pick roles\nSigner sets the terms and signs the EIP-712 order.\nSender submits swap onchain and pays the sender ERC20 amount plus protocol fee.\n\nBecause each deployed Swap has immutable requiredSenderKind, sender leg must match the routed contract kind.\n\n0.1) What each party does\n\nSigner responsibilities\n\nDecide terms and build the order.\nApprove the signer asset to the Swap contract.\nProduce an EIP-712 signature over the order.\nSend the signed order to the sender agent.\n\nMandatory maker approval rule\n\nIn maker flow, always perform the required signer-side approval before signing/posting.\nNever assume existing allowance is sufficient without checking onchain allowance against the full signer-side required amount for the routed swap contract.\nFor SwapERC20, signer required amount is signerAmount + signer protocol fee because fee is transferred from signer token side.\nIf signer allowance is below required amount, submit approve tx and wait for confirmation before signing the order cast.\nSender-side allowance must not block maker posting. Ignore SenderAllowanceLow in maker validation gates.\nTreat maker sign/post without required signer approval as invalid workflow.\n\nProtocol fee side semantics\n\nLegacy Swap: protocol fee is accounted on sender side for required spend/allowance calculations.\nSwapERC20: protocol fee is accounted on signer side for required spend/allowance calculations.\nUI implications in maker/taker surfaces:\nFee footer, fee-adjusted amount previews, and fee-adjusted value previews must appear on the side that actually pays the fee.\nShow fee-side preview only after both tokens are selected so route is known.\n\nSender responsibilities\n\nVerify the order details and expiry.\nEnsure sender ERC20 balance is enough for amount plus fee.\nApprove the sender ERC20 to the Swap contract.\nSubmit the swap transaction.\nShare the tx hash back to the signer.\n1) Ensure balances\nSender needs Base ETH for gas.\nSender needs the sender ERC20.\nSigner needs Base ETH for gas.\nSigner needs the signer asset and must approve it.\n\nCritical preflight before any sender execution\n\nVerify signer token balance is at least order.signer.amount.\nVerify signer allowance to Swap is at least order.signer.amount.\nVerify sender token balance is at least order.sender.amount + protocol fee + affiliateAmount.\nVerify sender allowance to Swap is at least the same total.\nVerify order expiry has enough time buffer.\nEstimate swap gas and abort if estimate exceeds MAX_GAS_LIMIT.\nCap maxPriorityFeePerGas to 10% of current gas price.\n\nTemporary execution override\n\nSome valid orders can fail at preflight simulation (eth_call / staticCall) or eth_estimateGas with execution reverted and TransferFailed(from,to) but still execute successfully onchain.\nDo not treat simulation/estimate reverts as absolute failure when all other safety checks pass.\nIn this case, bypass estimate-gated abort and submit with a manual gas limit of 650000.\nKeep fee caps active and log that manual gas was used due to simulation/estimate failure.\n\nGas safety policy for all agents\n\nNever submit swap with unbounded gas limit.\nNever use static high priority fee on Base.\nLog gasPrice, maxPriorityFeePerGas, maxFeePerGas, estimate status, and chosen gas limit before broadcast.\nTemporary rule: if estimate reverts on an otherwise valid order, submit once with manual gas limit 650000, then investigate root cause.\n\nIf signer balance or allowance is missing, sender execution will revert onchain.\n\n2) Approve\nSender approves Swap to spend the sender ERC20.\nSigner approves Swap to spend the signer asset.\n3) Create order\n\nOrder fields:\n\nnonce: unique per signer\nexpiry: unix seconds\nprotocolFee: must match Swap.protocolFee() at execution time\nsigner: Party struct\nsender: Party struct\naffiliateWallet, affiliateAmount: optional, set to zero for now\n4) Sign EIP-712\n\nUse protocol-specific domain/types based on routed swap contract.\n\nLegacy Swap v4.2\n\nDomain:\nname: SWAP\nversion: 4.2\nchainId: 8453\nverifyingContract: routed legacy Swap address\nTypes:\nOrder(uint256 nonce,uint256 expiry,uint256 protocolFee,Party signer,Party sender,address affiliateWallet,uint256 affiliateAmount)\nParty(address wallet,address token,bytes4 kind,uint256 id,uint256 amount)\n\nSwapERC20 v4.3\n\nDomain:\nname: SWAP_ERC20\nversion: 4.3\nchainId: 8453\nverifyingContract: 0x95D598D839dE1B030848664960F0A20b848193F4\nTypes:\nOrderERC20(uint256 nonce,uint256 expiry,address signerWallet,address signerToken,uint256 signerAmount,uint256 protocolFee,address senderWallet,address senderToken,uint256 senderAmount)\n5) Execute\n\nSender calls:\n\nswap(recipient, maxRoyalty, order)\n\nRecommended defaults:\n\nrecipient = sender for testing\nmaxRoyalty = 0 unless the signer asset is an ERC2981 NFT\n6) Confirm\nCheck tx hash on BaseScan\nCheck balances before and after\n7) Share orders in AirSwap Web compatible compressed format\n\nFarcaster mention and recipient rules\n\nDo not assume plain @username text will create a mention.\nFor reliable mention behavior when posting via API, always set both:\nmentions: array of target FIDs\nmentions_positions: UTF-8 byte offsets\nImportant: when using hub makeCastAdd mention fields, do not duplicate the handle in text manually at the same position. The client can render duplicated handles if both are present.\nMention offsets must be computed from UTF-8 bytes, not JS string index, before POSTing.\nValidation rule before sending cast:\nmentions.length === mentions_positions.length\neach position points to the beginning of the exact @handle token in text\nFor private order recipient lock, prefer the taker's Neynar verified_addresses.primary.eth_address when available.\nIf no primary verified address exists, fall back to custody address only with explicit confirmation.\n\nLong-cast link budget rules\n\nKeep order announcement text minimal when including a miniapp deeplink with compressed order query param.\nPrefer miniapp deeplink over embedding raw compressed blob in cast text.\nAvoid adding both long prose and raw compressed string in the same cast if you need to stay under long-cast size limits.\n\nStrict cast-parse format for cast-hash based loading\n\nIf miniapp is loading by cast hash, include one dedicated machine line in cast text:\nGBZ1:<compressedOrder>\nGBZ1: must be uppercase and start at line start.\nNo spaces inside <compressedOrder>.\nKeep only one GBZ1: line per cast.\nApp parser should reject casts without this exact line and show fallback error.\n\nNFT cast metadata and embed rules\n\nIn maker step 1 cast, include NFT metadata where possible:\nResolve NFT symbol from contract metadata readers and prefer it over generic fallback labels.\nAttach NFT image embeds to the step 1 cast when available.\nEmbed ordering is strict for 2-embed NFT offers:\nembed[0] = signer NFT image\nembed[1] = sender NFT image\nIf only one leg is NFT, include a single embed for that NFT image.\n\nHuman-readable cast line templates (context-dependent)\n\nStep 1 cast must include a natural-language summary line that depends on token kinds.\nCanonical phrasing:\nI offer <signer-leg text> for <sender-leg text>\nLeg text formatting by kind:\nERC20: <amount> <symbol>\nERC721: <symbol> #<tokenId>\nERC1155: <qty>x <symbol> #<tokenId>\nExamples:\nERC20 -> ERC20: I offer 12 USDC for 0.005 WETH\nERC721 -> ERC20: I offer PFP #176 for 200 USDC\nERC20 -> ERC721: I offer 200 USDC for PFP #176\nERC721 -> ERC721: I offer PFP #176 for PFP #174\nERC1155 -> ERC20: I offer 3x GAMEITEM #42 for 10 USDC\nAdd context line directly below summary:\nPrivate order: Private offer • expires in <human-duration>\nPublic order: Open offer • expires in <human-duration>\nAlways keep machine line unchanged and on its own line:\nGBZ1:<compressedOrder>\nMentioning private counterparty via API:\nDo not rely only on plain handle text.\nProvide mentions and mentions_positions aligned to UTF-8 byte offsets.\n\nERC721 order and allowance handling (legacy Swap)\n\nFor ERC721 sender legs on legacy Swap contracts, token quantity is encoded by id and amount must be 0.\nDo not use amount = 1 when ERC721 is on the sender leg. This can trigger AmountOrIDInvalid in onchain check(...).\nFor signer-side ERC721 in current tested flow, keep signer leg encoded as id=<tokenId>, amount=0.\n\nERC721 approvals (security + compatibility)\n\nPrefer explicit per-token approvals for ERC721:\napprove(swapContract, tokenId)\nDo not rely on setApprovalForAll for ERC721 in this flow.\nLegacy Swap ERC721 adapter allowance check is getApproved(tokenId) == swapContract.\nTherefore, isApprovedForAll alone can still show SignerAllowanceLow in check(...).\nUI/API allowance gating for ERC721 must use getApproved(tokenId).\n\nERC1155 approvals\n\nKeep ERC1155 approval path on setApprovalForAll(swapContract, true).\n\nKind routing guard\n\nIf UI kind state lags but tokenId is present, detect kind onchain before choosing approval route.\nDo not assume tokenId implies ERC721 only; ERC1155 also has tokenIds.\n\nRoyalty-bearing NFT handling (ERC2981)\n\nLegacy Swap can pull royalties from sender side when signer token supports ERC2981.\nRoyalty check path:\nsupportsInterface(0x2a55205a) on signer token\nroyaltyInfo(signerTokenId, senderAmountRaw)\nUnits are raw sender-token units (e.g. USDC 6 decimals).\nTaker-side required sender approval must include:\nsenderAmount + protocolFee + affiliateAmount + royaltyAmount\nLegacy swap execution must set maxRoyalty >= computed royalty amount, else revert RoyaltyExceedsMax(...).\n\nFor social posting and agent handoff, use the compressed ERC20 full-order format used by AirSwap Web. This is a URL-safe compressed payload, not a keccak hash. This payload is often too large for legacy cast limits. Use long casts when posting full compressed orders in one message.\n\nEncoded fields\n\nchainId\nswapContract\nnonce\nexpiry\nsignerWallet\nsignerToken\nsignerAmount\nprotocolFee\nsenderWallet\nsenderToken\nsenderAmount\nv\nr\ns\n\nsigner_make_order.js now writes\n\nairswapWeb.compressedOrder\nairswapWeb.orderPath as /order/<compressedOrder>\n\nmake_cast_payload.js writes\n\nairswapWeb.orderUrl with URL-encoded compressed order for reliable clickable links\nraw compressedOrder remains unencoded for machine parsing and execution\n8) Decompress and take a posted order\n\nIf you receive only the compressed order blob from a cast\n\nDecompress it with AirSwap utils decompressFullOrderERC20(compressedOrder)\nPrefer in-memory handling from cast payloads. Do not rely on local JSON files as durable storage.\nUse Farcaster cast content as the canonical order transport and storage layer.\n\nIf you receive the structured cast payload from make_cast_payload.js\n\nRead payload.airswapWeb.compressedOrder\nDecompress to recover full order and signature parts\nFor bot execution, ignore any human-summary totals and compute required sender spend from order fields:\nfeeAmount = order.sender.amount * order.protocolFee / 10000\ntotalRequired = order.sender.amount + feeAmount + order.affiliateAmount\n\nThen execute with sender flow\n\nSet SENDER_PRIVATE_KEY\nRun node scripts/sender_execute_order.js\n\nSender execution script already enforces\n\nexpiry check\nsender wallet restriction for non-open orders\nEIP-712 signature verification\nsigner balance and allowance preflight\nsender balance and allowance preflight\nScripts\n\nScripts are under scripts/.\n\nThese scripts are reference implementations. They can be run by one operator with both keys for testing. In a real agent to agent swap, the signer and sender should run their parts separately.\n\nRecommended setup\n\nUse Node 20+\nInstall deps in a temp folder\nnpm i ethers@5 lz-string\n\nThen run one of these\n\nnode scripts/signer_make_order.js\nnode scripts/sender_execute_order.js\nnode scripts/make_cast_payload.js to generate both human-readable cast text and machine-readable payload\nscripts/post_cast_farcaster_agent.js is intentionally disabled for security hardening\nReason: avoid file-read + network-send pattern in shared skill script audits\nUse Neynar/OpenClaw posting path instead\n\nFor a single machine end to end test\n\nnode scripts/test_weth_usdc_swap.js\n\nFor details and parameters Read scripts/README.md"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/agriimony/grand-bazaar-swap",
    "publisherUrl": "https://clawhub.ai/agriimony/grand-bazaar-swap",
    "owner": "agriimony",
    "version": "0.1.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/grand-bazaar-swap",
    "downloadUrl": "https://openagent3.xyz/downloads/grand-bazaar-swap",
    "agentUrl": "https://openagent3.xyz/skills/grand-bazaar-swap/agent",
    "manifestUrl": "https://openagent3.xyz/skills/grand-bazaar-swap/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/grand-bazaar-swap/agent.md"
  }
}