call和delegatecall合约调用 / 学习智能合约#60

in STEEM CN/中文2 years ago

昨天研究了下重入攻击,有查到call这个函数,感觉它很万能--几乎能干所有的事情!既能转帐以太,又能调用合约,也就无怪乎有重入风险。现在solidity早就建议用transfer来转帐以太,调用合约用接口(interface)。其实用call来调用合约也是很方便的,同时还有个类似的函数delegatecall

调用另一个合约中的函数,主要是两个方法:call 和 delegatecall。但推荐用接口调用!
call 会切换到被调合约中去执行方法,会切换上下文。msg.sender是主调合约地址。
delegatecall 则是将被调合约中的方法调到本合约中执行,也就是不会切换上下文。msg.sender是发起者本人。

传入的参数(address _addr)是合约地址。下边有个案例,可以试着去体会细节。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SetNum {
    uint256 public n = 20;
    address public sender;

    function setN(uint256 _n) public {
        n = _n;
        sender = msg.sender;
    }
}

contract CallSet {
    uint256 public n = 15;
    address public sender;

    function CallTest(address _addr, uint256 _n) public {
        _addr.call(abi.encodeWithSignature("setN(uint256)", _n));  //改变SetNum中的n值
        sender = msg.sender;  //是调用者本人,同时会改变SetNum的sender地址
    }

    function delegatecallTest(address _addr, uint256 _n) public {
        _addr.delegatecall(abi.encodeWithSignature("setN(uint256)", _n)); //改变自身的n值
        sender = msg.sender;  //是调用者本人,不会改变SetNum的sender地址
    }
}

call和delegatecal这两个方法做了很大改进,我估计也是为了防止重入的风险。以前是要算出函数的ID值,现在是计算整个的签名值。刚刚还不知错误在哪,到google上又是一顿好找,终于解决!solidity的文件写得干巴巴的,不好理解。找了个案例集,很不错,分享下。

Coin Marketplace

STEEM 0.19
TRX 0.13
JST 0.030
BTC 63630.78
ETH 3406.29
USDT 1.00
SBD 2.55