区块链 区块链技术 比特币公众号手机端

receive payable 里面尽量避免写代码,以免其他合约调用transfer 不成功

liumuhui 11个月前 (11-12) 阅读数 205 #区块链

receive() payable 里面尽量避免写代码,以免其他合约调用transfer 不成功

缘起:最近调试一段solidity代码,本来想测试在收款的时候,记录一个receive 和发出一个log,哪个消耗gas更大

  • 如下图,我定义了两个contract, TestTransfer 中的sendOut函数会使用transfer转账到TransferCount 合约.
    • 第一步 使用remix 测试,总是不成功.
    • 第二步 使用remix直接给TransferCount转账能成功
    • 修改代码,注释掉 TransferCount recieve() 里面的代码,重做第一步测试就能成功.

image.png

转账失败的

pragma solidity >0.8.0 ;

contract TransferCount {
    uint public fallbackCount = 0;
    uint public receiveCount = 0;
    constructor() payable{

    }
    function deposit() payable external{

    }
    receive() external payable {
       //这里增加代码,可能导致合约TestTransfer.sendOut 中调用 address.transfer 因为gas不足调用失败
        receiveCount ++;
    }
    fallback() external payable{
        fallbackCount ++;
    }
}

contract TestTransfer{
    uint public fallbackCount = 0;
    uint public receiveCount = 0;
    address payable public  tc;
    receive() external payable {
        receiveCount ++;
    }
    fallback() external payable{
        fallbackCount ++;
    }

    constructor(address payable addr) payable {
        tc = addr;

    }

    function sendOut(uint amount ) external{
        require(amount  <= address(this).balance, "insufficient balance");
        payable(tc).transfer(amount);

    }
}

转账成功

在receive中写状态变量,gas太高,超过23000 gas。 不过可以发个event,不涉及状态变量。 如下图

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
event Receive(address from, uint256 amount);
contract Target{
    // gas 22625
    receive() payable external{
        emit Receive(msg.sender,msg.value);
    }
}
contract TestTransfer{
    function send(address target )  public payable {
        payable(target).transfer(msg.value);
    }
}
版权声明

本文仅代表作者观点,不代表区块链技术网立场。
本文系作者授权本站发表,未经许可,不得转载。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门