深入以太坊智能合约 ABI

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

数字猫合约 ABI

ABI(Application Binary Interface)

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

Linux API and ABI

编译和部署智能合约

在 Ethereum 智能合约可以被大家使用前,必须先被部署到区块链上。

从智能合约的代码到使用智能合约,大概包含几个步骤:

  1. 编写智能合约的代码(一般是用 Solidity 写)
  2. 编译智能合约的代码变成可在 EVM 上执行的 bytecode(binary code)。同时可以通过编译取得智能合约的 ABI
  3. 部署智能合约,实际上是把 bytecode 存储在链上(通过一个transaction),并取得一个专属于这个合约的地址
  4. 如果要写个程序调用这个智能合约,就要把信息发送到这个合约的地址(一样的也是通过一个 transaction)。Ethereum 节点会根据输入的信息,选择要执行合约中的哪一个 function 和要输入的参数

而要如何知道這这个智能合约提供哪些 function 以及应该要传入什么样的参数呢?这些信息就是记录在智能合约的 ABI!

Ethereum 智能合约 ABI

Ethereum 智能合约 ABI 用一个 array 表示,其中会包含数个用 JSON 格式表示的 Function 或 Event。根据最新的 Solidity 文件:

Function

共有 7 个参数:

  1. name:a string,function 名称
  2. type:a string,"function", "constructor", or "fallback"
  3. inputs:an array,function 输入的参数,包含:
    • name:a string,参数名
    • type:a string,参数的 data type(e.g. uint256)
    • components:an array,如果输入的参数是 tuple(struct) type 才会有这个参数。描述 struct 中包含的参数类型
  4. outputs:an array,function 的返回值,和 inputs 使用相同表示方式。如果沒有返回值可忽略,值为 []
  5. payabletrue,function 是否可收 Ether,预设为 false
  6. constanttrue,function 是否会改写区块链状态,反之为 false
  7. stateMutability: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 个参数:

  1. name: a string,event 的名称
  2. type: a string,always "event"
  3. inputs: an array,输入参数,包含:
    • name: a string,参数名称
    • type: a string,参数的 data type(e.g. uint256)
    • components: an array,如果输入参数是 tuple(struct) type 才会有这个参数。描述 struct 中包含的信息类型
    • indexedtrue,如果这个参数被定义为 indexed ,反之为 false
  4. anonymoustrue,如果 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() function
  • set():一个修改 data 值的 function
  • Set():一个在每次修写 data 时记录 Log 的 event

智能合约 Source Code:

pragma solidity ^0.4.20;
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

另外 Etherscan 提供 API,可用来取得经过验证的合约 ABI。

原文地址:https://www.cnblogs.com/helloworld2018/p/8934425.html

时间: 2024-10-07 09:13:52

深入以太坊智能合约 ABI的相关文章

web3j开发以太坊智能合约快速入门(特别适合java和android开发者)

web3j简介 web3j是一个轻量级.高度模块化.响应式.类型安全的Java和Android类库提供丰富API,用于处理以太坊智能合约及与以太坊网络上的客户端(节点)进行集成. 可以通过它进行以太坊区块链的开发,而无需为你的应用平台编写集成代码. 可以快速启动dmeo示例 想要快速启动的话,有一个Web3j demo示例项目可用,演示了通过Web3j开发以太坊的许多核心特征,其中包括: 连接到以太网网络上的节点 加载一个以太坊钱包文件 将以太币从一个地址发送到另一个地址 向网络部署智能合约 从

以太坊智能合约入门项目-众筹项目

一.智能合约 智能合约(英语:Smart Contract)是一种旨在以信息化方式传播.验证或执行合同的计算机协议.智能合约允许在没有第三方的情况下进行可信交易.这些交易可追踪且不可逆转.智能合约概念于1994年由Nick Szabo首次提出. 以上解释来自于维基百科 由于缺少可信的执行环境,智能合约并没有被应用到实际产业中,自比特币诞生后,人们认识到比特币的底层技术区块链天生可以为智能合约提供可信的执行环境,以太坊首先看到了区块链和智能合约的契合,发布了白皮书<以太坊:下一代智能合约和去中心化

2018年以太坊智能合约开发语言Solidity最佳IDEs

Solidity是一种以智能合约为导向的编程语言.这是一种只有四年的年轻语言,旨在帮助开发基于以太坊数字货币的智能合约. 理解它官方文档应该是学习Solidity的最佳来源:solidity.readthedocs.io 想在以太坊的网络上建立自己的加密货币吗?想拥有自己的初始代码产品吗?以下是您今天可以使用的最佳Solidity IDE. Remix IDE Remix IDE是基于浏览器的,并且集成了编译器.没有服务器端组件. 官网: https://remix.ethereum.orggi

rpc接口调用以太坊智能合约

rpc接口调用以太坊智能合约 传送门: 柏链项目学院 ??在以太坊摸爬滚打有些日子了,也遇到了各种各样的问题.这几天主要研究了一下如何通过rpc接口编译.部署和调用合约.也遇到了一些困难和问题,下面将向大家分享. rpc接口调用智能合约 先来编写一个简单的智能合约 contract Multiply7 { event Print(uint); function multiply(uint input) returns (uint) { Print(input * 7); return input

以太坊智能合约部署与交互

启动容器来执行geth命令 [email protected]:~# docker run -i blockchain101/ethereum-geth:1.6.5 geth attach http://45.32.252.88:8201 Welcome to the Geth JavaScript console! instance: Geth/01/v1.6.5-stable/linux-amd64/go1.8 coinbase: 0x4c57e7e9c2f728046ddc6e960520

如何用python和flask以太坊智能合约开发

将数据存储在数据库中是任何软件应用程序不可或缺的一部分.无论如何控制该数据库都有一个该数据的主控.区块链技术将数据存储到区块链网络内的区块中.因此,只要某个节点与网络同步,它们就会获得区块中数据的副本.因此,该技术中没有特定的数据主控. 在本教程中,我们将编写一份智能合约(我将进一步解释),以便在区块链上保留用户数据.我们将使用python web3(web3的python库)来开发和部署智能合约.一旦我们在区块链上部署了智能合约.我们将使用flask API与智能合约进行交互以存储一些数据/信

通过一个案例精通以太坊智能合约和Solidity

作者介绍 Silver CEO 星际区块链信息发展有限公司 项目组件 ??这个项目是一个构建在以太坊上的游戏,感谢这个团队给我们提供的案例:https://cryptozombies.io ??从功能的角度看,有如下脚本: zombiefactory.sol:定义zombie和生成zombie. zombiefeeding.sol:定义小猫接口,给zombie吃小猫. zombieattack.sol:zombie打架的功能. erc721.sol:ERC721代币的接口. ownable.so

以太坊智能合约及应用开发简介

在这个入门教程中我们将建立以太坊应用开发环境并学习编写一个投票智能合约. 在这个教程中,让我们构建一个简单的"Hello World!" 应用程序, 这是一个投票应用程序. 该应用程序非常简单,它所做的只是初始化一组候选人,让任何人投票给候选人,并显示每个候选人收到的总票数. 我有意避免使用任何DAPP框架构建这个应用程序,因为框架抽象掉很多细节,你不了解系统的内部.此外,当你使用框架时,将对框架所做的繁重工作有更多的体会! 1. 设置开发环境 我们使用一个模拟的内存区块链(ganac

以太坊智能合约编程之菜鸟教程

基本概念 了解这些名词是一个不错的开始: 公钥加密系统. Alice有一把公钥和一把私钥.她可以用她的私钥创建数字签名,而Bob可以用她的公钥来验证这个签名确实是用Alice的私钥创建的,也就是说,确实是Alice的签名.当你创建一个以太坊或者比特币钱包的时候,那长长的0xdf...5f地址实质上是个公钥,对应的私钥保存某处.类似于Coinbase的在线钱包可以帮你保管私钥,你也可以自己保管.如果你弄丢了存有资金的钱包的私钥,你就等于永远失去了那笔资金,因此你最好对私钥做好备份.过来人表示:通过