智能合约入门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

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