Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

签名验证进阶:域缓存、执行上下文与许可容错

基础篇讨论重放、延展性和业务参数绑定。进阶分析重点是:域在什么执行上下文计算,以及哪一层签名真正授权了后续资产操作。

1. 分清三种域缓存场景

场景风险或预期行为
同一实例后来处于不同 chain ID构造时固化旧域可能仍接受原域签名
在新链重新部署并执行构造函数使用该链当前 chain ID,不自动继承原链缓存
通过不同 Proxy 委托调用同一 Implementation必须核对验签地址是否分别绑定各 Proxy

若分叉后 chain ID 未分离,只动态读取它也无法区分分叉。另行硬编码错误链 ID、复用不适当的初始化值或遗漏域字段,属于不同错误,应按实际部署取证。

固定 OpenZeppelin 5.2.0 的 EIP712 缓存执行地址和 chain ID,只有两者匹配时复用域,否则重算。代理项目还需正确的可升级版本、初始化和域升级策略,不能直接用普通构造函数代替初始化。源码

本博客 EIP-712 示例 使用该库;测试实际改变 chain ID 并验证旧签名失败,也验证另一个合约地址不接受旧签名。它没有复现完整代理部署或真实链分叉。

2. ERC-1271 验的是钱包当前策略

isValidSignature 成功返回 0x1626ba7e。低级调用成功、非空数据或任意非零数都不能代替魔数检查。钱包策略可变,结算时应查询当前结果。ERC-1271

静态查询禁止该调用树内的状态修改,但不禁止外部读取或递归 view 调用。业务在中间状态对外暴露价格、份额或权限时,仍需分析只读重入。Gas 上限和单项失败策略也会影响复杂钱包兼容性。

EIP-7702 委托 EOA 仍由私钥控制,同时可以提供代码策略;不能把委托后的账户描述为“没有私钥的合约钱包”。本例验签库的分派规则固定在 5.2.0,其他版本或签名扩展应重新核对。

3. permit 授权 Spender,不自动授权某次提款

EIP-2612 签名包含 Owner、Spender、Value、Nonce、Deadline。它不包含 Router 后续提款的收款人,也不直接授权某条 swap 路径或最低输出。

所以仅断言 transferFrom 的 from 与 permit 的 Owner 相等仍不足够:如果 Owner 可任意填写、Router 又把资产转给调用者,攻击者可借助用户历史 allowance 偷取资金。

危险模式可以表示为:

+ 任意调用者提供 from
+ 尝试 permit,错误被忽略或不支持接口的 fallback 返回成功
+ transferFrom(from, msg.sender, amount)
= 调用者可能使用 from 的历史额度

缺失的是对业务提款的授权。反过来,也不能把修复简单写成“所有 permit 失败都必须回滚”:合法许可可能已经被其他人提交,重复提交失败却留下了足够的额度。

4. 两种身份模型,对应两种集成方式

集成方式独立的业务授权
用户自己存款from = msg.sender,资产进入固定业务合约,给同一调用者记账
任意 Relayer 代提交验证业务签名,绑定 Owner、收款人、金额、nonce 及其他执行条件

自助模型可以把 permit 当作可选的额度建立步骤,随后让真实 safeTransferFrom 决定是否能完成业务。无余额或无额度时仍回滚;在旧额度足够时,当前许可错误或过期也可能不影响普通存款,这是必须写明的行为。

Relayer 模型必须验证业务授权。EIP-2612 的 allowance 只说明 Router 有代扣能力,不说明任意外部调用者能决定收款人。可信转发者与元交易模式也需要定义可信上下文,不能机械套用裸 msg.sender。

两个模型都可以在仓库 examples/ethereum-signatures 中运行:PermitDeposit 绑定调用者,SignedTransfer 签入收款人并消费 nonce。

5. 验证与审阅顺序

  1. 从真实入口确定资产提供方、收款方和执行者。
  2. 列出哪些字段进入签名,哪些依赖业务状态。
  3. 检查域的 chain ID、执行地址和版本变化。
  4. 检查 nonce、取消和重入时的状态推进。
  5. 让签名正确而转账失败,确认整个调用的状态回滚。

本例测试覆盖 permit 抢先提交后的合法存款、无额度的失败、任意 from 的反例,以及签名转账的收款人绑定和 nonce 回滚。permit 集成说明

参考资料