首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Ethereum 智能合约开发笔记深入 Ethereum 智能合约 ABI

-以太猫合约 ABI-

开发 DApp 时要呼叫在区块链上的 Ethereum 智能合约,就需要智能合约的 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格式表示的FunctionEvent。根据最新的 Solidity 文件:

Function

共有 7 个栏位:

:a string,function 名称

:a string,"function", "constructor", or "fallback"

:an array,function 输入的参数,包含:

:a string,参数名称

:a string,参数的 data type(e.g. uint256)

:an array,如果输入的参数是 tuple(struct) type 才会有这个栏位。描述 struct 中包含的资料型态

:an array,function 的回传值,和 使用相同表示方式。如果没有回传值可忽略,值为

:,如果 function 可收 Ether,预设为

:,如果 function 不会改写区块链的状态,反之为

:a string,其值可能为以下其中之一:"pure"(不会读和写区块链状态)、"view"(会读区块链状态,但不会改写区块链状态)、"payable" and "nonpayable"(会改写区块链状态,且如可收 Ether 为 "payable",反之为 "nonpayable")

仔细看会发现 和 这两个栏位所描述的内容,似乎已包含在 中。

事实的确是这样,在 Solidity v0.4.16 中把 这个修饰 function 的 key words 分成 (neither reads from nor writes to the state)和 (does not modify the state),并从 v0.4.17 开始 Type Checker 会强制检查。 改为只用来修饰不能被修改的 variable。并在 ABI 中加入 这个栏位统一表示, 和 目前保留是为了向后兼容。这个更新详细的内容和讨论可参考:Introduce a real constant keyword and rename the current behaviour #992。

Event

共有 4 个栏位:

: a string,event 的名称

: a string,always "event"

: an array,输入的参数,包含:

: a string,参数名称

: a string,参数的 data type(e.g. uint256)

: an array,如果输入的参数是 tuple(struct) type 才会有这个栏位。描述 struct 中包含的资料型态

: ,如果这个参数被宣告为 indexed(被存在 log 的 topics 中),反之为 (储存在 log 的 data 中)

: ,如果 event 被宣告为 anonymous

更新智能合约状态需要发送 transaction,transaction 需要等待验证,所以更新合约状态是非同步的,无法马上取得回传值。使用 Event 可以在状态更新成功后,将相关资讯记录到 Log,并让监听这个 Event 的 DApp 或任何使用介面收到通知。每一笔 transaction 都有对应的 Log。

所以简单来说,Event 可用来:1. 取得 function 更新合约状态后的回传值 2. 也可作为合约另外的储存空间。

Event 的参数分为:有 ,和其他没有 的。有 的参数可以使用 filter,例如同一个 Event,我可以选择只监听从特定 address 发出来的交易。每笔 Log 的资料同样分为两部分:Topics(长度最多为 4 的 array) 和Data。有 indexed 的参数会储存在 Log 的 Topics,其他的存在 Data。如果宣告为 ,就不会产生以下范例中的 Topics[0],其值为 Event signature 的 hash,作为这个 Event 的 ID。

-event Set(address indexed _from, uint value)-

要详细了解 Solidity Event 可参考 Solidity的event事件(二十一)|入门系列、Solidity的event的支持指引(二十二)|入门系列。

用一个简单的智能合约举例

这个智能合约包含:

:一个可改写的state variable,会自动产生一个只能读取的 function

:一个改写 值的function

:一个在每次更新 纪录 log 的event

智能合约 Source Code:

智能合约 ABI:

取得 Ethereum 智能合约 ABI

Solidity Compiler

可以用 Solidity Compiler 取得合约 ABI,我使用 JavaScript 版本的 Compiler 为例。

安装:

取得合约 ABI:

会产生一个 simpleStorage_sol_SimpleStorage.abi 档案,里面就是合约 ABI 内容。

也可以取得合约 binary code:

Remix

同样使用 Solidity Compiler,也可以用 Remix。在合约的 Details 可以看到完整的 ABI。可以在 Settings 中指定 Compiler 版本。

-Remix-

Etherscan

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

-Etherscan-

另外有提供 API 可以取得经验证的合约 ABI。

References

Latest Solidity Document

Ethereum contract Application Binary Interface(Video)

What is an application binary interface (ABI)?

What is an ABI and why is it needed to interact with contracts?

Solidity撰寫智能合約與注意事項(二) — 介紹如何使用 Event

相关套件

https://github.com/ethereum/solc-js

https://github.com/ethereumjs/ethereumjs-abi

https://github.com/ConsenSys/abi-decoder

本文首发于作者的简书,作者授权 EthFans 转载。

Ethereum 智能合约开发笔记系列:

下面是一份关于“智能合约开发的现状及挑战”的问卷调查,

我们始终相信,

每一次的热情投入,

都会让这个世界变得更好一点点,

期待你的参与哦 ~

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180302B171U500?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券