EIP-712EIP签名Final(2017-09-12)结构化数据签名
把待签名内容定义成带类型与域的结构体,钱包能把它渲染成人能读懂的字段表。
适用链:全部 EVM 链
为什么重要:一切「可读签名」的基础:Permit、订单签名(挂单)、4337 的 userOp 签名都基于它。
函数签名与选择器
选择器是签名的 keccak256 前 4 字节;事件则是完整的 32 字节 topic0。 点一下即可复制。
| 签名 / 字段 | 选择器 / topic0 | 说明 |
|---|---|---|
| 域(domain) | — | 固定四件套:name、version、chainId、verifyingContract;可选 salt。 |
| types | — | EIP-712 类型定义,字段顺序会影响最终哈希。 |
| 消息哈希 | — | keccak256("\x19\x01" || domainSeparator || hashStruct(message))。 |
| 链上校验 | — | 合约用 ecrecover + 自己重算的 domainSeparator 还原签名者。 |
| 合约签名 | — | 签名者是多签/智能账户时,走 EIP-1271 的 isValidSignature。 |
代码模板
合约侧校验(含 EIP-1271 分支)
合约侧校验(含 EIP-1271 分支)Solidity
签名里的 nonce 必须在链上标记为已使用。漏掉这一步,同一份签名可以被重复提交。
实现与使用时的常见陷阱
- ✕domain 里必须有 chainId 与 verifyingContract,否则签名可以跨链、跨合约重放。
- ✕types 里字段的顺序和类型必须与合约里的 TYPEHASH 字符串完全一致,差一个空格都会算出不同哈希。
- ✕链上要用 abi.encode(补零到 32 字节)而不是 encodePacked,后者会产生哈希碰撞。
- ✕签名超过 65 字节时说明是合约钱包签名,必须接入 EIP-1271 才能验签。
相关标准
同属「签名」的其他标准