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 地址 ...
AI 中文社