1

I would like someone to tell me if I am neglecting serious security concerns here. I Am trying to create a Solidity slot machine where hash puzzles (leading zeros) are used to get various jackpots. However, I can't just use a nonce as someone could test nonces offchain and submit the winning one first try. So I've been looking into PRNGs. And I found future blockhashes to be a solid idea as it's very unlikely a miner will be the creator of each and every block in a sequence. The code bellow is a quick simple example of logic for a lottery contract where users submit guesses that must "vest" a number of blocks before they can be checked for a win.

    contract Lottery{

    uint128 difficulty;
    uint128 immutable public BLOCK_VEST_PERIOD;
    mapping(address => guess) entry;

    struct guess{
        bytes32 guess;
        uint256 vestEnd;
    }

    constructor(uint128 _vestPeriod, uint128 _difficulty){
        BLOCK_VEST_PERIOD = _vestPeriod;
        difficulty = _difficulty;
    }

    function submitEntry(uint128 _x)external{
        entry[msg.sender] = guess(
            keccak256(abi.encodePacked(_x)),           //guess is stored as the hash of the number entry
            block.number + BLOCK_VEST_PERIOD
        );
    }

    /// @dev returns true if entry is a winner
    function claimEntry()external returns(bool){
        require(block.number - entry[msg.sender].vestEnd < 256, "cannot claimEntry if more than 255 blocks have passed");
        require(block.number >= entry[msg.sender].vestEnd, "must wait a few more blocks for vesting to end. For security reasons");
        bytes32 hash = entry[msg.sender].guess;
        for(uint128 i = 0; i < BLOCK_VEST_PERIOD; i++){
            hash = keccak256(abi.encodePacked(
                hash,
                blockhash(i)
                ));
        }
        return hashPuzzle(hash);
    }

    function hashPuzzle(bytes32 _entry) public returns(bool){
        /// @dev will return true if hash's leading 0s >= difficulty
    }

}

As far as I can tell the only way to cheat this system would be to have control of every block or at least the last block as a miner could discard it if unfavorable to get a second chance. However, this seems to be a negligible advantage in practice, especially if a hash puzzle is sufficiently difficult. Please let me know if I am wrong about this.

2
  • 2
    It doesn't look bad. The problem with your question is that there's no way I'm gonna say it is reasonable secure. If I need something secure I'd probably use an oracle.
    – Ismael
    May 12, 2021 at 4:45
  • 1
    This answer has some details on using block hash as a source of randomness: ethereum.stackexchange.com/a/95083/68501 I don't think this is a duplicate question since OP here is also demonstrating code and looking for feedback May 12, 2021 at 7:48

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.