# 合约调用合约的三种方式

By [fiveeth](https://paragraph.com/@fiveeth) · 2022-05-20

---

### 第一种：接口形式调用合约

为什么采用这种方式？

原因是因为被调用合约过于复杂的时候，全引入进来的话没有必要！

被调用合约：

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    contract Counter {
        uint public count;
    
        function inc() external  {
           count += 1;
        }
    
        function dec() external {
            count -= 1;
        }
    }
    

调用合约：

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    // 这个接口名称叫什么不重要，规范建议首字母大写
    interface ICounter {
        function count() external view returns(uint);
        function inc() external;
    }
    
    contract Interface {
        uint public count;
        
        // _counter为被调用合约的地址
        function examples(address _counter) external {
            ICounter(_counter).inc();
            count = ICounter(_counter).count();
        }
    }
    

### 第二种：直接引入形式调用合约

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    contract CallOtherContract {
        // 第一种方式
        // function setX(address _test, uint _x) external {
        //     TestContract(_test).setX(_x);
        // }
    
        // 第二种方式
        function setX(TestContract _test, uint _x) external {
            _test.setX(_x);
        }
    
        function getX(address _test) external view returns(uint) {
            return TestContract(_test).getX();
        }
    
        function setXandSendEth(address _test, uint _x) external payable{
            TestContract(_test).setXandSendEth{value: msg.value} (_x);
        }
    
        function getXandSendEth(address _test) external view returns(uint x, uint value) {
            (x, value) = TestContract(_test).getXandSendEth();
        }
    }
    
    contract TestContract {
        uint public x;
        uint public value;
    
        function setX(uint _x) public {
            x = _x;
        }
    
        function getX() public view returns(uint) {
            return x;
        }
    
        function setXandSendEth(uint _x) public payable {
            x = _x;
            value = msg.value;
        }
    
        function getXandSendEth() public view returns(uint,uint) {
            return (x, value);
        }
    }
    

### 第三种：call形式调用合约（注意问题）

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    contract TestCall {
        string public message;
        uint public x;
    
        event Log(string message);
    
        fallback() external payable {
            emit Log("fallback called");
        }
    
        function foo(string memory _message, uint _x) external payable returns(bool, uint) {
            message = _message;
            x = _x;
            return (true, 999);
        }
    }
    
    
    contract Call {
        bytes public data;
    
        function callFoo(address _test) external payable {
            (bool _status, bytes memory _data) = _test.call{value: 100}(abi.encodeWithSignature(
                "foo(string,uint256)", "call", 10));  // "foo(string,uint256)"这块参数类型之间一定不能有空格
            require(_status, "call failed");
            data = _data;
        }
    
        function callOther(address _test) external {
            (bool _status, ) = _test.call(abi.encodeWithSignature(
                "callOther()"));
            require(_status, "callOther failed");
        }
    }

---

*Originally published on [fiveeth](https://paragraph.com/@fiveeth/QkTEh0IteuCEq4Pzpdwh)*
