4

All the Pseudo Random Number Generators that depend on block hash or block time seems to generate the same "random" number for the same block. Is there any way to generate different numbers in the same block?

The use case is something like this, I have a game contract, people can send 1 Ether to this contract each time, and for a 1% chance, the sender may receive all the Ethers stored in the contract. Normally I use a PRNG with block hash and stuff, generate a uint256 number, mod it with 100 and award the sender when the result is 0.

However, there's a problem in that, as one person (address) may send multiple transactions to the contract at the same time (with incrementing nonce) and those transactions may be mined within a single block, then the "random" number ends up the same for all those transactions. That means if this person doesn't win the prize in the first transaction, he/she will not be able to win the prize in all the transactions that are mined in the same block. This seems to be unfair to this person, as I want to design the game so that on average if one person sends 100 transactions, he/she will be able to win once. But now if this person sends 100 transactions consecutively which are mined in 10 blocks (say each block included 10 transactions from this person), that means he/she only has 1/10 chance to win the prize.

Naturally, I'd like people to participate more in the game, instead of waiting for a transaction mined before sending the next transaction. So is there any way to make the PRNG generate random numbers for different transactions within the same block?

I've looked through the solidity docs, it seems the available variables that have the potential to be part of a PRNG are either block-related or something like the msg.sender, msg.value, msg.data, tx.gasprice, etc. which will all be the same for my use case when mined within the same block. And unfortunately nonce is not available in solidity? Am I forced to rely on some off-chain centralized random number generator for my use case?

1 Answer 1

5

You can use an incrementing nonce each time a number is generated. This would have a large effect on the hash output.

Random 0-100 Example:

contract Random {
    uint nonce;


    function random() internal returns (uint) {
    uint random = uint(keccak256(now, msg.sender, nonce)) % 100;
    nonce++;
    return random;
    }

    function getRandom() external view returns (uint) {
        return random();
    }
}
2
  • 1
    This should be 0-99 not 0-100, shouldn't it? Commented Mar 29, 2023 at 4:06
  • yes 0-99 indeed Commented Jun 1, 2023 at 12:46

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.