关于 recover-eco-funds
recover-eco-funds 是用于排查和追回旧版 Circle CLI Eco 存款资金的安全优先技能。它先收集只读证据,并将 Eco 退款与 backing EOA 归集分开处理。
主要功能
- 01只读存款诊断
- 02验证意图与退款接收方
- 03链上退款预检与模拟
- 04单独处理 backing EOA 归集
- 05审批与证据留存要求
适用场景
- 01确认存款是否采用旧版退款方式
- 02根据链上事件重建 Eco 退款
- 03追回存放在已验证 backing EOA 的资金
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ circlefin/ skills --skill recover-eco-funds安装后在 Claude Code 中输入/recover-eco-funds确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/eoa-to-sca.mdself-refund.mdscripts/_shared.mjseco-self-refund.mjssign-eoa-authorization.mjs详细介绍
恢复旧版 Eco 资金
概述
在不猜测意图数据、退款接收方或交易状态的前提下,恢复旧版 Circle CLI Eco 存款中的资金。此工作流以证据为先,默认仅进行只读检查。
仅限旧版恢复: 此技能中的可执行恢复阶段适用于此类存款:其已发布的意图将
reward.creator固定为经 API 验证的 Circle SCAeoaOwnerAddress。当前 Gateway v2/Circle CLI 存款会将refundRecipient设为 SCA,因此应直接退款至该地址。对于当前存款,请使用下方的只读状态检查,核对 SCA 和 Gateway 余额;如有必要,请通过常规支持渠道升级处理;不要运行旧版的 backing-EOA 归集操作。
不要仅凭存款时间或端点版本将存款归类为旧版。解码 IntentPublished 事件,并将固定的 reward.creator 与 SCA 及其经 API 验证的 eoaOwnerAddress 进行比较:
reward.creator == eoaOwnerAddress:完成所有只读检查后,可能适用旧版恢复。reward.creator == SCA:当前的直接退款至 SCA 行为;请在可执行的旧版阶段开始前停止。- 两者都不是:请停止,因为所选 Circle 钱包不拥有固定的退款接收方。
如果没有 Eco 存款,且 USDC 只是发送到了 Agent Wallet 的 backing EOA(CLI 对该地址报告“Wallet not found”),请跳过阶段 1 和 2,直接前往阶段 3。
如果尚未安装 Circle CLI、Terms 门槛尚未解决,或 Agent 会话无效,请先使用 use-circle-cli 和 use-agent-wallet 技能。不要触发多个登录请求:每个新的请求都会使之前的 OTP 失效。
了解两项恢复操作
旧版 Eco 存款可能需要执行两项独立操作:
- Eco 自行退款: 在奖励截止时间之后,调用金库/退款链上的
Portal.refund(destination, routeHash, reward)。Portal 会验证意图,并指示其确定性金库将资金退还给reward.creator。任何人都可以中继此调用,但接收方由原始意图固定。 - Backing EOA 归集: 如果
reward.creator是 SCA 的 backing EOA,则使用 ERC-3009 授权 USDC 从该 EOA 转入关联的 SCA。SCA 会中继代币调用并支付 Gas;backing EOA 无需原生 Gas。
当前 Gateway v2/Circle CLI Eco 存款会将 SCA 设为退款接收方,不在此技能的可执行范围内:请进行状态和余额核对,不要运行 backing-EOA 归集操作。
安全边界
- 将事件/创建链、金库/退款链、意图目的地值、Gateway 目的地链、SCA、支持它的 EOA、创建链 Portal、退款链 Portal、金库、代币、金额、路由哈希、意图哈希和截止时间视为不同字段。绝不能相互替代。组合式 Eco 流程可以在一条链上发布事件,同时将可退款金库留在另一条链上;不同链上的 Portal 部署地址也不一定相同。
- 根据 Circle 钱包 API 的
eoaOwnerAddress推导支持它的 EOA;除非先与该字段比较,否则不要接受用户提供的所有者地址。 - 在广播旧版自退款交易之前,要求
reward.creator等于所选 Circle 钱包经 API 验证的eoaOwnerAddress。如果它等于 SCA,则将其判定为当前直接转入 SCA 的流程,并在执行恢复操作前停止。虽然refund(...)无需许可,但绝不要花费用户的 Gas 为无关钱包退款。 - 根据源链上的
IntentPublished事件重建退款元组。Eco 状态 API 可用于了解背景,但不足以作为构造 calldata 的权威依据。 - 验证重建的意图哈希与事件中索引的意图哈希一致。
- 在链上截止时间之前,或当奖励状态已是
Withdrawn或Refunded时,拒绝退款。 - 广播之前,使用确切的 SCA 模拟确切的 calldata。
- 在每次资金转移操作之前,立即征求明确批准。展示链、代币、原始金额和十进制金额、来源、目的地、合约、意图/nonce,以及预估 Gas。
- 每个计划广播使用一个持久化的幂等键。响应不明确时,先核对链上状态,再尝试任何新操作。
- 绝不要记录用户令牌、会话密钥、OTP、私钥或原始 EIP-712 签名。应记录签名哈希。
- 如果
CIRCLE_PROXY_URL覆盖了 Circle 的默认设置,请检查确切的源,并在通过该源发送 Agent 会话令牌之前取得用户的明确授权。存在覆盖时,Phase 2 助手要求使用--allow-proxy-origin <scheme://host>。Phase 3 脚本只与 Circle 生产环境通信,并会在设置覆盖时拒绝运行。 - 绝不要将
refundTo(...)用作捷径。它可以更改收款方,并且在当前 Eco 合约中受创建者限制。无需许可的refund(...)路径已足够。
创建证据目录
诊断前创建专用目录,例如:
mkdir -p ./eco-recovery-evidence
记录命令执行时间、CLI 版本、Circle 链代码、RPC URL 主机、公有地址、意图和交易哈希、已清理的 stdout/stderr、退出代码、操作前后的余额、模拟结果、幂等键,以及最终区块浏览器链接。请将该目录设为私有,因为公有地址和账户关系仍可能属于敏感信息。
不要将原始签名或身份验证材料放入此目录。
阶段 1:诊断但不更改状态
依赖记忆中的标志之前,先运行当前帮助命令:
circle --version
circle wallet status --output json
circle gateway deposit --help
circle wallet execute --help
circle contract query --help
识别 SCA,并检查创建链、候选金库/退款链以及 Gateway 目的地:
circle wallet list --chain <SOURCE_CHAIN> --type agent --output json
circle wallet balance --address <SCA> --chain <SOURCE_CHAIN> --output json
circle gateway balance --address <SCA> --chain <GATEWAY_DESTINATION_CHAIN> --output json
至少收集一个意图标识符:
- Eco 意图哈希,或
- 发布该意图的创建链交易哈希,或
- Eco 存款地址,以及到达该地址的资金转账交易。
检查 Circle SCA 的当前 Eco 意向状态
Eco 未提供按 SCA 列出意向的端点。将 SCA 映射到为存款创建的单次使用 Eco 金库,然后查询该金库及其意向:
-
确认源链 SCA:
circle wallet list --chain <SOURCE_CHAIN> --type agent --output json -
从原始
circle gateway deposit --output json结果或已保存的证据中获取<VAULT_ADDRESS>。其vaultAddress、sourceAddress、sourceBlockchain、transferTxHash和deadline字段用于识别该笔存款。如果未保存该输出,请列出 SCA 已确认的转出交易,并找出对应的 USDC 资金转入交易;其destinationAddress即为 Eco 金库:circle transaction list \ --address <SCA> \ --chain <SOURCE_CHAIN> \ --operation transfer \ --tx-type outbound \ --state confirmed \ --output json根据预期金额、时间、USDC 代币和交易哈希进行匹配。存在多笔存款时,不要仅凭地址选择金库。
-
查询当前的 Gateway 存款金库记录。使用为该金库提供资金的链的 EVM 链 ID(Base 主网使用
8453,Base Sepolia 使用84532;通过circle gateway deposit --help确认 CLI 当前支持的选项):curl -fsS \ "https://api.eco.com/circle-gateway/v2/depositAddresses/<VAULT_ADDRESS>?sourceChainId=<SOURCE_CHAIN_EVM_ID>"记录
state、vaultAddress、amount、deadline、sourceChainId和intentHash。PENDING和FUNDING_DETECTED等状态表示仍在处理中;PUBLISHED表示已发布意向,而FAILED、REFUNDED_BY_USER和RECOVERY_PUBLISHED需要先进行核对,再执行其他操作。 -
当金库记录包含
intentHash时,查询意向生命周期:curl -fsS \ --request POST \ --url https://quotes.eco.com/api/v3/intents/intentStatus \ --header "Content-Type: application/json" \ --data '{"intentHash":"<INTENT_HASH>"}'如果只有创建交易哈希可用,请使用另一种受支持的标识符:
curl -fsS \ --request POST \ --url https://quotes.eco.com/api/v3/intents/intentStatus \ --header "Content-Type: application/json" \ --data '{"intentCreatedHash":"<CREATION_TRANSACTION_HASH>"}'记录
data.status、data.intentCreated、data.fulfillment和data.refund,包括其中出现的所有交易哈希和区块浏览器 URL。
这些 API 仅作为辅助证据。如果响应显示 WaitingForRefund,请继续进行链上重建;切勿仅依据 API 状态构建退款 calldata 或广播交易。
判定状态:
| 观察到的状态 | 操作 |
|---|---|
| 意向仍未到期 | 等待或升级处理;不要退款 |
| 意向已履行/完成 | 核对 Gateway 或目标端资金;不要退款 |
| 旧版意向、已过期、未履行、金库已注资 | 执行 Eco 自助退款环节 |
| 固定退款接收方是 SCA | 当前流程:核对或升级处理;不要执行旧版恢复 |
奖励状态已是 Refunded | 查找退款接收方余额;不要再次调用退款 |
| USDC 在 SCA 中 | 恢复已完成 |
| USDC 在已验证的 backing EOA 中 | 执行 backing EOA 归集环节 |
| 金库和两个钱包的余额均为零 | 停止并追踪转账事件;不要猜测 |
辅助工具前置条件
Phase 2 辅助工具(eco-self-refund.mjs)需要一个可信的 circle-cli 开发版检出目录,并已安装依赖,因为当前公开命令接口不支持提交原始合约 calldata。它会复用 Circle CLI 现有的安全会话和挑战代码;不会直接读取或打印钥匙串密钥。
Phase 3 辅助工具(sign-eoa-authorization.mjs)仅需要 Node.js 20.18.2+ 和公开版 @circle-fin/cli 1.1.4 或更高版本,并已使用 circle wallet login 登录。无需检出目录。
明确指定这两个路径:
<SKILL_DIR> directory containing this SKILL.md
<CIRCLE_CLI_REPO> trusted circle-cli checkout containing apps/cli and node_modules
如果较新版本的 CLI 在 --help 中提供原生恢复、原始 calldata 或 backing owner 命令,请优先使用这些命令,并保留相同的预检、审批和证据要求。
第 2 阶段:自行发起 Eco 退款
在链上事件证明该存款属于旧版,或以其他方式证明固定接收方由所选钱包所有且需要走此手动流程之前,请勿进入此阶段。如果 reward.creator 是 SCA,请停止并使用当前流程的对账路径。
操作前请阅读 references/self-refund.md。其中定义了确切的事件字段、元组、链上检查和原始 calldata 回退方案。
如果已安装的 CLI 在 --help 中提供原生 Circle CLI 恢复命令,请优先使用。否则,请使用来自可信 circle-cli 检出副本的捆绑辅助工具:
<CIRCLE_CLI_REPO>/node_modules/.bin/tsx \
<SKILL_DIR>/scripts/eco-self-refund.mjs \
--circle-cli-repo <CIRCLE_CLI_REPO> \
--chain <REFUND_CHAIN> \
--event-chain-id <CREATION_CHAIN_EVM_ID> \
--refund-chain-id <REFUND_CHAIN_EVM_ID> \
--event-rpc-url <CREATION_CHAIN_RPC_URL> \
--refund-rpc-url <REFUND_CHAIN_RPC_URL> \
--sca <SCA> \
--event-portal <CREATION_CHAIN_ECO_PORTAL> \
--portal <REFUND_CHAIN_ECO_PORTAL> \
--creation-tx <SOURCE_TX_HASH> \
--intent-hash <INTENT_HASH> \
--evidence-dir <EVIDENCE_DIR> \
--estimate-fee
此调用为只读操作。它会从明确选择的创建链 Portal 解码 IntentPublished,验证意图哈希,然后从单独选择的退款链 Portal 读取奖励状态和金库余额,构造确切的 refund(...) calldata,并从 SCA 执行 eth_call。--estimate-fee 还会加载 Circle 会话,验证固定接收方是否为所选 SCA 或其 API 报告的支持 EOA,并在审批预检中包含费用估算。仅在无需会话进行诊断时才省略此标志;此类输出不足以用于审批。如果所选链没有资金充足的金库,请停止并检查 Eco 组合路线所指示的其他链;不要假定事件链拥有该金库,也不要假定两个 Portal 地址相同。
在显示包含 recipientOwnership.checked: true 和 estimatedFee 的预检,并获得用户明确批准后,使用以下两个参数重新运行:
--submit --confirm-intent <INTENT_HASH>
确认值会将审批绑定到单个意图,而非开放式的退款操作。
当设置了 CIRCLE_PROXY_URL 时,辅助工具会在发送会话令牌前停止。检查报告的来源,询问用户是否信任该确切来源,只有在用户确认后才添加 --allow-proxy-origin <scheme://host>。
确认后,请验证:
- Circle 交易状态为已确认,且包含交易哈希。
- Portal 奖励状态为
Refunded。 - 每个奖励代币金库余额均为零,或已按退款金额减少。
- 固定退款接收方的余额有所增加。
- 收据包含针对预期意图和接收方的
IntentRefunded。
此技能的 allowed-tools 未预先授权可选的标准 circle wallet execute 元组形式估算,因为其动态元组参数无法进行严格限定。仅通过宿主的常规交互式命令审批来运行。如果该估算失败,而直接 RPC 模拟成功,请使用预先授权的辅助工具原始 calldata 路径。不要为了让托管解析器接受参数而更改元组值。
阶段 3:将 backing EOA 的 USDC 转至关联的 SCA
如果退款已到达 SCA,请跳过此阶段。
操作前请阅读 references/eoa-to-sca.md。这是由 backing EOA 授权、由其关联的 SCA 中继的标准 USDC ERC-3009 转账。
确认 backing EOA 的余额,然后展示链、USDC 合约、backing EOA、SCA、原始金额和十进制金额,并在签名前获得用户明确批准:
circle contract query "balanceOf(address)" <BACKING_EOA> --contract <USDC_CONTRACT> --chain <SOURCE_CHAIN>
node <SKILL_DIR>/scripts/sign-eoa-authorization.mjs \
--chain <SOURCE_CHAIN> \
--sca <SCA> \
--eoa <BACKING_EOA> \
--usdc <USDC_CONTRACT> \
--amount-atomic <RAW_USDC_AMOUNT>
此帮助程序:
- 要求
--sca是已登录账户的 Agent Wallet 之一,且其 API 报告的eoaOwnerAddress必须等于--eoa。 - 使用实时 USDC
name()/version()作为 EIP-712 域,构建TransferWithAuthorization,其中from=backing EOA、to=linked SCA、金额为精确的原始金额、nonce 为新生成的 32 字节值,过期时间为一小时后。 - 使用
walletAddress=<backing EOA>和blockchain=<SOURCE_CHAIN>请求对类型化数据进行签名。使用 SCA 钱包 ID 签名是错误的,因为这可能会生成 EIP-1271 防重放的 SCA 封装签名,而非 USDC 所需的原始 EOA 签名。 - 在本地恢复签名者,并要求其与 backing EOA 相同。
- 仅打印、不提交以下内容:
authorizationState检查、circle wallet execute ... --estimate费用估算、带固定幂等键的单条提交命令,以及验证查询。
该脚本只与 Circle 生产环境通信(https://agentic-wallet.circle.com)。如果设置了 CIRCLE_PROXY_URL,脚本会在读取会话前停止。取消设置该变量,重新运行 circle wallet login,然后再次运行;打印出的 circle wallet execute 命令也必须在未设置该变量的情况下运行。
在授权过期前,按顺序运行打印出的命令。展示 --estimate 结果,并在运行提交命令前获得用户对转账和网络费用的明确批准。提交命令包含原始签名;请勿将其存入证据目录,并改为记录签名哈希。
确认后,验证:
- Backing EOA 的 USDC 减少了准确金额。
- SCA 的 USDC 增加了准确金额。
authorizationState(backing EOA, nonce)为 true。- 收据包含预期的 USDC 转账。
提交状态不明或失败
不要仅仅因为客户端超时就创建新的授权或幂等键。
对于 Eco 退款状态不明的情况,请检查奖励状态、金库余额、收款方余额、交易列表和 IntentRefunded 日志。如果其中任何一项能证明交易成功,请记录结果并停止。
对于 ERC-3009 状态不明的情况,请检查 authorizationState、双方的 USDC 余额、交易列表和转账日志。nonce 已被消耗或余额已完成变动,即可证明该授权已被使用。除非已完成对第一笔转账的核查,否则绝不要签署第二笔转账。
如果已签名的授权从未提交,请等待其 validBefore 过期后再创建金额相同的新授权,除非链上状态能证明该 nonce 未被使用,且原始签名无法被非预期方重放。
完成报告
报告:
- 初始诊断和所选分支。
- 创建链、事件链、金库/退款链、意图目标链和 Gateway 目标链的名称及 ID。
- SCA、经验证的 backing EOA、创建链 Portal、退款链 Portal、金库、代币和固定退款收款方。
- 意图哈希、路由哈希、截止时间、奖励状态(前/后)。
- 以原子单位和 USDC 表示的金额。
- 模拟结果和 Gas 估算。
- Circle 交易 ID、链上交易哈希和区块浏览器链接。
- 交易前后余额和 ERC-3009 授权状态。
- 证据目录路径,以及已排除机密信息/签名的说明。
参考链接
- Eco Portal 合约:https://docs.eco.com/routes/architecture/portal
- Eco 金库:https://docs.eco.com/routes/architecture/vault
- Eco 意图状态 API:https://docs.eco.com/api-reference/quotes-v3/get-intent-status
- Eco 合约:https://github.com/eco/eco-routes
- EIP-3009:https://eips.ethereum.org/EIPS/eip-3009
- Circle USDC 合约:https://developers.circle.com/stablecoins/usdc-contract-addresses
- Circle Agent Wallet 设置技能:
use-agent-wallet
免责声明:此技能按“原样”提供,不附带任何保证,并受 Circle Developer Terms 约束。生成的输出可能包含错误。广播交易前,请检查每个地址、金额、截止时间、合约、模拟结果、费用和授权。