【问题标题】:Infinite gas warning in Remix for a functionRemix 中的无限气体警告功能
【发布时间】:2021-08-02 17:14:16
【问题描述】:

谁能说出为什么在把这个函数放入Remix时会产生上述警告?

 function doFlip() public{
       uint256 blockValue = uint256(blockhash(block.number - 1));
       uint256 coinFlip = uint256(uint256(blockValue)/FACTOR);
       side = coinFlip == 1 ? true : false;
       flipper.flip(side);
    }

完整的合同如下:

//SPDX-License-Identifier: Unlicensed
pragma solidity ^0.6.0;

import "@openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol";

interface CoinFlip {
    function flip(bool guess) external returns (bool);
 }
 
contract Flipper {

    using SafeMath for uint256;
    uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
    bool public side;
    CoinFlip public flipper;
    
    constructor() public {
        flipper = CoinFlip(xxxxxxxxxx);
    }
    
 

   function doFlip() public{
       uint256 blockValue = uint256(blockhash(block.number - 1));
       uint256 coinFlip = uint256(uint256(blockValue)/FACTOR);
       side = coinFlip == 1 ? true : false;
       flipper.flip(side);
    }
    
   

}


CoinFlip 合约如下所示:

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

import '@openzeppelin/contracts/math/SafeMath.sol';

contract CoinFlip {

  using SafeMath for uint256;
  uint256 public consecutiveWins;
  uint256 lastHash;
  uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;

  constructor() public {
    consecutiveWins = 0;
  }

  function flip(bool _guess) public returns (bool) {
    uint256 blockValue = uint256(blockhash(block.number.sub(1)));

    if (lastHash == blockValue) {
      revert();
    }

    lastHash = blockValue;
    uint256 coinFlip = blockValue.div(FACTOR);
    bool side = coinFlip == 1 ? true : false;

    if (side == _guess) {
      consecutiveWins++;
      return true;
    } else {
      consecutiveWins = 0;
      return false;
    }
  }
}

【问题讨论】:

  • CoinFlip合约是否部署在构造函数中定义的地址上?在 Remix 本地网络上还是在其他网络上(例如 Rinkeby、Ropsten、...)?
  • 是的,确实,部署在同一个网络上
  • 在这种情况下,您能否更新问题并分享flip() 函数体(以及它所访问的合约属性等依赖项)?我的猜测是flip() 函数有一个失败的require() 条件会引发异常,并且由于doFlip() 没有捕获异常,它会恢复交易 - 导致无限气体量消息。但这只是猜测,没有重现问题的代码和值。
  • 添加了具有flip()函数的CoinFlip合约。如您所见,它没有任何要求,看起来很基本

标签: ethereum solidity remix


【解决方案1】:

EVM 的 Remix JavaScript 模拟器似乎一直存在问题,无法计算 blockhash()

我能够重现该问题:

pragma solidity ^0.8;

contract MyContract {
    function foo() external returns (bytes32) {
        return blockhash(1); // fails in Remix JS VM
    }
}

并在 Ethereum StackExchange 上找到了链接到已删除问题的 this answer

因此,如果您需要合约在 Remix JS VM 中工作,我建议您更改合约逻辑,使其不使用失败的 blockhash() 函数。

【讨论】:

  • 我不认为这是块哈希问题,因为当我注释掉行时, Flipper.flip(side);上面,警告是,即使那里也有一个块哈希。可能是 Remix 在看到另一个合同的引用时会吓坏,所以它会通过抛出这个警告来过度谨慎,以防另一个合同确实有一些奇怪的东西
  • @Vlad 您还可以在doFlip() 函数中使用blockhash()。因此,仅注释掉 flipper.flip(side); 行仍会导致还原,因为还有一个未注释的 blockhash()
  • 无论如何,如果你这样做,警告就会从混音中消失
猜你喜欢
  • 1970-01-01
  • 2018-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多