当前位置:   article > 正文

solidity call()与delegatecall()的理解和区别_solidity delegatecall value

solidity delegatecall value
call()

当使用方法是:require(msg.sender.call.value(_weiToWithdraw)());
则作用是将_weiToWithdraw个以太币发送给msg.sender地址,并且调用msg.sender地址的fallback函数

当使用方法是:

addr.call(abi.encode(keccak256("increaseAge(string,uint)")),"jack",1);
那就是调用了合约地址addr的函数increaseAge,并且传入参数是"jack",1

函数的结果

call()的返回结果是一个bool,表示是否成功的调用,或者是失败引起了EVM异常。该方法无法直接访问函数返回结果(因为需要事前知道编码和返回结果大小)。

call()的返回结果即使成功,并不能说操作成功了,只是没有出现异常,比如我们第一个例子中,实际是调用到了fallback()函数。

delegatecall()

calldelegatecall的功能类似,区别仅在于后者仅使用给定地址(Calltest)的代码,其它信息则使用当前合约(Compare)(如存储,余额等等)。

函数的设计目的是为了借用存储在另一个合约的库代码,作为当前合约代码的一部分执行。

二者执行代码的上下文环境的不同,当使用call调用其它合约的函数时,代码是在被调用的合约的环境里执行,对应的,使用delegatecall进行函数调用时代码则是在调用函数的合约的环境里执行,

通过代码测试说明(注意看注释和执行结果):

  1. // SPDX-License-Identifier: GPL-3.0
  2. pragma solidity ^0.8.0;
  3. contract Calltest {
  4. address public sameAddress;
  5. // 获取当前合约地址,并赋值
  6. function test() public {
  7. sameAddress=address(this);
  8. }
  9. }
  10. contract Compare {
  11. // 注意此处的变量与合约Calltest的变量是一模一样的,为delegate,委托调用创造条件
  12. address public sameAddress;
  13. address public testaddress;
  14. // 构造时 将合约Calltest的部署地址传入
  15. constructor(address _addressOfCalltest) {
  16. testaddress = _addressOfCalltest;
  17. }
  18. // call方式调用,代表调用testaddress地址对应合约的test()方法,并且变更testaddress地址对应的状态数据 sameAddress
  19. function useCall() public {
  20. testaddress.call(abi.encode(keccak256("test()")));
  21. }
  22. // delegatecall 方法调用,官方叫做委托调用
  23. // 个人理解:其实就是借用testaddress合约地址的test()代码片段,拿到当前合约(Compare)来执行;
  24. // 也就是说执行时,把test()的代码作为了Compare的一部分代码,但是变量赋值时需要特别小心,每个当前合约的变量都要查看,未经充分测试绝对不要上线
  25. function useDelegatecall() public {
  26. testaddress.delegatecall(abi.encode(keccak256("test()")));
  27. }
  28. }

开发环境:remix+Remix VM(London)

1.部署Calltest合约 获得地址A (0x1E90187F96cb22A93eCfC97dC1F9cBb1A1F3dE99)

2.部署Compare合约,将地址A传入部署,得到地址B (0x1E90187F96cb22A93eCfC97dC1F9cBb1A1F3dE99)

call()测试

        1.Compare合约中调用方法useCall

        2.Calltest合约调用查询方法sameAddress,发现有返回值(A地址)符合预期

        3.Compare合约调用查询方法sameAddress,发现返回值依然是0地址 符合预期

elegatecall()测试

        1.Compare合约中调用方法useDelegatecall

        2.Compare合约调用查询方法sameAddress,发现返回值不是0地址 而是=B地址 出乎意料吧

        精髓:

        elegatecall其实就是借用合约地址testaddress所指向的代码片段,作为当前合约代码的一部分来执行,这样就好理解了,借用+内嵌为当前合约代码执行

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/654131
推荐阅读
相关标签
  

闽ICP备14008679号