深入以太坊智能合约 ABI
开发 DApp 时要调用在区块链上的以太坊智能合约,就需要智能合约的 ABI。本文希望更多了解 ABI,如为什么需要 ABI?如何解读 Ethereum 的智能合约 ABI?以及如何取得合约的 ABI?

ABI(Application Binary Interface)
如果理解 API 就很容易了解 ABI。简单来说,API 是程序与程序间互动的接口。这个接口包含程序提供外界存取所需的 functions、variables 等。ABI 也是程序间互动的接口,但程序是被编译后的 binary code。所以同样的接口,但传递的是 binary 格式的信息。所以 ABI 就要描述如何 decode/encode 程序间传递的 binary 信息。下图以 Linux 为例,描述 Linux 中 API、ABI 和程序的关系。

编译和部署智能合约
在 Ethereum 智能合约可以被大家使用前,必须先被部署到区块链上。
从智能合约的代码到使用智能合约,大概包含几个步骤:
- 编写智能合约的代码(一般是用 Solidity 写)
- 编译智能合约的代码变成可在 EVM 上执行的 bytecode(binary code)。同时可以通过编译取得智能合约的 ABI
- 部署智能合约,实际上是把 bytecode 存储在链上(通过一个transaction),并取得一个专属于这个合约的地址
- 如果要写个程序调用这个智能合约,就要把信息发送到这个合约的地址(一样的也是通过一个 transaction)。Ethereum 节点会根据输入的信息,选择要执行合约中的哪一个 function 和要输入的参数
而要如何知道這这个智能合约提供哪些 function 以及应该要传入什么样的参数呢?这些信息就是记录在智能合约的 ABI!
Ethereum 智能合约 ABI
Ethereum 智能合约 ABI 用一个 array 表示,其中会包含数个用 JSON 格式表示的 Function 或 Event。根据最新的 Solidity 文件:
Function
共有 7 个参数:
name:a string,function 名称type:a string,"function", "constructor", or "fallback"inputs:an array,function 输入的参数,包含:name:a string,参数名type:a string,参数的 data type(e.g. uint256)components:an array,如果输入的参数是 tuple(struct) type 才会有这个参数。描述 struct 中包含的参数类型
outputs:an array,function 的返回值,和inputs使用相同表示方式。如果沒有返回值可忽略,值为[]payable:true,function 是否可收 Ether,预设为falseconstant:true,function 是否会改写区块链状态,反之为falsestateMutability:a string,其值可能为以下其中之一:"pure"(不会读写区块链状态)、"view"(只读不写区块链状态)、"payable" and "nonpayable"(会改区块链状态,且如可收 Ether 为 "payable",反之为 "nonpayable")
仔细看会发现 payable 和 constant 这两个参数所描述的內容,似乎已包含在 stateMutability 中。
事实也确实是这样的,在 Solidity v0.4.16 中把 constant 这个修饰function 的 key words 分成: view(neither reads from nor writes to the state)和 pure(does not modify the state),并从 v0.4.17 开始 Type Checker 会强制检查。constant 改为只用来修饰不能被修改的 variable。并在 ABI 中加入 stateMutability 这个参数统一表示,payable 和 constant 目前保留是为了向后兼容。这个改动详细的內容和讨论可参考:https://github.com/ethereum/solidity/issues/992
Event
共有 4 个参数:
name: a string,event 的名称type: a string,always "event"inputs: an array,输入参数,包含:name: a string,参数名称type: a string,参数的 data type(e.g. uint256)components: an array,如果输入参数是 tuple(struct) type 才会有这个参数。描述 struct 中包含的信息类型indexed:true,如果这个参数被定义为 indexed ,反之为false
anonymous:true,如果 event 被定义为 anonymous
更新智能合约状态需要发送 transaction,transaction 需要等待验证,所以更新合约状态是非同步的,无法马上取得返回值。使用 Event 可以在状态更新成功后,将相关信息记录到 Log,并让监听这个 Event 的 DApp 或任何应用这个接口的程序收到通知。每笔 transaction 都有对应的 Log。
所以简单来说,Event 可用來:1. 取得 function 更新合约状态的返回值 2. 也可作为合约另外的存储空间。
Event 的参数分为:有 indexed,和其他没有 indexed 的。有 indexed 的参数可以使用 filter,例如同一个 Event,我可以选择只监听从特定 address 发出来的交易。每笔 Log 的信息同样分为两个部分:Topics(长度最多为 4 的 array) 和 Data。有 indexed 的参数会存储存在 Log 的 Topics,其他的存在 Data。如果定义为 anonymous,就不会产生以下示例中的 Topics[0],其值为 Event signature 的 hash,作为這個 Event 的 ID。

Event
event Set(address indexed _from, uint value)
用一个简单的智能合约举个例子
这个智能合约包含:
data:一个可修改的 state variable,会自动产生一个只能读取的data()functionset():一个修改data值的 functionSet():一个在每次修写data时记录 Log 的 event
智能合约 Source Code:
pragma solidity ^0.4.;
contract SimpleStorage {
uint public data;
event Set(address indexed _from, uint value);
function set(uint x) public {
data = x;
Set(msg.sender, x);
}
}
智能合约 ABI:
[{
"constant": true,
"inputs": [],
"name": "data",
"outputs": [{"name": "","type": "uint256"}],
"payable": false,
"stateMutabㄒility": "view",
"type": "function"
},
{
"anonymous": false,
"inputs": [{"indexed": true,"name": "_from","type": "address"},{"indexed": false,"name": "value","type": "uint256"}],
"name": "Set",
"type": "event"
},
{
"constant": false,
"inputs": [{"name": "x","type": "uint256"}],
"name": "set",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
}]
取得 Ethereum 智能合约 ABI
Solidity Compiler
可以用 Solidity Compiler 取得合约 ABI,我使用 JavaScript 版本的 Compiler 为例。
安装:
npm install solc -g
取得合约 ABI:
solcjs simpleStorage.sol --abi
会生成一个 simpleStorage_sol_SimpleStorage.abi 文件,里面就是合约ABI 內容。
也可以取得合约的 binary code:
solcjs your_contract.sol --bin
Remix
同样的使用 Solidity Compiler,也可以用 Remix。在合约的 Details 可以看到完整的 ABI。可以在 Settings 中指定 Compiler 版本。

Remix
Etherscan
许多知名合约会把合约 source code 放上 Etherscan 做验证,可以同时看到h 合约ABI。

另外 Etherscan 提供 API,可用来取得经过验证的合约 ABI。
分享一个区块链教程:以太坊DApp开发实战
深入以太坊智能合约 ABI的更多相关文章
- Go语言打造以太坊智能合约测试框架(level3)
传送门: 柏链项目学院 第三课 智能合约自动化测试 之前课程回顾 我们之前介绍了go语言调用exec处理命令行,介绍了toml配置文件的处理,以及awk处理文本文件获得ABI信息.我们的代码算是完成了 ...
- Go语言打造以太坊智能合约测试框架(level1)
传送门: 柏链项目学院 Go语言打造以太坊智能合约测试框架 前言 这是什么? 这是一个基于go语言编写的,自动化测试以太坊智能合约的开发框架,使用此框架,可以自动化的部署合约,自动测试合约内的功能函数 ...
- 以太坊智能合约 Solidity 的常用数据类型介绍
目录 目录 1.数组 1.1.对数组的增删改查操作. 2.String.Bytes.Mapping的使用 3.Enums 和 Structs 的简单应用 4.Ether 单位和 Time 单位 5.A ...
- 以太坊智能合约Hello World示例程序
简介 以太坊(Ethereum)是一提供个智能合约(smart contract)功能的公共区块链(BlockChain)平台. 本文介绍了一个简单的以太坊智能合约的开发过程. 开发环境 在以太坊上开 ...
- 如何通过以太坊智能合约来进行众筹(ICO)
前面我们有两遍文章写了如何发行代币,今天我们讲一下如何使用代币来公开募资,即编写一个募资合约. 写在前面 本文所讲的代币是使用以太坊智能合约创建,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还 ...
- rpc接口调用以太坊智能合约
rpc接口调用以太坊智能合约 传送门: 柏链项目学院 在以太坊摸爬滚打有些日子了,也遇到了各种各样的问题.这几天主要研究了一下如何通过rpc接口编译.部署和调用合约.也遇到了一些困难和问题,下面将 ...
- 使用web3.js监听以太坊智能合约event
传送门: 柏链项目学院 使用web3.js监听以太坊智能合约event 当我们在前端页面调用合约时发现有些数据不会立即返回,这时还需要再调用更新数据的函数.那么这样的方法使用起来非常不便,监听ev ...
- 以太坊智能合约开发,Web3.js API 中文文档 ethereum web3.js入门说明
以太坊智能合约开发,Web3.js API 中文文档 ethereum web3.js入门说明 为了让你的Ðapp运行上以太坊,一种选择是使用web3.js library提供的web3.对象.底层实 ...
- 以太坊智能合约介绍,Solidity介绍
以太坊智能合约介绍,Solidity介绍 一个简单的智能合约 先从一个非常基础的例子开始,不用担心你现在还一点都不了解,我们将逐步了解到更多的细节. Storage contract SimpleSt ...
随机推荐
- django的FBV和CBV
title: python djano CBV FBV tags: python, djano, CBV, FBV grammar_cjkRuby: true --- python django的fu ...
- 儿童节,我们从零开始——Python入门资源推荐
原创 2017-06-01 玄魂工作室 玄魂工作室 今天是六一儿童节,首先祝所有的小朋友身体健康,能永远生活在一个没有战争,没有压迫的世界里,永远快乐. 上一篇文章,很多人都对Python的各种书籍感 ...
- ASP.NET Web API编程——序列化与内容协商
1 多媒体格式化器 多媒体类型又叫MIME类型,指示了数据的格式.在HTTP协议中多媒体类型描述了消息体的格式.一个多媒体类型包括两个字符串:类型和子类型. 例如: text/html.image/p ...
- Python入门之PyCharm的快捷键与常用设置和扩展(Win系统)
1. PyCharm的快捷键 2 . PyCharm的常用设置和扩展 ---------------------------------------------------------------- ...
- Apache设置用户权限(2个域名。一个能访问全部文件,一个只能访问指定文件)
可以利用apache的虚拟主机的配置设置: 2个域名一个是xxxxx.com ,一个是aaaaa.com xxxxx.com配置只访问jpg文件,aaaaa.com可以访问所有文件 <Virtu ...
- ipv4与ipv6的区别
对于计算机网络有一定了解的园园们来说,对这两个概念应该比较熟悉,我也将我知道的一点点小知识分享给大家吧 1.协议使用的广泛程度不同 目前,ipv4得到了广泛的应用,基本上所以的与上网有关的(看电影,玩 ...
- tkinter的冷却技能
validatecommand=(f,s1,s2,s3) f就是冷却后的验证函数名,s1,s2,s3这些时额外的选项,这些选项会作为参数依次传给f函数. register()冷却作用:register ...
- 参加Java培训到底靠不靠谱?
导读 科技越发展,社会越进步,人们越便利,便衍生出更多的人从事程序员这个高大上的职业,可哈尔滨Java培训学校这么多,到底靠不靠谱,会不会处处是陷阱,爱尚实训帮你擦亮眼 随着时代的发展,越来越多的人对 ...
- 【转】Impala导出查询结果到文件
[转载出处]http://blog.csdn.net/jobschen/article/details/68942574 想用impala-shell 命令行中将查询的结果导出到本地文件,想当然的以为 ...
- C# 获取网页源代码
/// <summary> /// 获取网页源代码 /// </summary> /// <param name="url"></para ...