前言
- 最近看了一些奇怪的东西,触及到了知识盲区,就水了一篇博客记录一下
 - 写的也不是很专业,只是按照个人理解,有错误的话欢迎及时交流 👀
 - 参考了 👉 官方文档 👈
 
Function Selector
- 定义就不介绍了,不太清楚的可自行百度,直接来看例子(一看就懂,就不解释了)
- 参数包含结构体,相当于把结构体拆分成单个参数,只不过这些参数用 
()引起来 
 - 参数包含结构体,相当于把结构体拆分成单个参数,只不过这些参数用 
 
1  | pragma solidity >=0.4.16 <0.9.0;  | 
Function Selector and Argument Encoding
动态类型的数据,比如动态数组,结构体,变长字节,其编码后存储其
offset、length、data- 先把参数顺序存储:如果是定长数据类型,直接存储其 
data,如果是变长数据类型,先存储其offset - 顺序遍历变长数据:先存储 
offset,对于第一个变长数据,先存储其offset = 0x20 * number(number是函数参数的个数 );对于下一个变长数据,其offset = offset_of_prev + 0x20 + 0x20 * number(第一个0x20是存储前一个变长数据的长度占用的大小,number是前一个变长数据的元素个数) - 顺序遍历变长数据:存储完 
offset,接着就是遍历每个变长数据,分别存储其length和data - ( 
ps:对于结构体这样的类型,存储的时候可把结构体内元素看成是一个新函数的参数,这样的话,对于结构体中的第一个变长数据,其offset = 0x20 * num,num是结构体元素的个数 ) 
- 先把参数顺序存储:如果是定长数据类型,直接存储其 
 对于上述的合约例子,其函数调用最终编码如下
test1("0x112233")
1  | 0x0d2032f1 // function selector  | 
test2(["0x112233", "0x445566"])
1  | 0x2b231dad // function selector  | 
test3(0x123, 1)
1  | 0x92e92919 // function selector  | 
test4(0x123, ["0x11221122", "0x33443344"], "0x31323334353637383930", "0x3132333435")
1  | 0x4d189ce2 // function selector  | 
test5(0x123, ["cxy", "pika", 123])
1  | 0x4ca373dc // function selector  | 
test6(0x123, [["cxy1", "pika1", 123], ["cxy2", "pika2", 456]])
1  | 由于是结构体数组,所以需要拆分,由内向外。内部是两个结构体,分别来看其encoding  | 
test7([[1, 2], [3]], ["one", "two", "three"])
1  | 同理进行由内向外的拆分,首先是[[1, 2], [3]]动态数组中的[1, 2]和[3]两个动态数组  | 
