Solidity 调用合约
Solidity 支持一个合约调用另一个合约。两个合约既可以位于同一sol文件,也可以位于不同的两个sol文件。
Solidity 还能调用已经上链的其它合约。
调用内部合约
内部合约是指位于同一sol文件中的合约,它们不需要额外的声明就可以直接调用。
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Hello { function echo() external pure returns(string memory){ return "Hello World!"; } } contract SoldityTest { function callHello(address addr) external pure returns(string memory){ // 调用外部合约 Hello 的方法 echo return Hello(addr).echo(); } // 另外一种写法 function callHelloOr(Hello hello) external pure returns(string memory){ // 调用外部合约 Hello 的方法 echo return hello.echo(); } }
我们在部署上面两个合约的时候,首先要部署 Hello,得到它的地址,例如:0x78FD83768c7492aE537924c9658BE3D29D8ffFc1。
然后再部署合约 SoldityTest,调用 SoldityTest 的方法 callHello,传入参数 0x78FD83768c7492aE537924c9658BE3D29D8ffFc1 ,就会输出调用结果:"Hello World!"。
调用外部合约
外部合约是指位于不同文件的外部合约,以及上链的合约。
调用外部合约有两种方法:通过接口方式调用 和 通过签名方式调用。
通过接口方式调用
通过接口方式调用合约,需要在调用者所在的文件中声明被调用者的接口。
被调用者合约 hello.sol:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract IHello { function echo() external pure returns(string memory){ return "Hello World!"; } }
调用者合约 test.sol:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // 被调用者接口 interface IHello { // 被调用的方法 function echo() external pure returns(string memory); } // 调用者合约 contract SoldityTest { function callHello(address addr) external pure returns(string memory){ // 调用外部合约Hello的方法:echo return IHello(addr).echo(); } }
我们首先要部署 hello.sol 文件中的合约 Hello,得到它的地址,例如:0x78FD83768c7492aE537924c9658BE3D29D8ffFc1。
然后再部署合约 SoldityTest,调用 SoldityTest 的方法 callHello,传入参数 0x78FD83768c7492aE537924c9658BE3D29D8ffFc1 ,就会输出调用结果:"Hello World!"。
通过签名方式调用
通过签名方式调用合约,只需要传入被调用者的地址和调用方法声明。
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // 调用者合约 contract SoldityTest { function callHello(address addr) external returns(string memory){ // 调用合约 (bool success,bytes memory data) = addr.call(abi.encodeWithSignature("echo()")); if(success){ return abi.decode(data,(string)); } else { return "error"; } } }
另一种写法:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // 调用者合约 contract SoldityTest { function callHello(address addr) external view returns(string memory){ // 编码被调用者的方法签名 bytes4 methodId = bytes4(keccak256("echo()")); // 调用合约 (bool success,bytes memory data) = addr.staticcall(abi.encodeWithSelector(methodId)); if(success){ return abi.decode(data,(string)); } else { return "error"; } } }
我们首先要部署 hello.sol 文件中的合约 Hello,得到它的地址,例如:0x78FD83768c7492aE537924c9658BE3D29D8ffFc1。
然后再部署合约 SoldityTest,调用 SoldityTest 的方法 callHello,传入参数 0x78FD83768c7492aE537924c9658BE3D29D8ffFc1 ,就会输出调用结果:"Hello World!"。
签名方式调用,发送Eth
通过签名方式调用合约,可以发送Eth。
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // 调用者合约 contract SoldityTest { function callHello(address addr) external returns(string memory){ // 调用合约 (bool success,bytes memory data) = addr.call{value:1000}(abi.encodeWithSignature("echo()")); if(success){ return abi.decode(data,(string)); } else { return "error"; } } }
下一章:Solidity 支付Eth payable
使用 payable 标记的 Solidity 函数可以用于发送和接收 Eth。payable 意味着在调用这个函数的消息中可以附带 Eth。使用 payable 标记的 Solidity 地址 ...