智能合約入門2——library部署及調用

我們不造輪子,我們只是輪子的搬運工。

我們在進行軟件開發的時候,往往會用到別人寫的一些現成的東西,像python裏的tensorflow、numpy、pandas,C++裏的Qt、 boost等等。這類別人寫好的代碼往往被稱作“庫”(也叫輪子),引用別人的庫需要有現成的庫文件。

在區塊鏈上,同樣也包含這種概念,但是與我們一般編譯程序不同,我們引用的代碼是已經部署在區塊鏈網絡裏的代碼,不需要本地有這個庫。

這一步的教程比較複雜,分爲5個部分:
1.自己撰寫一個Libirary。
2.生成調用Library所需的Metadata。
3.編輯Metadata。
4.鏈接Library並部署。
5.查看部署詳情。

撰寫Library

library其實跟普通的contract沒什麼區別,只不過它是以library作爲key word並且可以讓其他的contract調用已經部署過的library,這樣不用重複造輪子。

pragma solidity >=0.4.22 <0.6.0;

contract test {
    function get () public returns(uint) {
        // should call a library method which returns `3`
        return LibraryForTest.getFromLib();    
    }
}

library LibraryForTest {
    function getFromLib() public returns(uint) {
        return 3;
    }
}

首先是在library裏製作一個getFromLib的函數,返回值爲3,然後再在contract當中建立一個get函數,調用這個getFromLib函數。

要注意的是,在solidity語言當中,返回值的類型也要卸載函數定義當中,通過returns定義返回值類型,這裏使用的是uint也就是無符號整型。

進行編譯和部署,在部署完後可以在界面內進行調用。(建議使用Ropsten測試網,可以領取測試的手續費)

生成調用Library所需的Metadata

在之前的程序當中,我們將contract和library寫在同一個文件裏,但是實際上在部署之後,他們將會是兩個不同的地址,那麼如果contract想引用這個library,就必須知道它的地址。

但library的地址並不會直接顯示在合約當中,在編譯好的contract的bytecode當中,會有一個placeholder指向這個library的address。

所以在部署一個調用library的contract之前,你需要生成這個contract的metadata,然後將要調用的library的address加入到metadata當中。

接下來我們就來看一下如何找metadata。

metadata在編譯(compile)的時候產生,當我們選擇左下角的設定,打勾generate metadata的選項,再進行編譯。就可以在文件裏找到sampleContract_metadata.json的文件。

編輯Metadata

Metadata的deploy當中有我們在編譯過程中所需library的所有address。

    "deploy": {
        "VM:-": {
            "linkReferences": {
                "browser/.learneth/Deploy with Libraries/2_Generate_Metadata/2_contractSimpleLibrary.sol": {
                    "aLib": "<address>"
                }
            },
            "autoDeployLib": true
        },
        "main:1": {
            "linkReferences": {
                "browser/.learneth/Deploy with Libraries/2_Generate_Metadata/2_contractSimpleLibrary.sol": {
                    "aLib": "<address>"
                }
            },
            "autoDeployLib": true
        },

關鍵詞<address>包含的是已經部署過的library的address,對於每個網絡需要進行具體說明。

autoDeployLib是一個bool量,代表remix在進行部署前是否要自動部署這個lib。

一般來說,autoDeploy是true,<address>不會被調用到,remix會進行自動部署。

但是爲了更好的模仿現實情況,我們在這裏將通過手動鏈接已經在網絡上部署過的VM Lib。

首先,我們將VM的autoDeply設置爲false。

手動連接library並部署

如果這個時候我們直接切換到deploy選擇simplecontract進行部署,會出現如下錯誤:

那麼首先,我們要先進行VM的部署,在deploy界面上更改contract,有個libA,進行部署。

部署後下面會有一個複製address的按鈕,點擊就可以複製已經部署好的library地址。

然後複製粘帖到之前我們找到的那個json文件當中。

        "VM:-": {
            "linkReferences": {
                "browser/.learneth/Deploy with Libraries/2_Generate_Metadata/2_contractSimpleLibrary.sol": {
                    "aLib": "0xf8e81D47203A594245E36C48e151709F0C19fBe8"
                }
            },
            "autoDeployLib": false
        },

再次跳回之前的deploy界面,選擇simplecontract進行部署,部署即可成功。

查看部署信息

在編譯後我們可以查看它的bytecode,在下面有一行小字可以複製到clipboard,貼出來大概是這樣:

{
    "linkReferences": {
        "browser/contractSimpleLibrary.sol": {
            "LibraryForTest": [
                {
                    "length": 20,
                    "start": 109
                }
            ]
        }
    },
    "object": "608060405234801561001057600080fd5b50610101806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80636d4ce63c14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b600073__$92b7644c0d8dcc07d172959bb8f25dc6be$__6387cc10e16040518163ffffffff1660e01b815260040160206040518083038186803b158015608e57600080fd5b505af415801560a1573d6000803e3d6000fd5b505050506040513d602081101560b657600080fd5b810190808051906020019092919050505090509056fea265627a7a72315820cc244a6979e5f20d4286dc7691fb21c2e6c9a88c694caea792eb02614a93ad0a64736f6c63430005110032",
    "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO ... ",
    "sourceMap": "34:107:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;34:107:0;;;;;;;"
}

這個東西看起來可能有些複雜,前面的linkReference內的內容代表被調用庫的信息。後面的object(bytecode)代表這個合約將被存在區塊鏈上的字節流,也就是說整個合約能在區塊鏈上查到的就是這一串數字。

在bytecode當中有一段__$92b7644c0d8dcc07d172959bb8f25dc6be __代表的是指向被調用library地址的佔位符(placeholder)。

opcodes是區塊鏈實現操作的語言,用於進行交易和轉移,被腳本引擎Script所調用。sourcemap是用於調試的源碼映射(這個我也不太懂什麼意思)。

結語

對於library的部署和調用是智能合約使用當中很基礎的一部分,但是從嘗試當中也能發現並不是一件簡單的事情。由於要將合約放到一個全世界都可以調用的地方,勢必要進行壓縮和刪減。

將部署和調用分開也是爲了更好地使用contract和library這兩個功能不同的關鍵字。從架構設計上來說,還有很多值得學習和研究的地方。

參考資料:https://blog.csdn.net/weixin_40959706/article/details/90719518

https://blog.csdn.net/HiBlock/article/details/81395375

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章