合约内的合约调用

  • nilliol
  • 更新于 2024-05-26 10:10
  • 阅读 1673

合约调用合约有五种方法

合约调用合约有五种方法:

  • 合约变量
  • CALL
  • CALLCODE
  • DELEGATECALL
  • STATICCALL

1 合约变量

通过创建或调用合约变量即可使用其他合约中的变量

    function callGetX2(address _Address) external view returns(uint x){
        OtherContract oc = OtherContract(_Address);
        x = oc.getX();
    }

其中OtherContract就是我们想调用的合约名字,_Address就是目标合约被部署后的地址。

这种方法要求:已知目标合约的代码(或接口)和地址。

调用者修改了,执行环境被修改

2 call

address类型低级成员函数,返回(bool, data),分别对应call是否成功以及目标函数的返回值。

call使用后调用者(msg.sender)被修改,执行环境也修改为目标合约的执行环境。可以指定发送给目标合约的valuegas

不推荐使用它来调用其他合约,因为不安全(因为这回将函数调用的主动权交给它),但其可以帮助我们在不知道目标合约代码(或接口)的情况下调用其函数。使用方法如下:

address.call{value:x,gas:y}(data)
// data 为二进制编码
// address 是目标合约地址,即想调用这个合约的函数

其中的data是使用((20240522135040-4donrkz "abi.encodeWithSignature"))获得的,其值为对调用函数和函数参数内容的编码。

当调用了不存在的函数时,会触发目标合约(address)的fallback函数,这存在安全风险。

3 delegatecall

call类似,为address类型低级成员函数,返回值也和call类似,但其只能指定gas,不能指定value

delegatecall使用后调用者(msg.sender)和执行环境均不变。

使用delegatecall一定要保证当前合约和目标合约的状态变量存储结构相同,并且目标合约安全,不然会造成资产损失。

使用其场景主要有((20240522094009-0i2a5ya "代理合约"))和 EIP-2535 Diamonds。使用方法如下:

address.delegatecall{value:x,gas:y}(data)
// data 为二进制编码,也是用 abi.encodeWithSignature 获得的
// address 是目标合约地址,即想调用这个合约的函数

4 callcode

call类似,为address类型低级成员函数,返回值也和call类似,使用后调用者(msg.sender)会修改,执行环境不会改变。

solidity 0.5.0后禁用了。

5 staticcall

它允许合约调用目标合约的函数和数据,但不能修改(即只能调用viewpure函数)。

目前solidity中没有 API 能够直接调用它,仅仅是计划将来在编译器层面把调用view和pure类型的函数编译成STATICCALL指令。

6 总结

主要能够使用的有三种(calldelegatecall合约变量),有一种废弃(callcode),一种未来计划用在编译器层面中(staticcall)。

几种方法可以这样记:call方法属于‘极端改变’的方法,调用者和执行环境均改变;delegatecall方法属于‘极端不改变’的方法,调用者和执行环境均不变;callcode方法改变调用者,但执行环境不变;合约变量方法要求高(多了个目标合约代码或接口的要求),但安全。

点赞 3
收藏 3
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

2 条评论

请先 登录 后评论
nilliol
nilliol
0xbe3e...29A9
web3 的学习者,寻找实习机会中。 博客地址:https://llwh2333.github.io