赞
踩
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()
函数。
call
与delegatecall
的功能类似,区别仅在于后者仅使用给定地址(Calltest)的代码,其它信息则使用当前合约(Compare)(如存储,余额等等)。
函数的设计目的是为了借用存储在另一个合约的库代码,作为当前合约代码的一部分执行。
二者执行代码的上下文环境的不同,当使用call调用其它合约的函数时,代码是在被调用的合约的环境里执行,对应的,使用delegatecall进行函数调用时代码则是在调用函数的合约的环境里执行,
通过代码测试说明(注意看注释和执行结果):
- // SPDX-License-Identifier: GPL-3.0
- pragma solidity ^0.8.0;
- contract Calltest {
- address public sameAddress;
- // 获取当前合约地址,并赋值
- function test() public {
- sameAddress=address(this);
- }
- }
-
-
- contract Compare {
- // 注意此处的变量与合约Calltest的变量是一模一样的,为delegate,委托调用创造条件
- address public sameAddress;
-
- address public testaddress;
- // 构造时 将合约Calltest的部署地址传入
- constructor(address _addressOfCalltest) {
- testaddress = _addressOfCalltest;
- }
- // call方式调用,代表调用testaddress地址对应合约的test()方法,并且变更testaddress地址对应的状态数据 sameAddress
- function useCall() public {
- testaddress.call(abi.encode(keccak256("test()")));
- }
- // delegatecall 方法调用,官方叫做委托调用
- // 个人理解:其实就是借用testaddress合约地址的test()代码片段,拿到当前合约(Compare)来执行;
- // 也就是说执行时,把test()的代码作为了Compare的一部分代码,但是变量赋值时需要特别小心,每个当前合约的变量都要查看,未经充分测试绝对不要上线
- function useDelegatecall() public {
- testaddress.delegatecall(abi.encode(keccak256("test()")));
- }
- }
开发环境: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所指向的代码片段,作为当前合约代码的一部分来执行,这样就好理解了,借用+内嵌为当前合约代码执行
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。