【问题标题】:How to Avoid making time-based decisions in contract business logic?如何避免在合约业务逻辑中做出基于时间的决策?
【发布时间】:2022-01-02 14:33:30
【问题描述】:

我写了一个省钱的智能合约,其中用户存入 ETH 并定义他们希望在合约中保留该 ETH 的时间,例如:用户 X 存入 2ETH 一年,他们只能在该期限之后提取他们的 ETH . 但是solidity linter 一直告诉我,我不应该依赖block.timestamp 来做决定。 这是我用来将每个地址映射到余额和结束时间的Saving 结构:

struct Saving {
    uint256 balance;
    uint256 endTime;
}

这是我的函数修饰符,我要求提款时间大于我在存款时存储的 endTime:

modifier onlyValidTimeWithdraw() {
    require(
        block.timestamp > balances[msg.sender].endTime,
        "You cannot withdraw yet"
    );
    _;
}

这是我通过 linter 得到的信息。

在做了一些研究后,我发现我的合约中不应该有时间相关的条件,因为矿工可以操纵时间戳,但我没有找到任何替代方案。

【问题讨论】:

    标签: ethereum solidity


    【解决方案1】:

    矿工可以在大约 10 分钟的范围内操纵区块时间戳。几秒钟,这足以影响业务逻辑,取决于秒级精度。

    function betLottery() external {
        // the block.timestamp can be affected by a miner
        // and they can submit their own winning transaction
        if (block.timestamp % 2 == 0) {
            win();
        }
    }
    

    但由于您的逻辑依赖于更长的时间,我会简单地忽略或抑制警告。

    或者,如果它适合您的用例,您可以根据大多数 linter 允许的块号进行验证。

    struct Saving {
        uint256 balance;
        uint256 endBlock;
    }
    
    require(
        block.number > balances[msg.sender].endBlock,
        "You cannot withdraw yet"
    );
    

    【讨论】:

      猜你喜欢
      • 2017-07-04
      • 2015-02-12
      • 2011-05-02
      • 2016-03-21
      • 1970-01-01
      • 2016-09-26
      • 2011-09-14
      • 2019-06-17
      • 1970-01-01
      相关资源
      最近更新 更多