为何直接编码结构体与展开编码结果不同?如何适配EIP712签名
EIP712签名校验:结构体编码结果不一致问题
问题描述
在进行EIP712签名校验时,Solidity合约中两个编码函数输出结果不一致,导致签名校验返回的地址不匹配:
encodeDecode1:直接对DATA结构体进行ABI编码后哈希encodeDecode2:手动展开结构体成员,对bytes类型字段先执行keccak256哈希,再编码哈希
相关代码
Solidity合约代码
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; pragma abicoder v2; contract testabi { struct DATA { address a1; uint256 num; bytes nom; } bytes32 constant public DATA_TYPEHASH = keccak256("DATA(address a1,uint256 num,bytes nom)"); DATA data1 = DATA(0x782DDbeBcCA0aC1952e6f8CD525f707B4e2B3077, 100, "0x0000000000000000000000000000000000000000000000000000000000011170000000000000000000000000420000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"); function encodeDecode1() public view returns(bytes32 ) { return keccak256(abi.encode( DATA_TYPEHASH, data1 )); } function encodeDecode2() public view returns(bytes32 ) { return keccak256(abi.encode( DATA_TYPEHASH, data1.a1, data1.num, keccak256(data1.nom) )); } }
生成签名的JS代码
const signature = await wallet._signTypedData( domain, { DATA: [ { name: 'a1', type: 'address' }, { name: 'num', type: 'uint256' }, { name: 'nom', type: 'bytes' } ] }, data ) return signature
原因分析
两者结果不同的核心原因是EIP712对动态类型的哈希规则与直接ABI编码的行为不一致:
- EIP712规范要求,计算结构体哈希时,对于
bytes这类动态类型字段,必须先对字段内容执行keccak256哈希,再将哈希值作为该字段的输入参与整体编码。 abi.encode(data1)是直接对整个结构体做标准ABI编码,其中bytes类型会被编码成「长度前缀 + 原始字节内容」的格式,而不是哈希后的32字节值,这就导致最终的整体哈希结果和EIP712要求的计算方式完全不同。- 你的JS签名代码是按照EIP712规范实现的(对
bytes字段自动处理哈希),所以只有encodeDecode2的计算逻辑和签名生成逻辑一致,encodeDecode1不符合EIP712规范,自然结果不匹配。
解决方法
要让两个函数输出相等,必须让encodeDecode1遵循EIP712的哈希规则,也就是不能直接编码整个结构体,而是要手动展开字段并对动态类型做哈希处理。正确的实现应该和encodeDecode2一致,或者修改encodeDecode1如下:
function encodeDecode1() public view returns(bytes32 ) { return keccak256(abi.encode( DATA_TYPEHASH, data1.a1, data1.num, keccak256(data1.nom) )); }
补充说明:EIP712的结构体哈希计算,本质就是对TYPEHASH和每个字段的「EIP712编码值」进行ABI编码后再哈希。对于值类型(如address、uint256),直接用其本身的32字节编码;对于动态类型(如bytes、string),必须先哈希再用哈希值参与编码。
内容的提问来源于stack exchange,提问作者MOHIT BHAT
相关产品推荐
相关产品推荐

