如何理解以太坊ABI - 應用程式二進位制介面

Tiny熊發表於2018-08-10

很多同學不是很明白以太坊ABI是什麼,他的作用是什麼,讀完本文就明白了。

寫在前面

閱讀本文前,你應該對以太坊、智慧合約有所瞭解,
如果你還不瞭解,建議你先看以太坊是什麼,也可以觀看我們的視訊:零基礎搞懂區塊鏈深入詳解以太坊智慧合約語言Solidity, 可以系統全面學習理解以太坊、智慧合約。

ABI 是什麼

ABI 全稱是 Application Binary Interface,翻譯過來就是:應用程式二進位制介面,簡單來說就是 以太坊的呼叫合約時的介面說明。還不是很理解,沒關係。

呼叫合約函式發生了什麼

從外部施加給以太坊的行為都稱之為向以太坊網路提交了一個交易, 呼叫合約函式其實是向合約地址(賬戶)提交了一個交易,這個交易有一個附加資料,這個附加的資料就是ABI的編碼資料。
如何理解以太坊ABI - 應用程式二進位制介面

比特幣的交易也可以附加資料,以太坊革命性的地方就是能把附加資料轉化為都函式的執行。

因此要想和合約互動,就離不開ABI資料。

演示呼叫函式

以下面以個最簡單的合約為例,我們看看用引數 1 呼叫set(uint x),這個交易附帶的資料是什麼。

pragma solidity ^0.4.0;

contract SimpleStorage {
    
    uint storedData;
    
    function set(uint x) public {
        storedData = x;
    }

    function get() public constant returns (uint) {
        return storedData;
    }
}

當然第一步需要先把合約部署到以太坊網路(其實部署也是一個)上,然後用 “1” 作為引數呼叫set,如下圖:
如何理解以太坊ABI - 應用程式二進位制介面

然後我們開啟etherscan檢視交易詳情資料, 可以看到其附加資料如下圖:
如何理解以太坊ABI - 應用程式二進位制介面

這個資料就是ABI的編碼資料:

0x60fe47b10000000000000000000000000000000000000000000000000000000000000001

ABI 編碼分析

我把上面交易的附加資料拷貝出來分析一下,這個資料可以分成兩個子部分:

  • 函式選擇器(4位元組)
    0x60fe47b1

  • 第一個引數(32位元組)
    00000000000000000000000000000000000000000000000000000000000000001

函式選擇器值 實際是對函式簽名字串進行sha3(keccak256)雜湊運算之後,取前4個位元組,用程式碼表示就是:

    bytes4(sha3(“set(uint256)”)) == 0x60fe47b1

引數部分則是使用對應的16進位制數。

現在就好理解 附加資料怎麼轉化為對應的函式呼叫。

ABI 編碼函式

那麼怎麼獲得函式對應的ABI 資料呢, 有兩種方法:

Solidity ABI 編碼函式

一個是 solidity 提供了ABI的相關API, 用來直接得到ABI編碼資訊,這些函式有:

  • abi.encode(...) returns (bytes):計算引數的ABI編碼。
  • abi.encodePacked(...) returns (bytes):計算引數的緊密打包編碼
  • abi. encodeWithSelector(bytes4 selector, ...) returns (bytes): 計算函式選擇器和引數的ABI編碼
  • abi.encodeWithSignature(string signature, ...) returns (bytes): 等價於* abi.encodeWithSelector(bytes4(keccak256(signature), ...)

通過ABI編碼函式可以在不用呼叫函式的情況下,獲得ABI編碼值,下面通過一段程式碼來看看這些方法的使用:

pragma solidity ^0.4.24;

contract testABI {
    uint storedData;

    function set(uint x) public {
        storedData = x;
    }

    function abiEncode() public constant returns (bytes) {
        abi.encode(1);  // 計算1的ABI編碼
        return abi.encodeWithSignature("set(uint256)", 1); //計算函式set(uint256) 及引數1 的ABI 編碼
    }
}

大家可以執行執行下abiEncode函式,它的輸出其實就是前面呼叫的附加資料。

Web3 ABI 編碼函式

另一個web3提供相應的API,例如使用web3計算函式選擇器的方式如下:

web3.eth.abi.encodeFunctionSignature('myMethod(uint256,string)');

其完整的文件在這裡,這裡不一一演示。

歡迎來知識星球提問,星球內已經聚集了300多位區塊鏈技術愛好者。
深入淺出區塊鏈 - 系統學習區塊鏈,打造最好的區塊鏈技術部落格。

相關文章