PRNG

Description:

Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "src/PRNG.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

import "./common/CRC32.sol";
import {IPRNG} from "./common/interfaces/IPRNG.sol";

/// @title PRNG
/// @notice A contract that provides pseudo-random number generation based on signatures
/// @dev Inherits from CRC32 for hash calculation. Uses a combination of keccak256 and CRC32
/// to generate random numbers within a specified range
contract PRNG is CRC32, IPRNG {
    /// @notice Base points for percentage calculations (100.00%)
    uint256 public constant BASE_POINTS = 10000;

    /// @notice Maximum CRC32 hash value adjusted to prevent modulo bias
    /// @dev Calculated as the largest multiple of BASE_POINTS that fits in uint32
    uint32 public constant MAX_CRC32_HASH_VALUE =
        uint32(type(uint32).max - (type(uint32).max % BASE_POINTS));

    /// @notice Generates a pseudo-random number between 0 and BASE_POINTS
    /// @dev Uses signature as initial entropy, then applies keccak256 and CRC32
    /// repeatedly until a value below MAX_CRC32_HASH_VALUE is found to avoid modulo bias
    /// @param signature The input signature bytes to use as entropy source
    /// @return A pseudo-random number between 0 and BASE_POINTS (0-10000)
    function _rng(bytes calldata signature) internal view returns (uint32) {
        bytes32 hashVal = keccak256(signature);
        uint32 hashNum = crc32(hashVal);

        // Loop until we get a value below MAX_CRC32_HASH_VALUE (to avoid modulo bias)
        while (hashNum >= MAX_CRC32_HASH_VALUE) {
            hashVal = keccak256(abi.encodePacked(hashVal));
            hashNum = crc32(hashVal);
        }

        return uint32(hashNum % BASE_POINTS);
    }

    function rng(bytes calldata signature) public view returns (uint32) {
        return _rng(signature);
    }
}
"
    },
    "src/common/CRC32.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

/**
 * @title CRC32 Hash Calculator
 * @dev Implements the CRC-32 (Cyclic Redundancy Check) algorithm as defined by ISO-HDLC, IEEE 802.3, and others.
 *
 * ref: https://gist.github.com/kbhokray/683f4260f9c13a767fcfdac2ac3ee188
 * ref: https://reveng.sourceforge.io/crc-catalogue/all.htm#crc.cat.crc-32-iso-hdlc
 *
 * check online:
 * https://www.browserling.com/tools/crc32-hash
 * https://crccalc.com/?crc=test&method=&datatype=ascii&outtype=hex
 *
 * The CRC-32 ISO-HDLC algorithm uses the following parameters:
 * - Width: 32 bits
 * - Polynomial: 0x04C11DB7 (expressed in the standard form used in specifications)
 * - Initial value: 0xFFFFFFFF
 * - Final XOR: 0xFFFFFFFF
 * - Reflect input: true (bits are processed LSB first)
 * - Reflect output: true (the final value is bit-reflected)
 *
 * Note on Polynomial Representation:
 * While the standard specification defines the polynomial as 0x04C11DB7, this implementation
 * uses 0x1DB710640. This discrepancy is due to implementation details in the table-based algorithm:
 *
 * 1. The standard polynomial (0x04C11DB7) gets bit-reflected to 0xEDB88320 for LSB-first processing
 * 2. For the table-driven implementation, we left-shift this reflected polynomial by 1 bit, resulting in 0x1DB710640
 *
 * This transformation is purely an optimization for the lookup table approach but produces
 * mathematically equivalent results to the standard algorithm.
 */
contract CRC32 {
    /**
     * @dev The CRC-32 polynomial used in the lookup table calculation.
     * This is NOT the canonical form (0x04C11DB7) from the spec, but rather:
     * - The bit-reflected value (0xEDB88320) left-shifted by 1 bit
     * - This transformation is required for the right-shift table-based implementation
     */
    uint256 private constant CRC_POLYNOMIAL = 0x1DB710640;

    /**
     * @dev Lookup table for fast CRC calculation.
     * Each entry represents the CRC value for a specific byte pattern.
     * These values are pre-computed based on CRC_POLYNOMIAL = 0x1DB710640
     */
    uint256[256] public crcTable = [
        0x00000000,
        0x77073096,
        0xEE0E612C,
        0x990951BA,
        0x076DC419,
        0x706AF48F,
        0xE963A535,
        0x9E6495A3,
        0x0EDB8832,
        0x79DCB8A4,
        0xE0D5E91E,
        0x97D2D988,
        0x09B64C2B,
        0x7EB17CBD,
        0xE7B82D07,
        0x90BF1D91,
        0x1DB71064,
        0x6AB020F2,
        0xF3B97148,
        0x84BE41DE,
        0x1ADAD47D,
        0x6DDDE4EB,
        0xF4D4B551,
        0x83D385C7,
        0x136C9856,
        0x646BA8C0,
        0xFD62F97A,
        0x8A65C9EC,
        0x14015C4F,
        0x63066CD9,
        0xFA0F3D63,
        0x8D080DF5,
        0x3B6E20C8,
        0x4C69105E,
        0xD56041E4,
        0xA2677172,
        0x3C03E4D1,
        0x4B04D447,
        0xD20D85FD,
        0xA50AB56B,
        0x35B5A8FA,
        0x42B2986C,
        0xDBBBC9D6,
        0xACBCF940,
        0x32D86CE3,
        0x45DF5C75,
        0xDCD60DCF,
        0xABD13D59,
        0x26D930AC,
        0x51DE003A,
        0xC8D75180,
        0xBFD06116,
        0x21B4F4B5,
        0x56B3C423,
        0xCFBA9599,
        0xB8BDA50F,
        0x2802B89E,
        0x5F058808,
        0xC60CD9B2,
        0xB10BE924,
        0x2F6F7C87,
        0x58684C11,
        0xC1611DAB,
        0xB6662D3D,
        0x76DC4190,
        0x01DB7106,
        0x98D220BC,
        0xEFD5102A,
        0x71B18589,
        0x06B6B51F,
        0x9FBFE4A5,
        0xE8B8D433,
        0x7807C9A2,
        0x0F00F934,
        0x9609A88E,
        0xE10E9818,
        0x7F6A0DBB,
        0x086D3D2D,
        0x91646C97,
        0xE6635C01,
        0x6B6B51F4,
        0x1C6C6162,
        0x856530D8,
        0xF262004E,
        0x6C0695ED,
        0x1B01A57B,
        0x8208F4C1,
        0xF50FC457,
        0x65B0D9C6,
        0x12B7E950,
        0x8BBEB8EA,
        0xFCB9887C,
        0x62DD1DDF,
        0x15DA2D49,
        0x8CD37CF3,
        0xFBD44C65,
        0x4DB26158,
        0x3AB551CE,
        0xA3BC0074,
        0xD4BB30E2,
        0x4ADFA541,
        0x3DD895D7,
        0xA4D1C46D,
        0xD3D6F4FB,
        0x4369E96A,
        0x346ED9FC,
        0xAD678846,
        0xDA60B8D0,
        0x44042D73,
        0x33031DE5,
        0xAA0A4C5F,
        0xDD0D7CC9,
        0x5005713C,
        0x270241AA,
        0xBE0B1010,
        0xC90C2086,
        0x5768B525,
        0x206F85B3,
        0xB966D409,
        0xCE61E49F,
        0x5EDEF90E,
        0x29D9C998,
        0xB0D09822,
        0xC7D7A8B4,
        0x59B33D17,
        0x2EB40D81,
        0xB7BD5C3B,
        0xC0BA6CAD,
        0xEDB88320,
        0x9ABFB3B6,
        0x03B6E20C,
        0x74B1D29A,
        0xEAD54739,
        0x9DD277AF,
        0x04DB2615,
        0x73DC1683,
        0xE3630B12,
        0x94643B84,
        0x0D6D6A3E,
        0x7A6A5AA8,
        0xE40ECF0B,
        0x9309FF9D,
        0x0A00AE27,
        0x7D079EB1,
        0xF00F9344,
        0x8708A3D2,
        0x1E01F268,
        0x6906C2FE,
        0xF762575D,
        0x806567CB,
        0x196C3671,
        0x6E6B06E7,
        0xFED41B76,
        0x89D32BE0,
        0x10DA7A5A,
        0x67DD4ACC,
        0xF9B9DF6F,
        0x8EBEEFF9,
        0x17B7BE43,
        0x60B08ED5,
        0xD6D6A3E8,
        0xA1D1937E,
        0x38D8C2C4,
        0x4FDFF252,
        0xD1BB67F1,
        0xA6BC5767,
        0x3FB506DD,
        0x48B2364B,
        0xD80D2BDA,
        0xAF0A1B4C,
        0x36034AF6,
        0x41047A60,
        0xDF60EFC3,
        0xA867DF55,
        0x316E8EEF,
        0x4669BE79,
        0xCB61B38C,
        0xBC66831A,
        0x256FD2A0,
        0x5268E236,
        0xCC0C7795,
        0xBB0B4703,
        0x220216B9,
        0x5505262F,
        0xC5BA3BBE,
        0xB2BD0B28,
        0x2BB45A92,
        0x5CB36A04,
        0xC2D7FFA7,
        0xB5D0CF31,
        0x2CD99E8B,
        0x5BDEAE1D,
        0x9B64C2B0,
        0xEC63F226,
        0x756AA39C,
        0x026D930A,
        0x9C0906A9,
        0xEB0E363F,
        0x72076785,
        0x05005713,
        0x95BF4A82,
        0xE2B87A14,
        0x7BB12BAE,
        0x0CB61B38,
        0x92D28E9B,
        0xE5D5BE0D,
        0x7CDCEFB7,
        0x0BDBDF21,
        0x86D3D2D4,
        0xF1D4E242,
        0x68DDB3F8,
        0x1FDA836E,
        0x81BE16CD,
        0xF6B9265B,
        0x6FB077E1,
        0x18B74777,
        0x88085AE6,
        0xFF0F6A70,
        0x66063BCA,
        0x11010B5C,
        0x8F659EFF,
        0xF862AE69,
        0x616BFFD3,
        0x166CCF45,
        0xA00AE278,
        0xD70DD2EE,
        0x4E048354,
        0x3903B3C2,
        0xA7672661,
        0xD06016F7,
        0x4969474D,
        0x3E6E77DB,
        0xAED16A4A,
        0xD9D65ADC,
        0x40DF0B66,
        0x37D83BF0,
        0xA9BCAE53,
        0xDEBB9EC5,
        0x47B2CF7F,
        0x30B5FFE9,
        0xBDBDF21C,
        0xCABAC28A,
        0x53B39330,
        0x24B4A3A6,
        0xBAD03605,
        0xCDD70693,
        0x54DE5729,
        0x23D967BF,
        0xB3667A2E,
        0xC4614AB8,
        0x5D681B02,
        0x2A6F2B94,
        0xB40BBE37,
        0xC30C8EA1,
        0x5A05DF1B,
        0x2D02EF8D
    ];

    /**
     * @dev Calculate CRC32 hash of a byte array.
     * This follows the ISO-HDLC standard for CRC-32 calculations.
     *
     * @param data The input byte array to calculate the CRC32 hash for
     * @return The 32-bit CRC value as a uint32
     */
    function crc32(bytes calldata data) public view returns (uint32) {
        unchecked {
            // Initialize CRC with all 1's (0xFFFFFFFF) as per the standard
            uint256 crc = 0xFFFFFFFF;

            // Process each byte in the input data
            for (uint256 i = 0; i < data.length; i++) {
                uint8 b = uint8(data[i]);

                // XOR the low byte of the current CRC with the input byte
                // Use this as an index into the lookup table
                // XOR the table value with the shifted CRC
                crc = (crc >> 8) ^ crcTable[(crc ^ uint256(b)) & 0xFF];
            }

            // Final XOR with all 1's (0xFFFFFFFF) as per the standard
            // and conversion to uint32 (which is the standard CRC-32 width)
            return uint32(crc ^ 0xFFFFFFFF);
        }
    }

    function crc32(bytes32 sigHash) public view returns (uint32) {
        unchecked {
            uint256 crc = 0xFFFFFFFF;

            // Process each byte in the bytes32 value directly
            for (uint256 i = 0; i < 32; i++) {
                // Extract byte at position i
                uint8 b = uint8(sigHash[i]);
                crc = (crc >> 8) ^ crcTable[(crc ^ uint256(b)) & 0xFF];
            }

            return uint32(crc ^ 0xFFFFFFFF);
        }
    }

    /**
     * @dev Calculate CRC32 hash of a string.
     * This is a convenience function that converts the string to bytes first.
     *
     * @param input The input string to calculate the CRC32 hash for
     * @return The 32-bit CRC value as a uint32
     */
    function crc32(string calldata input) public view returns (uint32) {
        return crc32(bytes(input));
    }
}
"
    },
    "src/common/interfaces/IPRNG.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

/// @title IPRNG
/// @notice Interface for the PRNG contract that provides pseudo-random number generation
interface IPRNG {
    /// @notice Base points for percentage calculations (100.00%)
    function BASE_POINTS() external view returns (uint256);

    /// @notice Maximum CRC32 hash value adjusted to prevent modulo bias
    function MAX_CRC32_HASH_VALUE() external view returns (uint32);

    /// @notice Generates a pseudo-random number between 0 and BASE_POINTS
    /// @param signature The input signature bytes to use as entropy source
    /// @return A pseudo-random number between 0 and BASE_POINTS (0-10000)
    function rng(bytes calldata signature) external view returns (uint32);
}
"
    }
  },
  "settings": {
    "remappings": [
      "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
      "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
      "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
      "forge-std/=lib/forge-std/src/",
      "halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
      "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
      "openzeppelin-contracts/=lib/openzeppelin-contracts/"
    ],
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "metadata": {
      "useLiteralContent": false,
      "bytecodeHash": "ipfs",
      "appendCBOR": true
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "evmVersion": "prague",
    "viaIR": true
  }
}}

Tags:
Proxy, Upgradeable, Factory|addr:0x5bd8a04bca6d71ff51fe81aa8d38e680d68fa689|verified:true|block:23633650|tx:0xda3bb7303ad4ffd69188c93c08e0890237a3d809aff6e60c4c70e43adfea29d8|first_check:1761244854

Submitted on: 2025-10-23 20:40:57

Comments

Log in to comment.

No comments yet.