以太坊智能合约ABI(Ethereum Contract ABI)

基本设计

我们假定应用程序二进制接口(ABI)是强类型的,在编译时和静态时都知道。将不提供内省机制。我们断言,所有的合同都有其在编译时调用的任何合同的接口定义。

本规范不涉及其界面是动态的或仅在运行时已知的契约。如果这些情况成为重要的他们可以适当的处理,在以太坊生态建造的设施。

合约的接口不是附在ABI 上,函数调用可以引用任意数量的参数,这些参数要填补成32字节,并被拼接。一个例外的情况是第一个参数被确切的编码成4字节,这种情况下,不用填补,直接使用函数符号。

功能选择

合约交互中函数调用的调用数据的前四字节指定要调用的函数。0x后的前四个字节,这个是Keccak(SHA-3)函数的签名散列。签名定义为基本原型的规范表达,即函数名和参数类型列表中的圆括号。参数类型用一个逗号分隔——不使用空格。那么函数调用数据就是0x+函数名称(函数类型N,函数类型N1,..)的Keccak(SHA-3)值的前4个字节

例子:

function issue(address account, uint amount) {
	        if (msg.sender != issuer) throw;
	        balances[account] += amount;
	    }
这个函数名为issue,存在两个参数,分别为address和uint类型,那么调用这个函数需要我们传递的数据为0x+issue(address,uint256)的sha3值的前4个字节。


那么截取前4个字节,一个字节=2个16进制字符,所有为867904b4,那么最后调用此函数需要传递参数为0x867904b4。

参数编码

对于调用没有参数的函数,上面就可以了,对于存在参数的函数调用就需要从第5个字节开始添加参数,参数的编码与参数的基本类型关联。

基本类型

  • uint<M>:M为integer类型代表M bits,0 < M <= 256M % 8 == 0,如uint32uint8,uint256。
  • int<M>:同上。同为从8到256位的无符号整数。
  • uint和int:整型,分别是uint256和int256的别名。这也是上面的例子中函数参数类型是uint,转sha3码时要变成uint256的原因。
  • address:地址,20个字节,160bits,一个Ethereum地址,址的类型也可以有成员作为所有合约的base。
  • bool:布尔类型,1个字节,true:1,false:0。
  • bytes<M>:固定大小的字节数组,0<M<=32,byte都是bytes1的别名。
  • bytes:动态分配大小字节数组。不是一个值类型!
  • string:动态大小UTF8编码的字符串,不是一个值类型!
作为一个常识, 使用bytes来表示任意长度原始字节数据,使用string来表示特定长度字符串数据(utf - 8编码)。如果你想限定特定数量的字节长度, 就使用bytes1 到 bytes32,  因为这样占用的存储空间更少。

下面例子说明bytes的参数如何实现传递:

比如一个参数类型为bytes,我们需要对传递参数值进行处理,bytes作为动态大小的数组,长度只能通过传递字符的length来获取,如“Hello, world!”存在13个字节,那么我们需要把这个长度传递过去,就是13的十六进制:0x000000000000000000000000000000000000000000000000000000000000000d,记得补全为32字节。数组长度有了,下一步就该传递参数了,也就是Hello, world!”的十六进制编码:0x48656c6c6f2c20776f726c6421,这里自动补全为32字节,从右边补全:0x48656c6c6f2c20776f726c642100000000000000000000000000000000000000,那么最后传递参数就是
0x函数+000000000000000000000000000000000000000000000000000000000000000d+48656c6c6f2c20776f726c642100000000000000000000000000000000000000+其他参数,其中标红部分代表的就是bytes类型的参数。
对于固定大小的数组来说,原理差不多,第一步:传递的数组参数中元素的个数,如[65,78]有65和75两个参数,那么元素个数为:2,转换为16进制:0x0000000000000000000000000000000000000000000000000000000000000002,接下来开始解析第一个元素65:
0x0000000000000000000000000000000000000000000000000000000000000041,第二个元素75:0x000000000000000000000000000000000000000000000000000000000000004b,那么最终传递的就是:0x函数+0000000000000000000000000000000000000000000000000000000000000002+0000000000000000000000000000000000000000000000000000000000000041+000000000000000000000000000000000000000000000000000000000000004b+其他参数,其中标红部分代表的就是固定大小数组类型的参数。
这是一些最常用的基本数据类型,还存在一些其他的类型需要了解的可以到https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI查看。



猜你喜欢

转载自blog.csdn.net/super_wu1992/article/details/76963769