Skip to content

Instantly share code, notes, and snippets.

@DoguD
Created September 28, 2022 09:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DoguD/be9013b699af89827b2cccea115e3d51 to your computer and use it in GitHub Desktop.
Save DoguD/be9013b699af89827b2cccea115e3d51 to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: MIT
/**
A simple Solidity smart contract which generates a random number between 0 and the desired max number.
Uses two functions to generate the random number:
- First "prepareRandom" should be called. The function will set the "preparationBlockNumber" to the current block number.
- Second "roll" should be called to generate the number. The function generates a random number using the blockhash of the block when "prepareRandom" has been called. This way, as the blockhash of the block can't be know before the "prepareRandom" transaction goes thorugh,
the result of the roll can't be predicted and thus manipulated.
How many times the roll has been called and all the previous results are recorded in the blockchain.
*/
pragma solidity ^0.8.0;
contract RandomNumberDraw {
address public manager;
// Result varibles
uint256[] public winnerNumbers;
uint256 public rollCount;
// Random Variables
uint256 public preparationBlockNumber;
bool public canCallRandom;
constructor() {
manager = msg.sender;
}
function prepareRandom() public onlyOwner {
/**
When called sets the preparation block number to the current block number.
*/
require(!canCallRandom, "Already prepared.");
preparationBlockNumber = block.number;
canCallRandom = true;
}
function random(uint256 maxNumber) public view returns (uint256) {
/**
Generates a random number between 0 and maxNumber. Uses current block difficulty, timestamp, caller address, and the blockhash of the block when prepareRandom has been called.
Although the output of this function can be precalculated, the manager not knowing the blockhash of the block they called "prepareRandom" makes the system fair.
*/
return
uint256(
keccak256(
abi.encodePacked(
blockhash(preparationBlockNumber),
msg.sender
)
)
) % maxNumber;
}
function roll(uint256 maxNumber) public onlyOwner {
require(
canCallRandom,
"You need to prepare the random before calling it."
);
canCallRandom = false;
winnerNumbers.push(random(maxNumber));
rollCount++;
}
// Modifiers
modifier onlyOwner() {
require(msg.sender == manager);
_;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment