深入以太坊智能合約ABI

數(shù)字貓合約 ABI

開(kāi)發(fā) DApp 時(shí)要調(diào)用在區(qū)塊鏈上的 Ethereum 智能合約谦去,就需要智能合約的 ABI慷丽。本文希望更多了解 ABI,如為什么需要 ABI鳄哭?如何解讀 Ethereum 的智能合約 ABI要糊?以及如何取得智能的 ABI?

ABI(Application Binary Interface)

如果理解 API 就很容易了解 ABI妆丘。簡(jiǎn)單來(lái)說(shuō)杨耙,API 是程序與程序間互動(dòng)的接口。這個(gè)接口包含程序提供外界存取所需的 functions飘痛、variables 等。ABI 也是程序間互動(dòng)的接口容握,但程序是被編譯后的 binary code宣脉。所以同樣的接口,但傳遞的是 binary 格式的信息剔氏。所以 ABI 就要描述如何 decode/encode 程序間傳遞的 binary 信息塑猖。下圖以 Linux 為例,描述 Linux 中 API谈跛、ABI 和程序的關(guān)系羊苟。

Linux API and ABI

編譯和部署智能合約

在 Ethereum 智能合約可以被大家使用前,必須先被部署到區(qū)塊鏈上感憾。

從智能合約的代碼到使用智能合約蜡励,大概包含幾個(gè)步驟:

  1. 編寫(xiě)智能合約的代碼(一般是用 Solidity 寫(xiě))
  2. 編譯智能合約的代碼變成可在 EVM 上執(zhí)行的 bytecode(binary code)。同時(shí)可以通過(guò)編譯取得智能合約的 ABI
  3. 部署智能合約,實(shí)際上是把 bytecode 存儲(chǔ)在鏈上(通過(guò)一個(gè)transaction)凉倚,并取得一個(gè)專(zhuān)屬于這個(gè)合約的地址
  4. 如果要寫(xiě)個(gè)程序調(diào)用這個(gè)智能合約兼都,就要把信息發(fā)送到這個(gè)合約的地址(一樣的也是通過(guò)一個(gè) transaction)。Ethereum 節(jié)點(diǎn)會(huì)根據(jù)輸入的信息稽寒,選擇要執(zhí)行合約中的哪一個(gè) function 和要輸入的參數(shù)

而要如何知道這這個(gè)智能合約提供哪些 function 以及應(yīng)該要傳入什么樣的參數(shù)呢扮碧?這些信息就是記錄在智能合約的 ABI!

Ethereum 智能合約 ABI

Ethereum 智能合約 ABI 用一個(gè) array 表示杏糙,其中會(huì)包含數(shù)個(gè)用 JSON 格式表示的 Function 或 Event慎王。根據(jù)最新的 Solidity 文件:

Function

共有 7 個(gè)參數(shù):

  1. name:a string,function 名稱(chēng)

  2. type:a string宏侍,"function", "constructor", or "fallback"

  3. inputs:an array赖淤,function 輸入的參數(shù),包含:

    • name:a string负芋,參數(shù)名

    • type:a string漫蛔,參數(shù)的 data type(e.g. uint256)

    • components:an array,如果輸入的參數(shù)是 tuple(struct) type 才會(huì)有這個(gè)參數(shù)旧蛾。描述 struct 中包含的參數(shù)類(lèi)型

  4. outputs:an array莽龟,function 的返回值,和 inputs 使用相同表示方式锨天。如果沒(méi)有返回值可忽略毯盈,值為 []

  5. payabletrue,function 是否可收 Ether病袄,預(yù)設(shè)為 false

  6. constanttrue搂赋,function 是否會(huì)改寫(xiě)區(qū)塊鏈狀態(tài),反之為 false

  7. stateMutability:a string益缠,其值可能為以下其中之一:"pure"(不會(huì)讀寫(xiě)區(qū)塊鏈狀態(tài))脑奠、"view"(只讀不寫(xiě)區(qū)塊鏈狀態(tài))、"payable" and "nonpayable"(會(huì)改區(qū)塊鏈狀態(tài)幅慌,且如可收 Ether 為 "payable"宋欺,反之為 "nonpayable")

仔細(xì)看會(huì)發(fā)現(xiàn) payableconstant 這兩個(gè)參數(shù)所描述的內(nèi)容,似乎已包含在 stateMutability 中胰伍。

事實(shí)也確實(shí)是這樣的齿诞,在 Solidity v0.4.16 中把 constant 這個(gè)修飾function 的 key words 分成: view(neither reads from nor writes to the state)和 pure(does not modify the state),并從 v0.4.17 開(kāi)始 Type Checker 會(huì)強(qiáng)制檢查骂租。constant 改為只用來(lái)修飾不能被修改的 variable祷杈。并在 ABI 中加入 stateMutability 這個(gè)參數(shù)統(tǒng)一表示,payableconstant 目前保留是為了向后兼容渗饮。這個(gè)改動(dòng)詳細(xì)的內(nèi)容和討論可參考:
https://github.com/ethereum/solidity/issues/992

Event

共有 4 個(gè)參數(shù):

  1. name: a string但汞,event 的名稱(chēng)

  2. type: a string宿刮,always "event"

  3. inputs: an array,輸入?yún)?shù)特占,包含:

    • name: a string糙置,參數(shù)名稱(chēng)

    • type: a string,參數(shù)的 data type(e.g. uint256)

    • components: an array是目,如果輸入?yún)?shù)是 tuple(struct) type 才會(huì)有這個(gè)參數(shù)谤饭。描述 struct 中包含的信息類(lèi)型

    • indexed: true,如果這個(gè)參數(shù)被定義為 indexed 懊纳,反之為 false

  4. anonymous: true揉抵,如果 event 被定義為 anonymous

更新智能合約狀態(tài)需要發(fā)送 transaction,transaction 需要等待驗(yàn)證嗤疯,所以更新合約狀態(tài)是非同步的冤今,無(wú)法馬上取得返回值。使用 Event 可以在狀態(tài)更新成功后茂缚,將相關(guān)信息記錄到 Log戏罢,并讓監(jiān)聽(tīng)這個(gè) Event 的 DApp 或任何應(yīng)用這個(gè)接口的程序收到通知。每筆 transaction 都有對(duì)應(yīng)的 Log脚囊。

所以簡(jiǎn)單來(lái)說(shuō)龟糕,Event 可用來(lái):1. 取得 function 更新合約狀態(tài)的返回值 2. 也可作為合約另外的存儲(chǔ)空間。

Event 的參數(shù)分為:有 indexed悔耘,和其他沒(méi)有 indexed 的讲岁。有 indexed 的參數(shù)可以使用 filter,例如同一個(gè) Event衬以,我可以選擇只監(jiān)聽(tīng)從特定 address 發(fā)出來(lái)的交易缓艳。每筆 Log 的信息同樣分為兩個(gè)部分:Topics(長(zhǎng)度最多為 4 的 array) 和 Data。有 indexed 的參數(shù)會(huì)存儲(chǔ)存在 Log 的 Topics看峻,其他的存在 Data阶淘。如果定義為 anonymous,就不會(huì)產(chǎn)生以下示例中的 Topics[0]互妓,其值為 Event signature 的 hash舶治,作為這個(gè) Event 的 ID。

Event

event Set(address indexed _from, uint value)

用一個(gè)簡(jiǎn)單的智能合約舉個(gè)例子

這個(gè)智能合約包含:

  • data:一個(gè)可修改的 state variable车猬,會(huì)自動(dòng)產(chǎn)生一個(gè)只能讀取的 data() function
  • set():一個(gè)修改 data 值的 function
  • Set():一個(gè)在每次修寫(xiě) data 時(shí)記錄 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

會(huì)生成一個(gè) simpleStorage_sol_SimpleStorage.abi 文件珠闰,里面就是合約ABI 內(nèi)容。

也可以取得合約的 binary code:

solcjs your_contract.sol --bin

Remix

同樣的使用 Solidity Compiler瘫辩,也可以用 Remix伏嗜。在合約的 Details 可以看到完整的 ABI坛悉。可以在 Settings 中指定 Compiler 版本承绸。

Remix

Etherscan

許多知名合約會(huì)把合約 source code 放上 Etherscan 做驗(yàn)證裸影,可以同時(shí)看到h 合約ABI。

Etherscan

另外 Etherscan 提供 API军熏,可用來(lái)取得經(jīng)過(guò)驗(yàn)證的合約 ABI轩猩。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市荡澎,隨后出現(xiàn)的幾起案子均践,更是在濱河造成了極大的恐慌,老刑警劉巖摩幔,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件彤委,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡或衡,警方通過(guò)查閱死者的電腦和手機(jī)焦影,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)封断,“玉大人斯辰,你說(shuō)我怎么就攤上這事〕胃郏” “怎么了椒涯?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)回梧。 經(jīng)常有香客問(wèn)我废岂,道長(zhǎng),這世上最難降的妖魔是什么狱意? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任湖苞,我火速辦了婚禮,結(jié)果婚禮上详囤,老公的妹妹穿的比我還像新娘财骨。我一直安慰自己,他們只是感情好藏姐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布隆箩。 她就那樣靜靜地躺著,像睡著了一般羔杨。 火紅的嫁衣襯著肌膚如雪捌臊。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,708評(píng)論 1 305
  • 那天兜材,我揣著相機(jī)與錄音理澎,去河邊找鬼逞力。 笑死,一個(gè)胖子當(dāng)著我的面吹牛糠爬,可吹牛的內(nèi)容都是我干的寇荧。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼执隧,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼揩抡!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起殴玛,我...
    開(kāi)封第一講書(shū)人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤捅膘,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后滚粟,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體寻仗,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年凡壤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了署尤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡亚侠,死狀恐怖曹体,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情硝烂,我是刑警寧澤箕别,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站滞谢,受9級(jí)特大地震影響串稀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜狮杨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一母截、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧橄教,春花似錦清寇、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至持灰,卻和暖如春垦江,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工比吭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人姨涡。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓衩藤,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親涛漂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子赏表,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容