以太坊ABI编码

35 阅读3分钟

本文介绍以太坊的abi编码,以太坊有两种常用的编码,abi编码和RLP编码, abi编码主要用于合约调用中,比如对合约方法的参数采用的编码, rlp编码主要用于对tx的数据进行编码

abi编码简介

abi编码的最小单位是32字节,称为slot,即1slot=32字节, 比如你要存一个数据0x1,那也需要用32字节,类似 00000000000000000000000000000000001,前面补0补到32字节

静态类型动态类型

abi里的类型分为静态类型和动态类型,静态类型都是固定长度的,动态类型则不固定长度, 比如uint 256,address都是静态类型,string和list是动态类型

静态类型一般就是拿一个slot存对应的数据, 动态类型则是存的offset,也就是索引,索引指向真正的数据存储的地方

header tail offset

abi编码后的数据存储的地方主要分header和tail,静态类型和索引存在header,动态类型真实的数据存在tail,比如有个数据

abi.encode(
  uint256(1),
  "abc"
)

对应的存储如下

HEAD:
slot0: 1
slot1: 0x40   ← string 的 offset(64 bytes)

TAIL:
slot2: 3      ← 字符串长度
slot3: 6162630000000000000000000000000000000000000000000000000000000000

一般abi.encode有几个参数,那么head的长度就是几,即参数的个数和head里slot的个数是一样的, 静态类型直接将对应的二进制数据放在对应的slot里,没什么好说的, 动态数据的head的slot里放的是对应的索引,即offset,offset是字节数,即这个动态数据的真实数据从offset这个地方开始,比如上面是从slot2开始,因为前面还有slot0和slot1,是64个字节,所以这里的offset为0x40,也就是64

动态数据里的第一个slot用来表示字符串的长度,后面的slot是真实的数据,比如上面的slot2为3,表示字符串是3个字节,然后slot3存的是真实的数据abc的二进制编码,如果长度大于32字节,则后面再按顺序添加slot

列表也是类似的,反正就是各种存offset,然后通过offset拿到真实的字符串或者列表的长度,然后再拿到真实的数据,然后这个是可以嵌套的,即列表套列表也可以,具体怎么实现的不用深究也可以,用库就好了,大致原理就是这么做的