跳到主要内容

合约类型

每一个合约,合约本身也是一个数据类型, 称为合约类型,如下代码定义了一个Hello合约类型:

pragma solidity ^0.8.0;

contract Hello {
function sayHi() public view returns (uint) {
return 10;
}
}

使用合约类型

我们要如何使用合约类型呢,我们可以通过合约类型创建出一个合约事例(即部署一个合约)。

这里是一个例子:

pragma solidity ^0.8.0;

contract Hello {
function sayHi() public view returns (uint) {
return 10;
}
}

contract HelloCreator {
uint public x;
Hello public h;

function createHello() public returns (address) {
h = new Hello();
return address(h);
}
}

上面的代码,调用 HelloCreator 合约的 createHello 函数可以创建一个合约(new Hello())。

我们在 Remix 演练一下,先部署HelloCreator 合约(注意不是部署Hello):

solidity-合约

然后调用createHello 在链上创建一个Hello合约:

solidity-创建合约

右下角的日志中,可以看到创建的合约地址0x93Ff8fe9BF4005...。让我们在Remix 加载该合约,并调用 sayHi 来验证该合约确实部署成功了。

在 Remix 使用 Hello的地址加载Hello, 选择Hello合约, 在At Address 处填入合约地址,如图:

solidity-加载合约

然后调用sayHi() :

solidity-调用合约函数

createHello 函数中,创建的合约赋值给了状态变量 h , 在 HelloCreator 合约,也可以利用h来调用sayHi 函数, 例如,可以在HelloCreator 合约中,添加如下函数:

function callHi() public returns (uint) {
x = h.sayHi();
return x;
}

合约类型元数据成员

Solidity 从 0.6 版本开始,Solidity 增加了一些属性来获取合约类型类似的元信息。

如:对于合约C,可以通过type(C)来获得合约的类型信息,这些信息包含以下内容:

(1)type(C).name :获得合约的名字。

(2)type(C).creationCode:获得创建合约的字节码。

(3)type(C).runtimeCode:获得合约运行时的字节码。

字节码是什么东西? 先留一个坑, 以后有机会介绍 EVM 时,在详细介绍。

额外知识点:如何区分合约及外部地址

经常需要区分一个地址是合约地址还是外部账号地址,区分的关键是看这个地址有没有与之相关联的代码。EVM提供了一个操作码EXTCODESIZE,用来获取地址相关联的代码大小(长度),如果是外部账号地址,则没有代码返回。因此我们可以使用以下方法判断合约地址及外部账号地址。

function isContract(address addr) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(addr) }
return size > 0;
}

如果是在合约外部判断,则可以使用web3.eth.getCode()(一个Web3的API),或者是对应的JSON-RPC方法——eth_getcode。getCode()用来获取参数地址所对应合约的代码,如果参数是一个外部账号地址,则返回“0x”;如果参数是合约,则返回对应的字节码,下面两行代码分别对应无代码和有代码的输出。

>web3.eth.getCode(“0xa5Acc472597C1e1651270da9081Cc5a0b38258E3”) 
“0x”
>web3.eth.getCode(“0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8”) “0x600160008035811a818181146012578301005b601b6001356025565b8060005260206000f25b600060078202905091905056”

这时候,通过对比getCode()的输出内容,就可以很容易判断出是哪一种地址。

小结

提炼本节的重点:合约是一个类型,我们可以通过这个合约类型来创建合约(即部署合约),然后与合约里的函数交互。

------

DeCert.me 码一个未来,DeCert 让每一位开发者轻松构建自己的可信履历。

DeCert.me 由登链社区 @UpchainDAO 孵化,欢迎 Discord 频道 一起交流。

本教程来自贡献者 @Tiny熊