// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Library for accessing block hashes way beyond the 256-block limit. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/BlockHashLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Blockhash.sol) library BlockHashLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Address of the EIP-2935 history storage contract. /// See: https://eips.ethereum.org/EIPS/eip-2935 address internal constant HISTORY_STORAGE_ADDRESS = 0x0000F90827F1C53a10cb7A02335B175320002935; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Retrieves the block hash for any historical block within the supported range. /// The function gracefully handles future blocks and blocks beyond the history window by returning zero, /// consistent with the EVM's native `BLOCKHASH` behavior. function blockHash(uint256 blockNumber) internal view returns (bytes32 result) { unchecked { // If `blockNumber + 256` overflows: // - Typical chain height (`block.number > 255`) -> `staticcall` -> 0. // - Very early chain (`block.number <= 255`) -> `blockhash` -> 0. if (block.number <= blockNumber + 256) return blockhash(blockNumber); } /// @solidity memory-safe-assembly assembly { mstore(0x20, blockNumber) mstore(0x00, 0) pop(staticcall(gas(), HISTORY_STORAGE_ADDRESS, 0x20, 0x20, 0x00, 0x20)) result := mload(0x00) } } }