{
  "schemaVersion": "1.0",
  "item": {
    "slug": "ceaser-send",
    "name": "Openclaw Send Skill",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/Zyra-V21/ceaser-send",
    "canonicalUrl": "https://clawhub.ai/Zyra-V21/ceaser-send",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/ceaser-send",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=ceaser-send",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md",
      "helpers/wallet-ops.js",
      "mcporter.json",
      "package-lock.json",
      "package.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/ceaser-send"
    },
    "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/ceaser-send",
    "agentPageUrl": "https://openagent3.xyz/skills/ceaser-send/agent",
    "manifestUrl": "https://openagent3.xyz/skills/ceaser-send/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/ceaser-send/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": "Ceaser Private Send",
        "body": "You are a skill that executes a complete private ETH transfer on Base L2 (chain ID 8453) using the Ceaser privacy protocol. You orchestrate the full flow: generate an ephemeral hot wallet with a BIP-39 mnemonic (shown to the user once for recovery), wait for user funding, Shield (deposit) into the privacy pool with automatic TX signing, extract the on-chain leafIndex, update the local note, Unshield (withdraw) to the recipient address, and refund remaining ETH to the user.\n\nNetwork: Base L2 (chain ID 8453)\nContract: 0x278652aA8383cBa29b68165926d0534e52BcD368\nFacilitator: https://ceaser.org\nProtocol Fee: 0.25% (25 bps) per operation\nValid Denominations: 0.001, 0.01, 0.1, 1, 10, 100 ETH\nProof System: Noir circuits compiled to UltraHonk proofs (no trusted setup)\n\nThis skill uses the ceaser-mcp npm package for shield, unshield, and note management operations. All ceaser tool calls use CLI subcommands:\n\nnpx -y ceaser-mcp <subcommand> [args]\n\nAlternatively, if mcporter is installed with the ceaser MCP server configured (see {baseDir}/mcporter.json), you may use mcporter call ceaser.TOOL_NAME as an equivalent method. CLI is the primary and recommended approach.\n\nExactly ONE manual step is required: the user must send ETH to a generated hot wallet address. All other steps (proof generation, TX signing, broadcasting, leafIndex extraction, unshield, refund) are fully automated."
      },
      {
        "title": "PRIVACY WARNING",
        "body": "Auto-signing mode creates observable on-chain links that reduce privacy compared to manual signing (the /ceaser skill). Specifically:\n\nFunding link: The user's main wallet (A) sends ETH to the hot wallet (H). This transfer is publicly visible on-chain, linking A to H.\nShield link: The hot wallet (H) calls shieldETH() on the contract. H is now linked to the shield deposit.\nRefund link: After the operation, remaining ETH is refunded from H back to A (or another address). This creates another public link.\nTiming correlation: Funding, shield, unshield, and refund happen in rapid succession (minutes apart), making them easy to correlate.\nWallet fingerprint: The hot wallet performs exactly 2-3 transactions (fund receive, shield, refund) and is never reused -- this pattern is distinctive.\n\nRecommendation: For maximum privacy, use the /ceaser skill (manual signing via MetaMask). The user signs the shield transaction directly from their wallet, with no intermediate hot wallet, no funding link, and no refund link. Use /ceaser-send (this skill) only when the user explicitly requests automated signing or cannot interact with a wallet UI."
      },
      {
        "title": "Prerequisites",
        "body": "Before executing this skill, verify:\n\nnode and npx are installed (for ceaser-mcp CLI and wallet-ops helper)\ncurl and jq are installed (for TX receipt parsing and notes.json manipulation)\nnode_modules are installed in the skill directory (test: node {baseDir}/helpers/wallet-ops.js --help)\nUser has a wallet capable of sending ETH on Base Mainnet (for funding the hot wallet)\nWallet has enough ETH for the desired amount + 0.25% protocol fee + ~0.0005 ETH gas reserve"
      },
      {
        "title": "Pre-Flight Checks",
        "body": "Execute ALL of these checks BEFORE starting the flow. Abort if any check fails."
      },
      {
        "title": "Check 1: Facilitator Status",
        "body": "Run:\n\ncurl -s \"https://ceaser.org/status\" | jq .\n\nVerify:\n\nFacilitator is operational (response received without error)\ncircuitBreaker.tripped is false\nindexer.synced is true\nFacilitator has enough balance for gas (balance > 0.001 ETH)\n\nIf the facilitator is down or circuit breaker is tripped, inform the user and abort."
      },
      {
        "title": "Check 2: Denomination Validation",
        "body": "Run:\n\ncurl -s \"https://ceaser.org/api/ceaser/denominations\" | jq .\n\nVerify:\n\nThe user's requested amount is in the denominations list\nValid: 0.001, 0.01, 0.1, 1, 10, 100 ETH\n\nIf the amount is not a valid denomination, show the user the valid options and ask them to choose."
      },
      {
        "title": "Check 3: Fee Calculation",
        "body": "Run:\n\ncurl -s \"https://ceaser.org/api/ceaser/fees/AMOUNT_WEI\" | jq .\n\nReplace AMOUNT_WEI with the amount in wei (e.g., 1000000000000000 for 0.001 ETH).\n\nPresent to the user:\n\nGross amount (what they send)\nProtocol fee (0.25%)\nNet amount (what the recipient receives after unshield fee)\nNote: Fees apply on BOTH shield and unshield. Total round-trip fee is approximately 0.5%.\n\nStore internally: amountWei and feeWei from the response (needed for funding calculation in Wallet Generation Phase).\n\nAsk the user to confirm they want to proceed."
      },
      {
        "title": "Check 4: Recipient Address Validation",
        "body": "Validate the recipient address format: must match /^0x[0-9a-fA-F]{40}$/.\n\nIf invalid, inform the user and ask for a correct Ethereum address."
      },
      {
        "title": "Check 5: Existing Notes",
        "body": "Run:\n\nnpx -y ceaser-mcp notes\n\nCheck for existing unspent notes:\n\nIf unspent notes with valid leafIndex exist: Ask the user whether to use an existing note (skip shield, go directly to unshield) or create a new shield.\nIf unspent notes with leafIndex=null exist: Inform the user: \"A note exists but its leafIndex is missing. The shield transaction may not have confirmed yet. If you have the TX hash, we can extract the leafIndex.\"\nIf no suitable notes exist: Proceed with the full Shield flow."
      },
      {
        "title": "Check 6: Helper Script Availability",
        "body": "Run:\n\nnode {baseDir}/helpers/wallet-ops.js --help\n\nVerify: valid JSON output listing available commands (generate, balance, sign-and-send, refund).\n\nIf this check fails: inform the user and abort. Message: \"Helper script not available. Please run npm install in the skill directory.\""
      },
      {
        "title": "Flow Decision",
        "body": "Based on Pre-Flight Check 5:\n\nPath A -- Use Existing Note:\nIf the user wants to use an existing unspent note with a valid leafIndex, skip directly to the Unshield Phase.\n\nPath B -- Update Existing Note:\nIf a note has leafIndex=null and the user has the TX hash, skip to the TX Confirmation and leafIndex Extraction phase.\n\nPath C -- Full Shield Flow:\nNo suitable note exists. Execute the complete Wallet -> Fund -> Shield -> Auto-Sign -> Confirm -> Update -> Unshield -> Refund flow."
      },
      {
        "title": "Wallet Generation Phase",
        "body": "Only execute for Path C (Full Shield Flow)."
      },
      {
        "title": "Step 1: Generate Hot Wallet",
        "body": "Run:\n\nnode {baseDir}/helpers/wallet-ops.js generate\n\nStore internally (in your working context):\n\nmnemonic -- The 12-word BIP-39 recovery phrase.\naddress -- The hot wallet address to show the user."
      },
      {
        "title": "Step 1.5: Show Mnemonic to User",
        "body": "IMPORTANT: Show the mnemonic to the user EXACTLY ONCE with a clear security warning:\n\nRECOVERY MNEMONIC (save this securely):\nword1 word2 word3 word4 word5 word6 word7 word8 word9 word10 word11 word12\nSAVE THIS MNEMONIC SECURELY. It controls the hot wallet funds.\nIf this session breaks after funding, import these 12 words into MetaMask (or any BIP-39 wallet) to recover your ETH.\nDo NOT share this mnemonic. Anyone with these words can access the hot wallet.\n\nAfter showing the mnemonic once, do NOT repeat it in summaries, follow-up responses, or any subsequent messages."
      },
      {
        "title": "Step 2: Calculate Funding Amount",
        "body": "Use the fee data from Pre-Flight Check 3:\n\nShield cost: amountWei + feeWei from ceaser_get_fees response\nGas reserve: 500000000000000 wei (0.0005 ETH -- conservative, covers ~500k gas at 1 gwei on Base L2)\nTotal funding = (amountWei + feeWei) + 500000000000000\n\nConvert total funding to ETH for display. Round UP to a human-friendly value if needed."
      },
      {
        "title": "Step 3: Ask for Refund Address",
        "body": "Before showing the funding instructions, ask the user:\n\n\"Where should I send any remaining ETH after the operation? Please provide your wallet address for the refund.\"\n\nStore the refund address internally. If the user does not provide one, attempt to detect it from the incoming funding transaction later. If detection fails, ask again after the shield completes.\n\nNote: If the session breaks after funding, the user can also recover hot wallet funds by importing the mnemonic into MetaMask."
      },
      {
        "title": "Step 4: Show Funding Instructions",
        "body": "Present to the user:\n\nHot Wallet Address: HOT_WALLET_ADDRESS\nSend exactly: FUNDING_AMOUNT ETH (or slightly more)\nNetwork: Base Mainnet (Chain ID 8453)\nSend EXACTLY the specified amount or slightly more. Sending less will cause the shield to fail. Any excess ETH will be automatically refunded after completion.\nIf you lose the mnemonic, you cannot recover funds from this wallet. The mnemonic will NOT be shown again.\nIn case of session interruption, use the mnemonic to recover funds via MetaMask."
      },
      {
        "title": "Balance Monitoring Phase",
        "body": "Only execute for Path C, after showing funding instructions."
      },
      {
        "title": "Polling Logic",
        "body": "Repeatedly execute:\n\nnode {baseDir}/helpers/wallet-ops.js balance --address HOT_WALLET_ADDRESS\n\nPolling interval: 10 seconds\nCheck: balanceWei >= required funding amount (in wei)\nMaximum polling duration: 10 minutes (60 cycles)"
      },
      {
        "title": "Cancel Handling",
        "body": "The user can say \"cancel\" or \"abbrechen\" at any time during the funding wait.\n\nCancel BEFORE funding (balance == 0): Clean abort. No loss. Key discarded.\nCancel AFTER partial funding (balance > 0): Execute refund to user's address first, then abort.\n\nTo refund on cancel:\n\nCEASER_HOT_MNEMONIC=\"MNEMONIC_PHRASE\" node {baseDir}/helpers/wallet-ops.js refund --recipient REFUND_ADDRESS --rpc https://mainnet.base.org"
      },
      {
        "title": "Timeout Handling",
        "body": "After 5 minutes without funding: Remind user: \"Still waiting for ETH at HOT_WALLET_ADDRESS...\"\nAfter 10 minutes: Abort with clear message.\nOn abort with balance > 0: Automatic refund to user address.\nOn abort with balance == 0: Clean abort, no loss.\nWarning on timeout: \"If you saved the mnemonic, you can still recover funds via MetaMask. Otherwise, do not send ETH after the timeout.\""
      },
      {
        "title": "Partial Funding",
        "body": "If balance > 0 but less than required:\n\n\"Received: X ETH. Required: Y ETH. Please send an additional Z ETH.\"\n\nContinue polling."
      },
      {
        "title": "Funding Confirmed",
        "body": "When balance >= required amount:\n\n\"Funding received. Proceeding with Shield operation.\"\n\nIf the user provided excess ETH:\n\n\"Received more ETH than required. Excess will be refunded after completion.\""
      },
      {
        "title": "Shield Phase",
        "body": "Run:\n\nnpx -y ceaser-mcp shield USER_AMOUNT\n\nReplace USER_AMOUNT with the ETH denomination (e.g., 0.1)."
      },
      {
        "title": "Expected Response Fields",
        "body": "note.id -- Internal ID for later reference\nnote.commitment -- bytes32 commitment hash\nnote.leafIndex -- Will be null (expected)\nunsignedTx.to -- Must be 0x278652aA8383cBa29b68165926d0534e52BcD368\nunsignedTx.data -- ABI-encoded calldata\nunsignedTx.value -- Amount + fee in wei\nunsignedTx.chainId -- Must be 8453\nbackup -- Base64-encoded backup string (SECURITY CRITICAL)\ninstructions -- Array of guidance messages"
      },
      {
        "title": "Validation",
        "body": "Verify after receiving the response:\n\nunsignedTx.value from shield response matches (amountWei + feeWei) from ceaser_get_fees\nunsignedTx.chainId == 8453\nunsignedTx.to == 0x278652aA8383cBa29b68165926d0534e52BcD368"
      },
      {
        "title": "Backup String Handling",
        "body": "SECURITY CRITICAL:\n\nShow the backup string to the user EXACTLY ONCE with a clear warning:\n\nSAVE THIS BACKUP STRING SECURELY. It contains your private ZK secrets (secret + nullifier). Anyone with this string can withdraw your shielded ETH. Store it offline. Do not share it.\n\n\nDo NOT repeat the backup string in subsequent messages.\nDo NOT include the backup string in summaries or follow-up responses."
      },
      {
        "title": "Internal State",
        "body": "Remember these values for later steps (keep in your working context, do not output again):\n\nnote.id\nnote.commitment\nbackup (needed for leafIndex update)\npendingTxFile (path to the saved unsigned TX -- auto-detected by sign-and-send, no need to pass manually)"
      },
      {
        "title": "Shield Error After Funding (Edge Case)",
        "body": "If ceaser_shield_eth fails (proof error, facilitator down, etc.):\n\nETH is still in the hot wallet (untouched)\nRetry up to 2 times\nIf failure persists: automatic refund to user address\nInform user: \"Shield proof generation failed. Your ETH has been refunded.\""
      },
      {
        "title": "Automatic TX Signing Phase",
        "body": "This replaces the previous manual signing phase. The agent signs and broadcasts the Shield TX automatically using the mnemonic-derived hot wallet."
      },
      {
        "title": "Execute Sign-and-Send",
        "body": "The ceaser-mcp shield command automatically saves the unsigned transaction to ~/.ceaser-mcp/pending-tx.json. The sign-and-send helper auto-detects this file, so you do NOT need to pass the transaction data as a CLI argument.\n\nRun:\n\nCEASER_HOT_MNEMONIC=\"MNEMONIC_PHRASE\" node {baseDir}/helpers/wallet-ops.js sign-and-send --rpc https://mainnet.base.org\n\nThe helper automatically reads the unsigned TX from ~/.ceaser-mcp/pending-tx.json and deletes the file after a successful send.\n\nWhere:\n\nMNEMONIC_PHRASE: The 12-word mnemonic from Wallet Generation Phase (passed via environment variable, NEVER as CLI argument)\n\nAlternative: You can also specify the file explicitly or pass the JSON directly:\n\n# Explicit file path\nCEASER_HOT_MNEMONIC=\"...\" node {baseDir}/helpers/wallet-ops.js sign-and-send --unsigned-tx-file ~/.ceaser-mcp/pending-tx.json --rpc https://mainnet.base.org\n\n# Legacy: pass JSON directly (NOT recommended -- the data field is 4000-9000 chars)\nCEASER_HOT_MNEMONIC=\"...\" node {baseDir}/helpers/wallet-ops.js sign-and-send --unsigned-tx 'JSON_STRING' --rpc https://mainnet.base.org\n\nIMPORTANT: Do NOT pass the unsignedTx JSON as a CLI argument unless absolutely necessary. The data field contains 4000-9000 characters of hex-encoded ZK proof, which can cause issues with shell argument handling. Always prefer the automatic file-based approach.\n\nSecurity notes:\n\nMnemonic is passed via environment variable (CEASER_HOT_MNEMONIC), NOT as a CLI argument\nBIP-39 mnemonic words contain only ASCII lowercase letters (a-z), no shell special characters\nThe pending-tx.json file is created with 0600 permissions and deleted after successful send\n\nSet exec timeout: 60 seconds (covers gas estimation + signing + broadcasting + 1 block confirmation)."
      },
      {
        "title": "Process TX Result",
        "body": "Success (status == 1): Extract txHash, proceed to TX Confirmation phase.\n\"insufficient funds\": Inform user. Show required vs. available balance. Suggest sending more ETH.\n\"execution reverted\": Inform user. Possible causes: invalid proof, denomination mismatch, contract pause.\n\"nonce too low\": Handled automatically by the helper script (retry with fresh nonce).\nTimeout / no confirmation: TX may still be pending. Extract txHash if available and proceed to manual confirmation check."
      },
      {
        "title": "TX Confirmation and leafIndex Extraction",
        "body": "Using the txHash from the automatic sign-and-send operation, extract the leafIndex from the on-chain Shield event.\n\nNote: The helper script already waits for 1 block confirmation. In most cases, the receipt is already available. The steps below serve as verification and leafIndex extraction."
      },
      {
        "title": "Step 1: Fetch TX Receipt",
        "body": "Use Bash to query the Base Mainnet RPC:\n\ncurl -s -X POST https://mainnet.base.org \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"method\":\"eth_getTransactionReceipt\",\"params\":[\"TX_HASH\"],\"id\":1}' | jq '.result'\n\nReplace TX_HASH with the actual hash."
      },
      {
        "title": "Step 2: Check TX Status",
        "body": "status == \"0x1\": Success. Continue to Step 3.\nstatus == \"0x0\": TX failed on-chain. Inform the user: \"Transaction reverted. Possible causes: insufficient funds, gas limit too low, or contract error.\" Attempt refund of remaining hot wallet balance.\nstatus == null or no result: TX still pending. Wait 10 seconds and retry. Maximum 5 retries. If still pending, inform the user and provide the TX hash for manual checking."
      },
      {
        "title": "Step 3: Find Shield Event in Logs",
        "body": "Search the logs array for an entry matching:\n\naddress == 0x278652aa8383cba29b68165926d0534e52bcd368 (case-insensitive)\ntopics[0] == 0x39b0d8da40fd574f8fb61ef14d4f466fb3bceb268547c27680755e9b08fd8677 (Shield event signature)\n\nIf no matching log found: \"No Shield event found in this transaction. This may not be a Shield transaction. Please verify the TX hash.\" Abort."
      },
      {
        "title": "Step 4: Extract leafIndex",
        "body": "The Shield event structure:\n\ntopics[0]: Event signature hash\ntopics[1]: commitment (indexed, bytes32)\ntopics[2]: assetId (indexed, uint256)\ndata: ABI-encoded (uint32 leafIndex, uint256 timestamp)\n\nExtract leafIndex from data:\n\n# data is hex string like 0x000000000000000000000000000000000000000000000000000000000000000600000000...\n# First 32 bytes (64 hex chars after 0x) = leafIndex (uint32 zero-padded)\nLEAF_INDEX_HEX=$(echo \"DATA_FIELD\" | cut -c3-66)\nLEAF_INDEX=$(node -e \"console.log(parseInt('0x$LEAF_INDEX_HEX', 16))\")"
      },
      {
        "title": "Step 5: Validate Commitment",
        "body": "Extract topics[1] from the log and compare against the stored note.commitment.\n\nCRITICAL: If the commitment does not match, WARN the user: \"The Shield event commitment does not match the generated note. This TX hash may belong to a different shield operation. Aborting leafIndex extraction to prevent data corruption.\""
      },
      {
        "title": "Step 6: Validate leafIndex",
        "body": "The extracted leafIndex must be a non-negative integer. If it is NaN or negative, abort with an error."
      },
      {
        "title": "Edge Case: Multiple Shield Events",
        "body": "If the TX contains multiple Shield events (unusual but possible in batch operations), use the commitment match from Step 5 to identify the correct event."
      },
      {
        "title": "Note Update (notes.json Workaround)",
        "body": "The shield tool stores the note with leafIndex=null. The unshield tool requires leafIndex != null. No MCP tool exists for updating the leafIndex directly. This workaround uses Bash to manipulate the backup string and notes.json."
      },
      {
        "title": "Why This Is Necessary",
        "body": "ceaser_shield_eth saves note with leafIndex=null (TX not yet sent at proof time)\nceaser_unshield requires leafIndex != null (needed for Merkle proof)\nceaser_import_note rejects duplicates by commitment (including spent notes)\nOld entry must be PHYSICALLY removed from notes.json before re-import"
      },
      {
        "title": "Step 1: Decode Backup String",
        "body": "echo \"BACKUP_STRING\" | base64 -d\n\nThis yields a JSON object with fields: s (secret), n (nullifier), a (amount), am (amountWei), c (commitment), i (leafIndex -- currently null), ai (assetId), as (assetSym), ad (contractAddress)."
      },
      {
        "title": "Step 2: Update leafIndex in Backup",
        "body": "UPDATED_JSON=$(echo \"BACKUP_STRING\" | base64 -d | jq --argjson idx LEAF_INDEX '.i = $idx')\n\nReplace LEAF_INDEX with the extracted decimal value. This sets the i field from null to the actual leafIndex."
      },
      {
        "title": "Step 3: Re-encode to Base64",
        "body": "UPDATED_BACKUP=$(echo \"$UPDATED_JSON\" | base64 -w 0)"
      },
      {
        "title": "Step 4: Remove Old Note from notes.json",
        "body": "CRITICAL: Only remove the specific entry matching the commitment. Do NOT modify other notes.\n\nCOMMITMENT=\"NOTE_COMMITMENT_VALUE\"\njq --arg c \"$COMMITMENT\" '[.[] | select(.commitment != $c)]' ~/.ceaser-mcp/notes.json > ~/.ceaser-mcp/notes.json.tmp && mv ~/.ceaser-mcp/notes.json.tmp ~/.ceaser-mcp/notes.json && chmod 600 ~/.ceaser-mcp/notes.json\n\nIMPORTANT: Always restore file permissions to 0600 after modification."
      },
      {
        "title": "Step 5: Import Updated Note",
        "body": "Run:\n\nnpx -y ceaser-mcp import \"$UPDATED_BACKUP\""
      },
      {
        "title": "Step 6: Verify Import",
        "body": "Run:\n\nnpx -y ceaser-mcp notes\n\nVerify:\n\nNote exists with the same commitment\nleafIndex is the correct value (NOT null, NOT 0 unless actually the first leaf)\nspent is false"
      },
      {
        "title": "Edge Cases",
        "body": "parseBackup null-leafIndex bug: Number(null) returns 0 in JavaScript. ALWAYS set the leafIndex in the backup string BEFORE importing. Never import with i=null.\nFile permissions: After ANY modification to notes.json, run chmod 600 ~/.ceaser-mcp/notes.json.\nOther notes: The jq filter must preserve all other note entries. Only remove the one matching the specific commitment."
      },
      {
        "title": "Pre-Checks",
        "body": "Before calling unshield, verify:\n\nThe note ID is known (from shield phase or from npx -y ceaser-mcp notes)\nThe note has leafIndex != null\nThe note is spent == false\nThe recipient address is valid"
      },
      {
        "title": "Execute Unshield",
        "body": "Inform the user: \"Generating burn proof and submitting to facilitator. This may take 15-60 seconds depending on tree size and hardware.\"\n\nRun:\n\nnpx -y ceaser-mcp unshield NOTE_ID RECIPIENT_ADDRESS\n\nReplace NOTE_ID and RECIPIENT_ADDRESS with actual values."
      },
      {
        "title": "Expected Success Response",
        "body": "success: true\ntxHash: Facilitator settlement TX hash\nrecipient: Target address\ngrossAmount: Gross amount in wei\nfeeWei: Fee in wei\nnetAmount: Net amount in wei\nnoteId: The used note ID"
      },
      {
        "title": "Expected Error Responses",
        "body": "\"Note does not have a leaf index\": leafIndex update failed. Check notes.json.\n\"Note has already been spent\": Double-spend attempt. Note was already unshielded.\n\"Unshield proof generation failed\": Proof generation error. May retry.\n\nThe unshield is GASLESS -- the facilitator pays all gas costs."
      },
      {
        "title": "Gas Refund Phase",
        "body": "Only execute for Path C, after successful Unshield. Refunds remaining ETH from the hot wallet to the user."
      },
      {
        "title": "Execute Refund",
        "body": "Run:\n\nCEASER_HOT_MNEMONIC=\"MNEMONIC_PHRASE\" node {baseDir}/helpers/wallet-ops.js refund --recipient REFUND_ADDRESS --rpc https://mainnet.base.org\n\nWhere:\n\nMNEMONIC_PHRASE: The 12-word mnemonic (from Wallet Generation Phase)\nREFUND_ADDRESS: The user's refund address (from Step 3 of Wallet Generation Phase, or detected from funding TX)"
      },
      {
        "title": "Process Refund Result",
        "body": "refunded: true: Show amount and TX hash to user. \"Refunded X ETH to your address.\"\nrefunded: false (balance too low for gas + L1 fee): Inform user: \"Remaining balance is too small to cover gas + L1 data fee for a refund transfer. Import the mnemonic into MetaMask to recover manually.\"\nError (network, RPC): Inform user of the error. Show hot wallet address and remaining balance so user is aware.\n\nThe refund is a best-effort operation. Refund failure does NOT affect the main operation (Shield + Unshield already completed successfully)."
      },
      {
        "title": "On Success",
        "body": "Present to the user:\n\nRecipient: The target address\nNet amount: Convert netAmount from wei to ETH (human-readable)\nFee: Convert feeWei from wei to ETH\nShield TX: Clickable link: https://basescan.org/tx/SHIELD_TX_HASH\nSettlement TX: Clickable link: https://basescan.org/tx/UNSHIELD_TX_HASH\nRefund: Amount refunded (if any) with TX link\nConfirmation: \"Private transfer complete. ETH has been sent to the recipient. The temporary wallet mnemonic has been discarded from this session.\""
      },
      {
        "title": "On Shield Success but Unshield Failure",
        "body": "Present:\n\nNote status (unspent, with leafIndex)\nMessage: \"Your ETH is safely in the privacy pool. The unshield can be retried later.\"\nNote ID for future reference\nSuggestion: \"Try again with: /ceaser-send (use existing note)\"\nRefund: Attempt refund of remaining hot wallet ETH."
      },
      {
        "title": "On Complete Flow Abort",
        "body": "Present:\n\nCurrent status summary\nWhether ETH was moved (NO if shield TX was not sent/confirmed)\nIf hot wallet has balance: refund status\nReminder: \"As long as you have the backup string, your shielded ETH can always be recovered.\"\nNext steps based on where the flow stopped\nNote: \"The temporary wallet mnemonic has been discarded. Use your saved mnemonic to recover any remaining hot wallet funds.\""
      },
      {
        "title": "Error Handling Reference",
        "body": "ErrorCauseData Loss?ActionHot wallet generation failsNode.js crypto issueNoneRetryInsufficient fundingUser sent too little ETHETH in hot walletInform user, wait for more ETHFunding timeout (10 min)User did not fundNone (no ETH sent)Retry flowFunding timeout with balanceUser sent partial amountETH in hot walletAuto-refund, retry flowUser cancels fundingUser choiceNone or ETH in hot walletAuto-refund if balance > 0Shield proof fails after fundingFacilitator down, circuit errorETH in hot walletRetry (2x), then auto-refundSign-and-send failsGas, nonce, RPC issueETH in hot walletRetry or auto-refundTX reverts (status=0x0)Insufficient funds, gas, revertETH partially in hot walletAuto-refund remainderTX pending too longNetwork congestionETH spent on TXProvide TX hash, check laterNo Shield event in TXWrong TX hashNoneVerify TX hashCommitment mismatchWrong TX for this noteNoneVerify TX hash matches shield operationnotes.json manipulation failsPermissions, syntaxNote still in backupManual recovery with backup stringUnshield proof failsFacilitator down, indexer desyncNone (note unspent)Retry laterceaser.org unreachableServer downNoneCheck status, retry laterInvalid mnemonic in env varEnv var corrupted or wrong formatNoneRe-run generate, use fresh mnemonicRefund failsGas too high for remainderSmall dust in hot walletInform user\n\nRecovery guarantee: The backup string is ALWAYS the ultimate fallback. As long as the user has it, shielded ETH can be recovered."
      },
      {
        "title": "Session Interruption",
        "body": "If the session aborts during the flow:\n\nPhaseStateLoss RiskRecoveryBefore fundingNo ETH sentNoneRestart flowAfter funding, before Shield TXETH in hot walletRecoverable via mnemonicUser imports mnemonic into MetaMask to access hot walletAfter Shield TX, before UnshieldNote in notes.json, backup with userNoneResume with Path A or B using backupAfter Unshield, before refundMain operation completeSmall dust in hot walletUser can recover dust via mnemonic if desired\n\nRisk minimization: The agent executes the Shield TX as quickly as possible after funding is confirmed. The window between funding and Shield TX is minimized. Additionally, the user has the mnemonic phrase as a safety net. Even if the session breaks after funding, the user can recover funds by importing the mnemonic into any BIP-39 compatible wallet (e.g., MetaMask)."
      },
      {
        "title": "Backup String",
        "body": "The backup string contains private ZK secrets (secret + nullifier)\nAnyone with the backup string can withdraw the shielded ETH\nThe agent MUST show it ONCE and never repeat it\nThe agent MUST NOT store it in session summaries or memory\nInstruct the user to save it offline immediately"
      },
      {
        "title": "Hot Wallet Security",
        "body": "The agent generates a temporary BIP-39 mnemonic that is shown to the user ONCE as a recovery mechanism\nAfter the session ends, the mnemonic is only available if the user saved it. The agent discards it.\nThe mnemonic appears in session logs (same risk level as the backup string)\nThe user should ONLY send the displayed funding amount to the hot wallet\nDo NOT send ETH to the hot wallet address after the operation completes\nThe agent MUST show the mnemonic ONCE to the user with a recovery warning. After that, do NOT repeat the mnemonic.\nThe agent MUST NOT repeat the mnemonic in summaries or follow-up responses\nAfter flow completion: inform user \"The temporary wallet mnemonic has been discarded from this session. Recover funds using your saved mnemonic if needed.\""
      },
      {
        "title": "Privacy Notice",
        "body": "The agent sees the backup string during the flow (contains ZK secrets)\nThe agent generates and shows a temporary mnemonic phrase during the flow\nOpenClaw session logs may contain both the backup string and the mnemonic\nFor maximum privacy: save backup offline and clear chat history after completion\nAuto-signing creates on-chain links between user wallet and hot wallet (see PRIVACY WARNING section above)"
      },
      {
        "title": "Recipient Verification",
        "body": "The recipient address CANNOT be changed after unshield is submitted\nAsk the user to double-check the recipient address before executing unshield"
      },
      {
        "title": "Fee Transparency",
        "body": "0.25% protocol fee applies on EACH shield and unshield operation\nAlways show: gross amount, fee amount, and net amount\nTotal round-trip cost for a complete private send: approximately 0.5%"
      },
      {
        "title": "Concurrent Execution",
        "body": "Each execution generates its own hot wallet -- no conflicts between parallel runs\nHowever, ceaser-mcp stores notes in a shared notes.json file -- parallel writes may conflict\nRecommendation: do not run multiple ceaser-send flows in parallel"
      }
    ],
    "body": "Ceaser Private Send\n\nYou are a skill that executes a complete private ETH transfer on Base L2 (chain ID 8453) using the Ceaser privacy protocol. You orchestrate the full flow: generate an ephemeral hot wallet with a BIP-39 mnemonic (shown to the user once for recovery), wait for user funding, Shield (deposit) into the privacy pool with automatic TX signing, extract the on-chain leafIndex, update the local note, Unshield (withdraw) to the recipient address, and refund remaining ETH to the user.\n\nNetwork: Base L2 (chain ID 8453) Contract: 0x278652aA8383cBa29b68165926d0534e52BcD368 Facilitator: https://ceaser.org Protocol Fee: 0.25% (25 bps) per operation Valid Denominations: 0.001, 0.01, 0.1, 1, 10, 100 ETH Proof System: Noir circuits compiled to UltraHonk proofs (no trusted setup)\n\nThis skill uses the ceaser-mcp npm package for shield, unshield, and note management operations. All ceaser tool calls use CLI subcommands:\n\nnpx -y ceaser-mcp <subcommand> [args]\n\n\nAlternatively, if mcporter is installed with the ceaser MCP server configured (see {baseDir}/mcporter.json), you may use mcporter call ceaser.TOOL_NAME as an equivalent method. CLI is the primary and recommended approach.\n\nExactly ONE manual step is required: the user must send ETH to a generated hot wallet address. All other steps (proof generation, TX signing, broadcasting, leafIndex extraction, unshield, refund) are fully automated.\n\nPRIVACY WARNING\n\nAuto-signing mode creates observable on-chain links that reduce privacy compared to manual signing (the /ceaser skill). Specifically:\n\nFunding link: The user's main wallet (A) sends ETH to the hot wallet (H). This transfer is publicly visible on-chain, linking A to H.\nShield link: The hot wallet (H) calls shieldETH() on the contract. H is now linked to the shield deposit.\nRefund link: After the operation, remaining ETH is refunded from H back to A (or another address). This creates another public link.\nTiming correlation: Funding, shield, unshield, and refund happen in rapid succession (minutes apart), making them easy to correlate.\nWallet fingerprint: The hot wallet performs exactly 2-3 transactions (fund receive, shield, refund) and is never reused -- this pattern is distinctive.\n\nRecommendation: For maximum privacy, use the /ceaser skill (manual signing via MetaMask). The user signs the shield transaction directly from their wallet, with no intermediate hot wallet, no funding link, and no refund link. Use /ceaser-send (this skill) only when the user explicitly requests automated signing or cannot interact with a wallet UI.\n\nPrerequisites\n\nBefore executing this skill, verify:\n\nnode and npx are installed (for ceaser-mcp CLI and wallet-ops helper)\ncurl and jq are installed (for TX receipt parsing and notes.json manipulation)\nnode_modules are installed in the skill directory (test: node {baseDir}/helpers/wallet-ops.js --help)\nUser has a wallet capable of sending ETH on Base Mainnet (for funding the hot wallet)\nWallet has enough ETH for the desired amount + 0.25% protocol fee + ~0.0005 ETH gas reserve\nPre-Flight Checks\n\nExecute ALL of these checks BEFORE starting the flow. Abort if any check fails.\n\nCheck 1: Facilitator Status\n\nRun:\n\ncurl -s \"https://ceaser.org/status\" | jq .\n\n\nVerify:\n\nFacilitator is operational (response received without error)\ncircuitBreaker.tripped is false\nindexer.synced is true\nFacilitator has enough balance for gas (balance > 0.001 ETH)\n\nIf the facilitator is down or circuit breaker is tripped, inform the user and abort.\n\nCheck 2: Denomination Validation\n\nRun:\n\ncurl -s \"https://ceaser.org/api/ceaser/denominations\" | jq .\n\n\nVerify:\n\nThe user's requested amount is in the denominations list\nValid: 0.001, 0.01, 0.1, 1, 10, 100 ETH\n\nIf the amount is not a valid denomination, show the user the valid options and ask them to choose.\n\nCheck 3: Fee Calculation\n\nRun:\n\ncurl -s \"https://ceaser.org/api/ceaser/fees/AMOUNT_WEI\" | jq .\n\n\nReplace AMOUNT_WEI with the amount in wei (e.g., 1000000000000000 for 0.001 ETH).\n\nPresent to the user:\n\nGross amount (what they send)\nProtocol fee (0.25%)\nNet amount (what the recipient receives after unshield fee)\nNote: Fees apply on BOTH shield and unshield. Total round-trip fee is approximately 0.5%.\n\nStore internally: amountWei and feeWei from the response (needed for funding calculation in Wallet Generation Phase).\n\nAsk the user to confirm they want to proceed.\n\nCheck 4: Recipient Address Validation\n\nValidate the recipient address format: must match /^0x[0-9a-fA-F]{40}$/.\n\nIf invalid, inform the user and ask for a correct Ethereum address.\n\nCheck 5: Existing Notes\n\nRun:\n\nnpx -y ceaser-mcp notes\n\n\nCheck for existing unspent notes:\n\nIf unspent notes with valid leafIndex exist: Ask the user whether to use an existing note (skip shield, go directly to unshield) or create a new shield.\nIf unspent notes with leafIndex=null exist: Inform the user: \"A note exists but its leafIndex is missing. The shield transaction may not have confirmed yet. If you have the TX hash, we can extract the leafIndex.\"\nIf no suitable notes exist: Proceed with the full Shield flow.\nCheck 6: Helper Script Availability\n\nRun:\n\nnode {baseDir}/helpers/wallet-ops.js --help\n\n\nVerify: valid JSON output listing available commands (generate, balance, sign-and-send, refund).\n\nIf this check fails: inform the user and abort. Message: \"Helper script not available. Please run npm install in the skill directory.\"\n\nFlow Decision\n\nBased on Pre-Flight Check 5:\n\nPath A -- Use Existing Note: If the user wants to use an existing unspent note with a valid leafIndex, skip directly to the Unshield Phase.\n\nPath B -- Update Existing Note: If a note has leafIndex=null and the user has the TX hash, skip to the TX Confirmation and leafIndex Extraction phase.\n\nPath C -- Full Shield Flow: No suitable note exists. Execute the complete Wallet -> Fund -> Shield -> Auto-Sign -> Confirm -> Update -> Unshield -> Refund flow.\n\nWallet Generation Phase\n\nOnly execute for Path C (Full Shield Flow).\n\nStep 1: Generate Hot Wallet\n\nRun:\n\nnode {baseDir}/helpers/wallet-ops.js generate\n\n\nStore internally (in your working context):\n\nmnemonic -- The 12-word BIP-39 recovery phrase.\naddress -- The hot wallet address to show the user.\nStep 1.5: Show Mnemonic to User\n\nIMPORTANT: Show the mnemonic to the user EXACTLY ONCE with a clear security warning:\n\nRECOVERY MNEMONIC (save this securely):\n\nword1 word2 word3 word4 word5 word6 word7 word8 word9 word10 word11 word12\n\nSAVE THIS MNEMONIC SECURELY. It controls the hot wallet funds. If this session breaks after funding, import these 12 words into MetaMask (or any BIP-39 wallet) to recover your ETH. Do NOT share this mnemonic. Anyone with these words can access the hot wallet.\n\nAfter showing the mnemonic once, do NOT repeat it in summaries, follow-up responses, or any subsequent messages.\n\nStep 2: Calculate Funding Amount\n\nUse the fee data from Pre-Flight Check 3:\n\nShield cost: amountWei + feeWei from ceaser_get_fees response\nGas reserve: 500000000000000 wei (0.0005 ETH -- conservative, covers ~500k gas at 1 gwei on Base L2)\nTotal funding = (amountWei + feeWei) + 500000000000000\n\nConvert total funding to ETH for display. Round UP to a human-friendly value if needed.\n\nStep 3: Ask for Refund Address\n\nBefore showing the funding instructions, ask the user:\n\n\"Where should I send any remaining ETH after the operation? Please provide your wallet address for the refund.\"\n\nStore the refund address internally. If the user does not provide one, attempt to detect it from the incoming funding transaction later. If detection fails, ask again after the shield completes.\n\nNote: If the session breaks after funding, the user can also recover hot wallet funds by importing the mnemonic into MetaMask.\n\nStep 4: Show Funding Instructions\n\nPresent to the user:\n\nHot Wallet Address: HOT_WALLET_ADDRESS\n\nSend exactly: FUNDING_AMOUNT ETH (or slightly more)\n\nNetwork: Base Mainnet (Chain ID 8453)\n\nSend EXACTLY the specified amount or slightly more. Sending less will cause the shield to fail. Any excess ETH will be automatically refunded after completion.\n\nIf you lose the mnemonic, you cannot recover funds from this wallet. The mnemonic will NOT be shown again. In case of session interruption, use the mnemonic to recover funds via MetaMask.\n\nBalance Monitoring Phase\n\nOnly execute for Path C, after showing funding instructions.\n\nPolling Logic\n\nRepeatedly execute:\n\nnode {baseDir}/helpers/wallet-ops.js balance --address HOT_WALLET_ADDRESS\n\nPolling interval: 10 seconds\nCheck: balanceWei >= required funding amount (in wei)\nMaximum polling duration: 10 minutes (60 cycles)\nCancel Handling\n\nThe user can say \"cancel\" or \"abbrechen\" at any time during the funding wait.\n\nCancel BEFORE funding (balance == 0): Clean abort. No loss. Key discarded.\nCancel AFTER partial funding (balance > 0): Execute refund to user's address first, then abort.\n\nTo refund on cancel:\n\nCEASER_HOT_MNEMONIC=\"MNEMONIC_PHRASE\" node {baseDir}/helpers/wallet-ops.js refund --recipient REFUND_ADDRESS --rpc https://mainnet.base.org\n\nTimeout Handling\nAfter 5 minutes without funding: Remind user: \"Still waiting for ETH at HOT_WALLET_ADDRESS...\"\nAfter 10 minutes: Abort with clear message.\nOn abort with balance > 0: Automatic refund to user address.\nOn abort with balance == 0: Clean abort, no loss.\nWarning on timeout: \"If you saved the mnemonic, you can still recover funds via MetaMask. Otherwise, do not send ETH after the timeout.\"\nPartial Funding\n\nIf balance > 0 but less than required:\n\n\"Received: X ETH. Required: Y ETH. Please send an additional Z ETH.\"\n\nContinue polling.\n\nFunding Confirmed\n\nWhen balance >= required amount:\n\n\"Funding received. Proceeding with Shield operation.\"\n\nIf the user provided excess ETH:\n\n\"Received more ETH than required. Excess will be refunded after completion.\"\n\nShield Phase\n\nRun:\n\nnpx -y ceaser-mcp shield USER_AMOUNT\n\n\nReplace USER_AMOUNT with the ETH denomination (e.g., 0.1).\n\nExpected Response Fields\nnote.id -- Internal ID for later reference\nnote.commitment -- bytes32 commitment hash\nnote.leafIndex -- Will be null (expected)\nunsignedTx.to -- Must be 0x278652aA8383cBa29b68165926d0534e52BcD368\nunsignedTx.data -- ABI-encoded calldata\nunsignedTx.value -- Amount + fee in wei\nunsignedTx.chainId -- Must be 8453\nbackup -- Base64-encoded backup string (SECURITY CRITICAL)\ninstructions -- Array of guidance messages\nValidation\n\nVerify after receiving the response:\n\nunsignedTx.value from shield response matches (amountWei + feeWei) from ceaser_get_fees\nunsignedTx.chainId == 8453\nunsignedTx.to == 0x278652aA8383cBa29b68165926d0534e52BcD368\nBackup String Handling\n\nSECURITY CRITICAL:\n\nShow the backup string to the user EXACTLY ONCE with a clear warning:\n\nSAVE THIS BACKUP STRING SECURELY. It contains your private ZK secrets (secret + nullifier). Anyone with this string can withdraw your shielded ETH. Store it offline. Do not share it.\n\nDo NOT repeat the backup string in subsequent messages.\nDo NOT include the backup string in summaries or follow-up responses.\nInternal State\n\nRemember these values for later steps (keep in your working context, do not output again):\n\nnote.id\nnote.commitment\nbackup (needed for leafIndex update)\npendingTxFile (path to the saved unsigned TX -- auto-detected by sign-and-send, no need to pass manually)\nShield Error After Funding (Edge Case)\n\nIf ceaser_shield_eth fails (proof error, facilitator down, etc.):\n\nETH is still in the hot wallet (untouched)\nRetry up to 2 times\nIf failure persists: automatic refund to user address\nInform user: \"Shield proof generation failed. Your ETH has been refunded.\"\nAutomatic TX Signing Phase\n\nThis replaces the previous manual signing phase. The agent signs and broadcasts the Shield TX automatically using the mnemonic-derived hot wallet.\n\nExecute Sign-and-Send\n\nThe ceaser-mcp shield command automatically saves the unsigned transaction to ~/.ceaser-mcp/pending-tx.json. The sign-and-send helper auto-detects this file, so you do NOT need to pass the transaction data as a CLI argument.\n\nRun:\n\nCEASER_HOT_MNEMONIC=\"MNEMONIC_PHRASE\" node {baseDir}/helpers/wallet-ops.js sign-and-send --rpc https://mainnet.base.org\n\n\nThe helper automatically reads the unsigned TX from ~/.ceaser-mcp/pending-tx.json and deletes the file after a successful send.\n\nWhere:\n\nMNEMONIC_PHRASE: The 12-word mnemonic from Wallet Generation Phase (passed via environment variable, NEVER as CLI argument)\n\nAlternative: You can also specify the file explicitly or pass the JSON directly:\n\n# Explicit file path\nCEASER_HOT_MNEMONIC=\"...\" node {baseDir}/helpers/wallet-ops.js sign-and-send --unsigned-tx-file ~/.ceaser-mcp/pending-tx.json --rpc https://mainnet.base.org\n\n# Legacy: pass JSON directly (NOT recommended -- the data field is 4000-9000 chars)\nCEASER_HOT_MNEMONIC=\"...\" node {baseDir}/helpers/wallet-ops.js sign-and-send --unsigned-tx 'JSON_STRING' --rpc https://mainnet.base.org\n\n\nIMPORTANT: Do NOT pass the unsignedTx JSON as a CLI argument unless absolutely necessary. The data field contains 4000-9000 characters of hex-encoded ZK proof, which can cause issues with shell argument handling. Always prefer the automatic file-based approach.\n\nSecurity notes:\n\nMnemonic is passed via environment variable (CEASER_HOT_MNEMONIC), NOT as a CLI argument\nBIP-39 mnemonic words contain only ASCII lowercase letters (a-z), no shell special characters\nThe pending-tx.json file is created with 0600 permissions and deleted after successful send\n\nSet exec timeout: 60 seconds (covers gas estimation + signing + broadcasting + 1 block confirmation).\n\nProcess TX Result\nSuccess (status == 1): Extract txHash, proceed to TX Confirmation phase.\n\"insufficient funds\": Inform user. Show required vs. available balance. Suggest sending more ETH.\n\"execution reverted\": Inform user. Possible causes: invalid proof, denomination mismatch, contract pause.\n\"nonce too low\": Handled automatically by the helper script (retry with fresh nonce).\nTimeout / no confirmation: TX may still be pending. Extract txHash if available and proceed to manual confirmation check.\nTX Confirmation and leafIndex Extraction\n\nUsing the txHash from the automatic sign-and-send operation, extract the leafIndex from the on-chain Shield event.\n\nNote: The helper script already waits for 1 block confirmation. In most cases, the receipt is already available. The steps below serve as verification and leafIndex extraction.\n\nStep 1: Fetch TX Receipt\n\nUse Bash to query the Base Mainnet RPC:\n\ncurl -s -X POST https://mainnet.base.org \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"method\":\"eth_getTransactionReceipt\",\"params\":[\"TX_HASH\"],\"id\":1}' | jq '.result'\n\n\nReplace TX_HASH with the actual hash.\n\nStep 2: Check TX Status\nstatus == \"0x1\": Success. Continue to Step 3.\nstatus == \"0x0\": TX failed on-chain. Inform the user: \"Transaction reverted. Possible causes: insufficient funds, gas limit too low, or contract error.\" Attempt refund of remaining hot wallet balance.\nstatus == null or no result: TX still pending. Wait 10 seconds and retry. Maximum 5 retries. If still pending, inform the user and provide the TX hash for manual checking.\nStep 3: Find Shield Event in Logs\n\nSearch the logs array for an entry matching:\n\naddress == 0x278652aa8383cba29b68165926d0534e52bcd368 (case-insensitive)\ntopics[0] == 0x39b0d8da40fd574f8fb61ef14d4f466fb3bceb268547c27680755e9b08fd8677 (Shield event signature)\n\nIf no matching log found: \"No Shield event found in this transaction. This may not be a Shield transaction. Please verify the TX hash.\" Abort.\n\nStep 4: Extract leafIndex\n\nThe Shield event structure:\n\ntopics[0]: Event signature hash\ntopics[1]: commitment (indexed, bytes32)\ntopics[2]: assetId (indexed, uint256)\ndata: ABI-encoded (uint32 leafIndex, uint256 timestamp)\n\nExtract leafIndex from data:\n\n# data is hex string like 0x000000000000000000000000000000000000000000000000000000000000000600000000...\n# First 32 bytes (64 hex chars after 0x) = leafIndex (uint32 zero-padded)\nLEAF_INDEX_HEX=$(echo \"DATA_FIELD\" | cut -c3-66)\nLEAF_INDEX=$(node -e \"console.log(parseInt('0x$LEAF_INDEX_HEX', 16))\")\n\nStep 5: Validate Commitment\n\nExtract topics[1] from the log and compare against the stored note.commitment.\n\nCRITICAL: If the commitment does not match, WARN the user: \"The Shield event commitment does not match the generated note. This TX hash may belong to a different shield operation. Aborting leafIndex extraction to prevent data corruption.\"\n\nStep 6: Validate leafIndex\n\nThe extracted leafIndex must be a non-negative integer. If it is NaN or negative, abort with an error.\n\nEdge Case: Multiple Shield Events\n\nIf the TX contains multiple Shield events (unusual but possible in batch operations), use the commitment match from Step 5 to identify the correct event.\n\nNote Update (notes.json Workaround)\n\nThe shield tool stores the note with leafIndex=null. The unshield tool requires leafIndex != null. No MCP tool exists for updating the leafIndex directly. This workaround uses Bash to manipulate the backup string and notes.json.\n\nWhy This Is Necessary\nceaser_shield_eth saves note with leafIndex=null (TX not yet sent at proof time)\nceaser_unshield requires leafIndex != null (needed for Merkle proof)\nceaser_import_note rejects duplicates by commitment (including spent notes)\nOld entry must be PHYSICALLY removed from notes.json before re-import\nStep 1: Decode Backup String\necho \"BACKUP_STRING\" | base64 -d\n\n\nThis yields a JSON object with fields: s (secret), n (nullifier), a (amount), am (amountWei), c (commitment), i (leafIndex -- currently null), ai (assetId), as (assetSym), ad (contractAddress).\n\nStep 2: Update leafIndex in Backup\nUPDATED_JSON=$(echo \"BACKUP_STRING\" | base64 -d | jq --argjson idx LEAF_INDEX '.i = $idx')\n\n\nReplace LEAF_INDEX with the extracted decimal value. This sets the i field from null to the actual leafIndex.\n\nStep 3: Re-encode to Base64\nUPDATED_BACKUP=$(echo \"$UPDATED_JSON\" | base64 -w 0)\n\nStep 4: Remove Old Note from notes.json\n\nCRITICAL: Only remove the specific entry matching the commitment. Do NOT modify other notes.\n\nCOMMITMENT=\"NOTE_COMMITMENT_VALUE\"\njq --arg c \"$COMMITMENT\" '[.[] | select(.commitment != $c)]' ~/.ceaser-mcp/notes.json > ~/.ceaser-mcp/notes.json.tmp && mv ~/.ceaser-mcp/notes.json.tmp ~/.ceaser-mcp/notes.json && chmod 600 ~/.ceaser-mcp/notes.json\n\n\nIMPORTANT: Always restore file permissions to 0600 after modification.\n\nStep 5: Import Updated Note\n\nRun:\n\nnpx -y ceaser-mcp import \"$UPDATED_BACKUP\"\n\nStep 6: Verify Import\n\nRun:\n\nnpx -y ceaser-mcp notes\n\n\nVerify:\n\nNote exists with the same commitment\nleafIndex is the correct value (NOT null, NOT 0 unless actually the first leaf)\nspent is false\nEdge Cases\nparseBackup null-leafIndex bug: Number(null) returns 0 in JavaScript. ALWAYS set the leafIndex in the backup string BEFORE importing. Never import with i=null.\nFile permissions: After ANY modification to notes.json, run chmod 600 ~/.ceaser-mcp/notes.json.\nOther notes: The jq filter must preserve all other note entries. Only remove the one matching the specific commitment.\nUnshield Phase\nPre-Checks\n\nBefore calling unshield, verify:\n\nThe note ID is known (from shield phase or from npx -y ceaser-mcp notes)\nThe note has leafIndex != null\nThe note is spent == false\nThe recipient address is valid\nExecute Unshield\n\nInform the user: \"Generating burn proof and submitting to facilitator. This may take 15-60 seconds depending on tree size and hardware.\"\n\nRun:\n\nnpx -y ceaser-mcp unshield NOTE_ID RECIPIENT_ADDRESS\n\n\nReplace NOTE_ID and RECIPIENT_ADDRESS with actual values.\n\nExpected Success Response\nsuccess: true\ntxHash: Facilitator settlement TX hash\nrecipient: Target address\ngrossAmount: Gross amount in wei\nfeeWei: Fee in wei\nnetAmount: Net amount in wei\nnoteId: The used note ID\nExpected Error Responses\n\"Note does not have a leaf index\": leafIndex update failed. Check notes.json.\n\"Note has already been spent\": Double-spend attempt. Note was already unshielded.\n\"Unshield proof generation failed\": Proof generation error. May retry.\n\nThe unshield is GASLESS -- the facilitator pays all gas costs.\n\nGas Refund Phase\n\nOnly execute for Path C, after successful Unshield. Refunds remaining ETH from the hot wallet to the user.\n\nExecute Refund\n\nRun:\n\nCEASER_HOT_MNEMONIC=\"MNEMONIC_PHRASE\" node {baseDir}/helpers/wallet-ops.js refund --recipient REFUND_ADDRESS --rpc https://mainnet.base.org\n\n\nWhere:\n\nMNEMONIC_PHRASE: The 12-word mnemonic (from Wallet Generation Phase)\nREFUND_ADDRESS: The user's refund address (from Step 3 of Wallet Generation Phase, or detected from funding TX)\nProcess Refund Result\nrefunded: true: Show amount and TX hash to user. \"Refunded X ETH to your address.\"\nrefunded: false (balance too low for gas + L1 fee): Inform user: \"Remaining balance is too small to cover gas + L1 data fee for a refund transfer. Import the mnemonic into MetaMask to recover manually.\"\nError (network, RPC): Inform user of the error. Show hot wallet address and remaining balance so user is aware.\n\nThe refund is a best-effort operation. Refund failure does NOT affect the main operation (Shield + Unshield already completed successfully).\n\nResult Presentation\nOn Success\n\nPresent to the user:\n\nRecipient: The target address\nNet amount: Convert netAmount from wei to ETH (human-readable)\nFee: Convert feeWei from wei to ETH\nShield TX: Clickable link: https://basescan.org/tx/SHIELD_TX_HASH\nSettlement TX: Clickable link: https://basescan.org/tx/UNSHIELD_TX_HASH\nRefund: Amount refunded (if any) with TX link\nConfirmation: \"Private transfer complete. ETH has been sent to the recipient. The temporary wallet mnemonic has been discarded from this session.\"\nOn Shield Success but Unshield Failure\n\nPresent:\n\nNote status (unspent, with leafIndex)\nMessage: \"Your ETH is safely in the privacy pool. The unshield can be retried later.\"\nNote ID for future reference\nSuggestion: \"Try again with: /ceaser-send (use existing note)\"\nRefund: Attempt refund of remaining hot wallet ETH.\nOn Complete Flow Abort\n\nPresent:\n\nCurrent status summary\nWhether ETH was moved (NO if shield TX was not sent/confirmed)\nIf hot wallet has balance: refund status\nReminder: \"As long as you have the backup string, your shielded ETH can always be recovered.\"\nNext steps based on where the flow stopped\nNote: \"The temporary wallet mnemonic has been discarded. Use your saved mnemonic to recover any remaining hot wallet funds.\"\nError Handling Reference\nError\tCause\tData Loss?\tAction\nHot wallet generation fails\tNode.js crypto issue\tNone\tRetry\nInsufficient funding\tUser sent too little ETH\tETH in hot wallet\tInform user, wait for more ETH\nFunding timeout (10 min)\tUser did not fund\tNone (no ETH sent)\tRetry flow\nFunding timeout with balance\tUser sent partial amount\tETH in hot wallet\tAuto-refund, retry flow\nUser cancels funding\tUser choice\tNone or ETH in hot wallet\tAuto-refund if balance > 0\nShield proof fails after funding\tFacilitator down, circuit error\tETH in hot wallet\tRetry (2x), then auto-refund\nSign-and-send fails\tGas, nonce, RPC issue\tETH in hot wallet\tRetry or auto-refund\nTX reverts (status=0x0)\tInsufficient funds, gas, revert\tETH partially in hot wallet\tAuto-refund remainder\nTX pending too long\tNetwork congestion\tETH spent on TX\tProvide TX hash, check later\nNo Shield event in TX\tWrong TX hash\tNone\tVerify TX hash\nCommitment mismatch\tWrong TX for this note\tNone\tVerify TX hash matches shield operation\nnotes.json manipulation fails\tPermissions, syntax\tNote still in backup\tManual recovery with backup string\nUnshield proof fails\tFacilitator down, indexer desync\tNone (note unspent)\tRetry later\nceaser.org unreachable\tServer down\tNone\tCheck status, retry later\nInvalid mnemonic in env var\tEnv var corrupted or wrong format\tNone\tRe-run generate, use fresh mnemonic\nRefund fails\tGas too high for remainder\tSmall dust in hot wallet\tInform user\n\nRecovery guarantee: The backup string is ALWAYS the ultimate fallback. As long as the user has it, shielded ETH can be recovered.\n\nSession Interruption\n\nIf the session aborts during the flow:\n\nPhase\tState\tLoss Risk\tRecovery\nBefore funding\tNo ETH sent\tNone\tRestart flow\nAfter funding, before Shield TX\tETH in hot wallet\tRecoverable via mnemonic\tUser imports mnemonic into MetaMask to access hot wallet\nAfter Shield TX, before Unshield\tNote in notes.json, backup with user\tNone\tResume with Path A or B using backup\nAfter Unshield, before refund\tMain operation complete\tSmall dust in hot wallet\tUser can recover dust via mnemonic if desired\n\nRisk minimization: The agent executes the Shield TX as quickly as possible after funding is confirmed. The window between funding and Shield TX is minimized. Additionally, the user has the mnemonic phrase as a safety net. Even if the session breaks after funding, the user can recover funds by importing the mnemonic into any BIP-39 compatible wallet (e.g., MetaMask).\n\nSecurity Warnings\nBackup String\nThe backup string contains private ZK secrets (secret + nullifier)\nAnyone with the backup string can withdraw the shielded ETH\nThe agent MUST show it ONCE and never repeat it\nThe agent MUST NOT store it in session summaries or memory\nInstruct the user to save it offline immediately\nHot Wallet Security\nThe agent generates a temporary BIP-39 mnemonic that is shown to the user ONCE as a recovery mechanism\nAfter the session ends, the mnemonic is only available if the user saved it. The agent discards it.\nThe mnemonic appears in session logs (same risk level as the backup string)\nThe user should ONLY send the displayed funding amount to the hot wallet\nDo NOT send ETH to the hot wallet address after the operation completes\nThe agent MUST show the mnemonic ONCE to the user with a recovery warning. After that, do NOT repeat the mnemonic.\nThe agent MUST NOT repeat the mnemonic in summaries or follow-up responses\nAfter flow completion: inform user \"The temporary wallet mnemonic has been discarded from this session. Recover funds using your saved mnemonic if needed.\"\nPrivacy Notice\nThe agent sees the backup string during the flow (contains ZK secrets)\nThe agent generates and shows a temporary mnemonic phrase during the flow\nOpenClaw session logs may contain both the backup string and the mnemonic\nFor maximum privacy: save backup offline and clear chat history after completion\nAuto-signing creates on-chain links between user wallet and hot wallet (see PRIVACY WARNING section above)\nRecipient Verification\nThe recipient address CANNOT be changed after unshield is submitted\nAsk the user to double-check the recipient address before executing unshield\nFee Transparency\n0.25% protocol fee applies on EACH shield and unshield operation\nAlways show: gross amount, fee amount, and net amount\nTotal round-trip cost for a complete private send: approximately 0.5%\nConcurrent Execution\nEach execution generates its own hot wallet -- no conflicts between parallel runs\nHowever, ceaser-mcp stores notes in a shared notes.json file -- parallel writes may conflict\nRecommendation: do not run multiple ceaser-send flows in parallel"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/Zyra-V21/ceaser-send",
    "publisherUrl": "https://clawhub.ai/Zyra-V21/ceaser-send",
    "owner": "Zyra-V21",
    "version": "1.3.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/ceaser-send",
    "downloadUrl": "https://openagent3.xyz/downloads/ceaser-send",
    "agentUrl": "https://openagent3.xyz/skills/ceaser-send/agent",
    "manifestUrl": "https://openagent3.xyz/skills/ceaser-send/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/ceaser-send/agent.md"
  }
}