关于 wallets
面向 Ethereum 钱包与 Agent 开发的安全和架构参考,介绍 EIP-7702、Safe 多签及密钥保护实践。适合构建链上操作的开发者和 AI Agent,内容侧重权限、交易确认与凭据安全。
主要功能
- 01说明 EIP-7702 委托执行能力
- 02介绍 Safe 多签配置模式
- 03提供密钥和凭据保护规则
- 04列出 AI Agent 交易安全护栏
- 05展示安全发送交易的检查项
适用场景
- 01规划 Agent 的钱包与权限
- 02为高价值操作设计多签恢复
- 03检查提交前的代码是否含密钥
- 04实现需人工确认的链上交易
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ austintgriffith/ ethskills --skill wallets安装后在 Claude Code 中输入/wallets确认已加载。
详细介绍
以太坊上的钱包
你可能搞错的地方
EIP-7702 已上线。 自 Pectra(2025 年 5 月 7 日)起,常规 EOA 无需迁移钱包即可将执行权限委托给智能合约代码。这支持批量处理、Gas 赞助和类似会话密钥的用户体验。这不是“即将推出”,而是已经上线。
账户抽象状态: ERC-4337 正在发展,但仍处于早期阶段(2026 年 2 月)。主要实现包括:Kernel(ZeroDev)、Biconomy、Alchemy Account Kit、Pimlico。EntryPoint v0.7:0x0000000071727De22E5E9d8BAf0edAc6f37da032。
最安全的存储方式: 硬件钱包本身是单点故障。经过审计的多签智能合约(例如 Safe)更加安全。多签不需要多个人参与;一个用户可以控制多个设备上的不同密钥。在 2-of-4 设置中,三个签名者是用户在不同设备上的钱包(例如硬件钱包、手机热钱包、笔记本电脑钱包)。第四个签名者是值得信赖的联系人,用于恢复。攻击者必须攻破多个设备,而不是一个。
EIP-7702:智能 EOA(自 2025 年 5 月起上线)
EOA 可以授权执行智能合约代码中的委托代码。这并不会自动“一劳永逸”——委托可以持续生效,直到被替换或明确清除。
工作原理:
- 钱包签署一条消息,指定 EOA 可以使用哪个合约代码。
- 一笔特殊的 EIP-7702 交易提交该签名消息。
- 随后,EOA 可以运行该合约逻辑(批量处理、赞助、权限控制),就像运行账户逻辑一样。
- 这并不会自动“一劳永逸”——委托可以持续生效,直到被替换或明确清除。
- 如果交易之后失败,委托更新本身仍可能保留。
支持的功能:
- 将 10 次代币授权合并为一笔交易
- 为 EOA 用户提供 Gas 赞助/元交易
- 具有有限权限的会话密钥
- 自定义授权逻辑
- 消除“授权疲劳”(授权 + 执行 → 一步完成)
状态(2026 年 2 月): 已部署至主网。MetaMask、Rainbow 正在添加支持。对于生产环境中的 Agent 来说仍处于早期阶段——在工具链成熟之前,请使用标准 EOA 或 Safe。
Safe(Gnosis Safe)多签
关键地址(v1.4.1,跨链确定性一致)
| 合约 | 地址 |
|---|---|
| Safe Singleton | 0x41675C099F32341bf84BFc5382aF534df5C7461a |
| Safe Proxy Factory | 0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67 |
| MultiSend | 0x38869bf66a61cF6bDB996A6aE40D5853Fd43B526 |
主网、Arbitrum、Base 及所有主流链上的地址都相同。
面向 AI Agent 的 Safe
模式: 2-of-3 Safe
- 所有者 1:Agent 的钱包(热钱包,自动操作)
- 所有者 2:人类的热钱包(热钱包,手动操作)
- 所有者 3:人类的冷钱包(冷钱包,用于恢复)
- 阈值:2(Agent 可以将交易加入队列,由人类执行;反之亦然)
优势:如果 Agent 密钥遭到泄露,人类可以将其移除。人类始终可以恢复资金。Agent 可以批量处理交易。
🚨 切勿将密钥提交到 Git
这是 AI Agent 资金损失和凭据泄露的头号原因。 机器人会实时抓取 GitHub,并在数秒内利用泄露的密钥——即使是私有仓库中的密钥也不例外,即使立即删除也无济于事。提交到 Git 的密钥将永久泄露。
这种情况在 AI 编码 Agent 中不断发生。 Agent 生成部署脚本,将密钥硬编码进去,运行 git add .,然后在下一个提示词到来前,钱包里的资金就被转走了。或者 Agent 把 Alchemy API 密钥粘贴到 scaffold.config.ts 中,结果该密钥最终出现在公开仓库里。
这适用于所有密钥:
- 钱包私钥——资金会立即被转走
- API 密钥——Alchemy、Infura、Etherscan、WalletConnect
- 嵌入密钥的 RPC URL——
https://base-mainnet.g.alchemy.com/v2/YOUR_KEY - OAuth 令牌、Bearer 令牌、密码
预防措施
# .gitignore (MUST exist in every project)
.env
.env.*
*.key
*.pem
broadcast/
cache/
# Verify before every commit
git diff --cached --name-only | grep -iE '\.env|key|secret|private'
# If this matches ANYTHING, stop and fix it
# Nuclear option: scan entire repo history
git log --all -p | grep -iE 'private.?key|0x[a-fA-F0-9]{64}'
如果你已经提交了密钥
- 假设它已泄露。 不要心存侥幸,以为没人看到。
- 立即将所有资金转移到新钱包。
- 轮换密钥。 生成一个新密钥。旧密钥已永久作废。
- 使用
git filter-repo或 BFG Repo Cleaner 清理 Git 历史记录——但这只是亡羊补牢,并不能防止问题发生。密钥已经泄露。
AI Agent 的安全模式
# Load key from environment (NEVER hardcode)
cast send ... --private-key $DEPLOYER_PRIVATE_KEY
# Or use encrypted keystore
cast send ... --keystore ~/.foundry/keystores/deployer --password-file .password
# Or use hardware wallet
cast send ... --ledger
经验法则: 如果 grep -r "0x[a-fA-F0-9]{64}" . 能在你的源代码中匹配到任何内容,就说明存在问题。grep -r "g.alchemy.com/v2/[A-Za-z0-9]" 和任何嵌入了 API 密钥的 RPC URL 也是如此。
AI Agent 的关键防护措施
密钥安全规则
- 未经明确的人类许可,绝不从任何钱包中提取私钥。
- **绝不将私钥存储在:**聊天记录、纯文本文件、共享环境中的环境变量、Git 仓库、未加密的数据库中。
- 未经人类确认,绝不转移资金。 展示:金额、目的地(带校验和的地址)、Gas 费用及操作内容。等待明确的“是”。
- 除非人类明确选择使用命令行或脚本,否则优先使用钱包原生 UI 进行签名。
- 使用资金有限的专用钱包执行 Agent 操作。绝不使用人类的主钱包。
- 仔细核对地址。 使用
viem.getAddress()或等效方法验证校验和。仅一个字符错误,就可能造成永久损失。 - 先在测试网上进行测试。 或使用本地 Anvil 分叉。
- 设置支出限额。 超过阈值时须获得人类批准。高价值操作使用 Safe 多签。
- 记录所有交易(绝不记录密钥)。 保留审计记录。
- 假设密钥会泄露。 做好设计,确保 Agent 密钥泄露不会导致全部损失。
存储选项(从最差到最佳)
❌ 将纯文本存放在代码或日志中——绝不允许
❌ 在共享环境中使用环境变量——绝不允许
❌ 提交到 Git——绝不允许
⚠️ 本地 .env 文件——仅用于测试
✅ 加密密钥库(受密码保护)
✅ 硬件钱包 / Cloud KMS / TEE
安全交易模式
async function sendSafely(publicClient, walletClient, to, value) {
const checksummedTo = viem.getAddress(to);
const { account } = walletClient;
const gas = await publicClient.estimateGas({ account, to: checksummedTo, value });
const fees = await publicClient.estimateFeesPerGas();
const totalCostUSD = Number(viem.formatEther(value + gas * fees.maxFeePerGas)) * 2000;
if (totalCostUSD > 10) {
// human approval
}
const hash = await walletClient.sendTransaction({
account,
to: checksummedTo,
value,
gas: (gas * 120n) / 100n,
maxFeePerGas: fees.maxFeePerGas,
maxPriorityFeePerGas: fees.maxPriorityFeePerGas,
});
const receipt = await publicClient.waitForTransactionReceipt({ hash });
logTransaction({ hash, to: checksummedTo, value, block: receipt.blockNumber });
return receipt;
}
延伸阅读
- Safe 文档: https://docs.safe.global/
- EIP-7702 规范: https://eips.ethereum.org/EIPS/eip-7702
- ERC-4337 规范: https://eips.ethereum.org/EIPS/eip-4337