3分钟Solidity: 11.12 区块时间戳

34 阅读1分钟

欢迎订阅专栏3分钟Solidity--智能合约--Web3区块链技术必学

如需获取本内容的最新版本,请参见 Cyfrin.io 上的“块时间戳作(代码示例)”

漏洞

block.timestamp可能会被矿工操纵,但有以下限制:

  • 它不能比其父区块的时间戳更早
  • 它不能设定为太远的未来时间
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

/*
轮盘赌是一种游戏,如果你能在特定时机提交交易,就能赢得合约中的所有以太币。
玩家需要发送10个以太币,如果区块时间戳模15等于0,即可获胜。
*/

/*
1.  用10个以太坊部署轮盘赌
2.  Eve运行着一个强大的矿工,可以操纵区块时间戳。
3.  Eve将block.timestamp设置为未来能被15整除的数字,并找到目标区块哈希。
4.  Eve的区块成功被纳入链中,Eve赢得了轮盘赌游戏。
*/

contract Roulette {
    uint256 public pastBlockTime;

    constructor() payable {}

    function spin() external payable {
        require(msg.value == 10 ether); // 必须发送10个以太币才能参与
        require(block.timestamp != pastBlockTime); // 每个区块仅限一笔交易

        pastBlockTime = block.timestamp;

        if (block.timestamp % 15 == 0) {
            (bool sent,) = msg.sender.call{value: address(this).balance}("");
            require(sent, "Failed to send Ether");
        }
    }
}

预防性技术

  • 不要使用 block.timestamp作为熵源和随机数

Try on Remix试用混音版