solidity的一段代码revert

zhangtgv
  • 184

使用ganache和truffle开发,使用了如下两个合约,首先部署Game合约,然后部署GamePlayer。在执行GamePlayer的attack时,运行到g.deposit{value:1}();就会被revert,麻烦各位大神赐教。代码和truffle console的运行命令如下

代码:

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

contract Game{
    //记录各个玩家余额
    mapping(address => uint256) private balance;
    
    constructor() payable {
        
    }

    //玩家下注函数,向游戏合约充值
    function deposit() public payable{
        balance[msg.sender] += msg.value;
    }
    //玩家向其他玩家转移游戏合约中的资产
    function playerTransfer(address to, uint amount) public {
        require(balance[msg.sender] >= amount);
        
        balance[to] += amount;
        balance[msg.sender] -= amount;
    }
    //玩家提款函数
    function withdraw() public {
        bool ret;
        bytes  memory data;
        
        uint256 amount = balance[msg.sender];
       
        (ret, data) = msg.sender.call{value:amount}("");
     
        if (ret){
            balance[msg.sender] = 0;
        }
    }
    //查询游戏合约中玩家的资产
    function playerBalance(address player) public view returns(uint256){
        return balance[player];
    }

    //获取合约总余额函数
    function gameBalance() public view returns(uint256){
        return address(this).balance;
    }
}


contract GamePlayer{
    //记录游戏合约地址
    address payable target;
    //记录攻击者外部账户地址
    address attacker;

    constructor() payable{
        
    }

    //攻击函数,外部账户调用这个合约对游戏合约进行攻击
    function attack(address payable addr) public{
        //记录被攻击者合约地址和攻击者外部账户地址
        target = addr;
        attacker = (msg.sender);
        
        Game g = Game(target);

        //攻击合约做为玩家向游戏中充值一个1以太币
        g.deposit{value:1}();
        //提款
        //g.withdraw();
    }

    //fallback函数
    fallback() payable external {
        // Game g = Game(target);
        // 将游戏合约中的1个以太币转移给攻击者外部账户
        // g.playerTransfer(attacker, 1000);
    }
}

truffle console执行的命令:

let accounts = await web3.eth.getAccounts()
let gameInstance = await Game.new()
gameInstance.deposit({from:accounts[0], value:100000})
let gamePlayerInstance = await GamePlayer.new()
gamePlayerInstance.attack(gameInstance.address)

报错信息:

Uncaught Error: Returned error: VM Exception while processing transaction: revert
    at evalmachine.<anonymous>:1:28
    at evalmachine.<anonymous>:2:49
    at sigintHandlersWrap (vm.js:274:12)
    at Script.runInContext (vm.js:142:14)
    at runScript (/opt/node-v14.17.1-linux-x64/lib/node_modules/truffle/build/webpack:/packages/core/lib/console.js:329:1)
    at Console.interpret (/opt/node-v14.17.1-linux-x64/lib/node_modules/truffle/build/webpack:/packages/core/lib/console.js:344:1)
    at bound (domain.js:416:15)
    at REPLServer.runBound [as eval] (domain.js:427:12)
    at REPLServer.onLine (repl.js:819:10)
    at REPLServer.emit (events.js:375:28)
    at REPLServer.emit (domain.js:470:12)
    at REPLServer.Interface._onLine (readline.js:364:10)
    at REPLServer.Interface._line (readline.js:700:8)
    at REPLServer.Interface._ttyWrite (readline.js:1045:14) {
  data: {
    '0x259e0a165fb8dd25fec6ee83b184d9b3c32dccf251a7aa58aa4ce5da7fad3c6e': { error: 'revert', program_counter: 344, return: '0x' },
    stack: 'c: VM Exception while processing transaction: revert\n' +
      '    at Function.c.fromResults (/opt/node-v14.17.1-linux-x64/lib/node_modules/ganache-cli/build/ganache-core.node.cli.js:4:192416)\n' +
      '    at w.processBlock (/opt/node-v14.17.1-linux-x64/lib/node_modules/ganache-cli/build/ganache-core.node.cli.js:42:50915)\n' +
      '    at runMicrotasks (<anonymous>)\n' +
      '    at processTicksAndRejections (internal/process/task_queues.js:95:5)',
    name: 'c'
  },
  hijackedStack: 'Error: Returned error: VM Exception while processing transaction: revert\n' +
    '    at Object.ErrorResponse (/opt/node-v14.17.1-linux-x64/lib/node_modules/truffle/build/webpack:/node_modules/web3-core-helpers/lib/errors.js:28:1)\n' +
    '    at /opt/node-v14.17.1-linux-x64/lib/node_modules/truffle/build/webpack:/node_modules/web3/node_modules/web3-core-requestmanager/lib/index.js:303:1\n' +
    '    at /opt/node-v14.17.1-linux-x64/lib/node_modules/truffle/build/webpack:/packages/provider/wrapper.js:107:1\n' +
    '    at XMLHttpRequest.request.onreadystatechange (/opt/node-v14.17.1-linux-x64/lib/node_modules/truffle/build/webpack:/node_modules/web3/node_modules/web3-providers-http/lib/index.js:98:1)\n' +
    '    at XMLHttpRequestEventTarget.dispatchEvent (/opt/node-v14.17.1-linux-x64/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request-event-target.js:34:1)\n' +
    '    at XMLHttpRequest.exports.modules.996763.XMLHttpRequest._setReadyState (/opt/node-v14.17.1-linux-x64/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request.js:208:1)\n' +
    '    at XMLHttpRequest.exports.modules.996763.XMLHttpRequest._onHttpResponseEnd (/opt/node-v14.17.1-linux-x64/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request.js:318:1)\n' +
    '    at IncomingMessage.<anonymous> (/opt/node-v14.17.1-linux-x64/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request.js:289:47)\n' +
    '    at IncomingMessage.emit (events.js:387:35)\n' +
    '    at IncomingMessage.emit (domain.js:532:15)\n' +
    '    at endReadableNT (internal/streams/readable.js:1317:12)\n' +
    '    at processTicksAndRejections (internal/process/task_queues.js:82:21)'
}
回复
阅读 440
1 个回答

通过其他实验发现,这里revert的原因应该是余额不足。实验发现在attack方法中调用deposit的话,对于Game这个合约来说msg.sender其实是GamePlayer的合约地址。但是之前一直没有对GamePlayer合约进行充值,所以GamePlayer的balance就是0,最终导致revert调用失败。解决方法就是在GamePlayer创建的时候先充入一些以太。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏