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
    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 '21 at 04:45
  • 1
    This answer has some details on using block hash as a source of randomness: https://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 – The Renaissance May 12 '21 at 07:48

0 Answers0