As @Greg Scullard notes,
HIP-351
proposed a new system contract which includes
a precompiled function that generates pseudorandom numbers.
To use this within solidity code,
you need an address plus an interface,
both of which are defined in HIP-351:
Address: 0x169
Solidity interface:
interface IPrngSystemContract {
function getPseudorandomSeed() external returns (bytes32);
}
To use it, simply initialise an instance, we'll name it PrngSystemContract
:
IPrngSystemContract constant PrngSystemContract =
IPrngSystemContract(address(0x169));
Then subsequently invoke its getPseudorandomSeed
function,
which will return a pseudorandom bytes32
,
which you can then use in your smart contract's logic.
Here's an example smart contract implementation which
does what was described above.
In addition, it also uses a type conversion and modulo arithmetic
choose a random number between a specified range.
After generating the random number,
it simply emits that result in an event.
You should substitute the emit event with the logic you want.
Try this out on Remix
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.18;
interface IPrngSystemContract {
// Generates a 256-bit pseudorandom seed using the first 256-bits of running hash of n-3 transaction record.
// Users can generate a pseudorandom number in a specified range using the seed by (integer value of seed % range)
function getPseudorandomSeed() external returns (bytes32);
}
contract Prng {
IPrngSystemContract constant PrngSystemContract =
IPrngSystemContract(address(0x169));
event RandomResult(bytes32 randomBytes, uint256 num);
function getPseudorandomSeed() public returns (bytes32 randomBytes) {
randomBytes = PrngSystemContract.getPseudorandomSeed();
}
// Return value in the range [lo, hi)
function getPseudorandomNumber(uint256 lo, uint256 hi) external returns (uint256 num) {
bytes32 randomBytes = getPseudorandomSeed();
num = uint256(randomBytes);
num = lo + (num % (hi - lo));
emit RandomResult(randomBytes, num);
}
}