PRNG.sol 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. // SPDX-License-Identifier: Apache 2
  2. pragma solidity ^0.8.0;
  3. /// @title PRNG Contract
  4. /// @notice A contract for pseudorandom number generation and related utility functions
  5. /// @dev This PRNG contract is designed to work with Pyth Entropy as the seed source.
  6. /// Pyth Entropy provides secure, rapid random number generation for blockchain applications,
  7. /// enabling responsive UX for NFT mints, games, and other use cases requiring randomness.
  8. contract PRNG {
  9. bytes32 private seed;
  10. uint256 private nonce;
  11. /// @notice Initialize the PRNG with a seed
  12. /// @param _seed The Pyth Entropy seed (bytes32)
  13. constructor(bytes32 _seed) {
  14. seed = _seed;
  15. nonce = 0;
  16. }
  17. /// @notice Set a new seed and reset the nonce
  18. /// @param _newSeed The new seed (bytes32)
  19. function setSeed(bytes32 _newSeed) internal {
  20. seed = _newSeed;
  21. nonce = 0;
  22. }
  23. /// @notice Generate the next random bytes32 value and update the state
  24. /// @return The next random bytes32 value
  25. function nextBytes32() internal returns (bytes32) {
  26. bytes32 result = keccak256(abi.encode(seed, nonce));
  27. nonce++;
  28. return result;
  29. }
  30. /// @notice Generate a random uint256 value
  31. /// @return A random uint256 value
  32. function randUint() internal returns (uint256) {
  33. return uint256(nextBytes32());
  34. }
  35. /// @notice Generate a random uint64 value
  36. /// @return A random uint64 value
  37. function randUint64() internal returns (uint64) {
  38. return uint64(uint256(nextBytes32()));
  39. }
  40. /// @notice Generate a random uint256 value within a specified range
  41. /// @param min The minimum value (inclusive)
  42. /// @param max The maximum value (exclusive)
  43. /// @return A random uint256 value between min and max
  44. /// @dev The result is uniformly distributed between min and max, with a slight bias toward lower numbers.
  45. /// @dev This bias is insignificant as long as (max - min) << MAX_UINT256.
  46. function randUintRange(
  47. uint256 min,
  48. uint256 max
  49. ) internal returns (uint256) {
  50. require(max > min, "Max must be greater than min");
  51. return (randUint() % (max - min)) + min;
  52. }
  53. /// @notice Generate a random permutation of a sequence
  54. /// @param length The length of the sequence to permute
  55. /// @return A randomly permuted array of uint256 values
  56. function randomPermutation(
  57. uint256 length
  58. ) internal returns (uint256[] memory) {
  59. uint256[] memory permutation = new uint256[](length);
  60. for (uint256 i = 0; i < length; i++) {
  61. permutation[i] = i;
  62. }
  63. for (uint256 i = 0; i < length; i++) {
  64. uint256 j = i + (randUint() % (length - i));
  65. (permutation[i], permutation[j]) = (permutation[j], permutation[i]);
  66. }
  67. return permutation;
  68. }
  69. }