由于EIP712是EIP191的一种,相当于EIP-712继承了EIP-191,所以就不过多解析EIP-191了。EIP-191简单来说EIP-191是为了定义智能合约中签名数据的格式。EIP191的数据格式为:0x19<1byteversion><versionspecific
由于EIP712是EIP191的一种,相当于EIP-712继承了EIP-191,所以就不过多解析EIP-191了。
简单来说EIP-191是为了定义智能合约中签名数据的格式。
EIP191的数据格式为:
0x19 <1 byte version> <version specific data> <data to sign>.
这其中的<1 byte version>用来确定EIP191的版本。
目前一共有三个版本号:0x00,0x01,0x45。其中0x01即为EIP712。
version 0x00数据格式为:
0x19 <0x00> <intended validator address> <data to sign>
version 0x45数据格式为:
0x19 <0x45 (E)> <thereum Signed Message:\n" + len(message)> <data to sign>
之所以使用0x19作为前缀:
是为了和RLP编码区分。
是为了兼容交易。因为一开始并没有EIP191格式,人们常用的是最初由Geth实现的 personal_sign方案,数据格式为:
"\x19Ethereum Signed Message:\n" + length(message) + message
而人们往往会对message做哈希运算,因此更常见的格式为:
"\x19Ethereum Signed Message:\n32" + Keccak256(message)
为了兼容这类交易,就以0x19为前缀,再把第一个字母“E”作为版本号。
EIP712是EIP191的改良版,用于改良EIP191中存在的问题。
EIP191有几个问题:
EIP712就是为了解决以上两个问题:
EIP-712结构如下
encode(domainSeparator,message)=x19x01/domainSeparator/hashStruct(message)
其中的x19x01与hashStruct(message)就不解释了,我们主要看domainSeparator字段,这才是防止重入的关键。
domainSeparator字段结构如下:
domainSeparator = keccak256(typeHash / encodeData(S))
typeHash为一个结构体的编码再进行keccak256,结构体如下:
struct EIP712Domain{
string name,
string version,
uint256 chainId,
address verifyingContract,
bytes32 salt
}
encodeData是上述结构体中的参数的编码。
需要注意的是,结构体中的字段可以省略,但不可以颠倒顺序。
EIP712通过规范对结构体编码的方式来使签名内容可视化。其主要体现在hashStruct(message)字段中。 hashStruct(message)字段结构如下:
hashStruct(message) = keccak256(typeHash / encodeData(S))
与domainSeparator字段类似,因此就不再赘述了。
可以看到messageHash中,把结构体名称,属性名称都编码进去了,因此钱包等第三方能够知道编码的结构体数据结构。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!