{
  "language": "Solidity",
  "sources": {
    "lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (interfaces/draft-IERC6093.sol)\n\npragma solidity >=0.8.4;\n\n/**\n * @dev Standard ERC-20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\n */\ninterface IERC20Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC20InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC20InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     * @param allowance Amount of tokens a `spender` is allowed to operate with.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC20InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC-721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\n */\ninterface IERC721Errors {\n    /**\n     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-721.\n     * Used in balance queries.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721InvalidOwner(address owner);\n\n    /**\n     * @dev Indicates a `tokenId` whose `owner` is the zero address.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721NonexistentToken(uint256 tokenId);\n\n    /**\n     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param tokenId Identifier number of a token.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC721InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC721InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC721InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC-1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\n */\ninterface IERC1155Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC1155InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC1155InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC1155MissingApprovalForAll(address operator, address owner);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC1155InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC1155InvalidOperator(address operator);\n\n    /**\n     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n     * Used in batch transfers.\n     * @param idsLength Length of the array of token identifiers\n     * @param valuesLength Length of the array of token amounts\n     */\n    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n"
    },
    "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC20Metadata} from \"./extensions/IERC20Metadata.sol\";\nimport {Context} from \"../../utils/Context.sol\";\nimport {IERC20Errors} from \"../../interfaces/draft-IERC6093.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC-20\n * applications.\n */\nabstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {\n    mapping(address account => uint256) private _balances;\n\n    mapping(address account => mapping(address spender => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * Both values are immutable: they can only be set once during construction.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the default value returned by this function, unless\n     * it's overridden.\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual returns (uint8) {\n        return 18;\n    }\n\n    /// @inheritdoc IERC20\n    function totalSupply() public view virtual returns (uint256) {\n        return _totalSupply;\n    }\n\n    /// @inheritdoc IERC20\n    function balanceOf(address account) public view virtual returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - the caller must have a balance of at least `value`.\n     */\n    function transfer(address to, uint256 value) public virtual returns (bool) {\n        address owner = _msgSender();\n        _transfer(owner, to, value);\n        return true;\n    }\n\n    /// @inheritdoc IERC20\n    function allowance(address owner, address spender) public view virtual returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 value) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, value);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Skips emitting an {Approval} event indicating an allowance update. This is not\n     * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].\n     *\n     * NOTE: Does not update the allowance if the current allowance\n     * is the maximum `uint256`.\n     *\n     * Requirements:\n     *\n     * - `from` and `to` cannot be the zero address.\n     * - `from` must have a balance of at least `value`.\n     * - the caller must have allowance for ``from``'s tokens of at least\n     * `value`.\n     */\n    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(from, spender, value);\n        _transfer(from, to, value);\n        return true;\n    }\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead.\n     */\n    function _transfer(address from, address to, uint256 value) internal {\n        if (from == address(0)) {\n            revert ERC20InvalidSender(address(0));\n        }\n        if (to == address(0)) {\n            revert ERC20InvalidReceiver(address(0));\n        }\n        _update(from, to, value);\n    }\n\n    /**\n     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`\n     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding\n     * this function.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _update(address from, address to, uint256 value) internal virtual {\n        if (from == address(0)) {\n            // Overflow check required: The rest of the code assumes that totalSupply never overflows\n            _totalSupply += value;\n        } else {\n            uint256 fromBalance = _balances[from];\n            if (fromBalance < value) {\n                revert ERC20InsufficientBalance(from, fromBalance, value);\n            }\n            unchecked {\n                // Overflow not possible: value <= fromBalance <= totalSupply.\n                _balances[from] = fromBalance - value;\n            }\n        }\n\n        if (to == address(0)) {\n            unchecked {\n                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.\n                _totalSupply -= value;\n            }\n        } else {\n            unchecked {\n                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.\n                _balances[to] += value;\n            }\n        }\n\n        emit Transfer(from, to, value);\n    }\n\n    /**\n     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).\n     * Relies on the `_update` mechanism\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead.\n     */\n    function _mint(address account, uint256 value) internal {\n        if (account == address(0)) {\n            revert ERC20InvalidReceiver(address(0));\n        }\n        _update(address(0), account, value);\n    }\n\n    /**\n     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.\n     * Relies on the `_update` mechanism.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead\n     */\n    function _burn(address account, uint256 value) internal {\n        if (account == address(0)) {\n            revert ERC20InvalidSender(address(0));\n        }\n        _update(account, address(0), value);\n    }\n\n    /**\n     * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     *\n     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\n     */\n    function _approve(address owner, address spender, uint256 value) internal {\n        _approve(owner, spender, value, true);\n    }\n\n    /**\n     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.\n     *\n     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by\n     * `_spendAllowance` during the `transferFrom` operation sets the flag to false. This saves gas by not emitting any\n     * `Approval` event during `transferFrom` operations.\n     *\n     * Anyone who wishes to continue emitting `Approval` events on the `transferFrom` operation can force the flag to\n     * true using the following override:\n     *\n     * ```solidity\n     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {\n     *     super._approve(owner, spender, value, true);\n     * }\n     * ```\n     *\n     * Requirements are the same as {_approve}.\n     */\n    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {\n        if (owner == address(0)) {\n            revert ERC20InvalidApprover(address(0));\n        }\n        if (spender == address(0)) {\n            revert ERC20InvalidSpender(address(0));\n        }\n        _allowances[owner][spender] = value;\n        if (emitEvent) {\n            emit Approval(owner, spender, value);\n        }\n    }\n\n    /**\n     * @dev Updates `owner`'s allowance for `spender` based on spent `value`.\n     *\n     * Does not update the allowance value in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Does not emit an {Approval} event.\n     */\n    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance < type(uint256).max) {\n            if (currentAllowance < value) {\n                revert ERC20InsufficientAllowance(spender, currentAllowance, value);\n            }\n            unchecked {\n                _approve(owner, spender, currentAllowance - value, false);\n            }\n        }\n    }\n}\n"
    },
    "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"
    },
    "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
    },
    "lib/openzeppelin-contracts/contracts/utils/Context.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"
    },
    "lib/openzeppelin-contracts/contracts/utils/Panic.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Helper library for emitting standardized panic codes.\n *\n * ```solidity\n * contract Example {\n *      using Panic for uint256;\n *\n *      // Use any of the declared internal constants\n *      function foo() { Panic.GENERIC.panic(); }\n *\n *      // Alternatively\n *      function foo() { Panic.panic(Panic.GENERIC); }\n * }\n * ```\n *\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\n *\n * _Available since v5.1._\n */\n// slither-disable-next-line unused-state\nlibrary Panic {\n    /// @dev generic / unspecified error\n    uint256 internal constant GENERIC = 0x00;\n    /// @dev used by the assert() builtin\n    uint256 internal constant ASSERT = 0x01;\n    /// @dev arithmetic underflow or overflow\n    uint256 internal constant UNDER_OVERFLOW = 0x11;\n    /// @dev division or modulo by zero\n    uint256 internal constant DIVISION_BY_ZERO = 0x12;\n    /// @dev enum conversion error\n    uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\n    /// @dev invalid encoding in storage\n    uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\n    /// @dev empty array pop\n    uint256 internal constant EMPTY_ARRAY_POP = 0x31;\n    /// @dev array out of bounds access\n    uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\n    /// @dev resource error (too large allocation or too large array)\n    uint256 internal constant RESOURCE_ERROR = 0x41;\n    /// @dev calling invalid internal function\n    uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\n\n    /// @dev Reverts with a panic code. Recommended to use with\n    /// the internal constants with predefined codes.\n    function panic(uint256 code) internal pure {\n        assembly (\"memory-safe\") {\n            mstore(0x00, 0x4e487b71)\n            mstore(0x20, code)\n            revert(0x1c, 0x24)\n        }\n    }\n}\n"
    },
    "lib/openzeppelin-contracts/contracts/utils/ReentrancyGuardTransient.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (utils/ReentrancyGuardTransient.sol)\n\npragma solidity ^0.8.24;\n\nimport {TransientSlot} from \"./TransientSlot.sol\";\n\n/**\n * @dev Variant of {ReentrancyGuard} that uses transient storage.\n *\n * NOTE: This variant only works on networks where EIP-1153 is available.\n *\n * _Available since v5.1._\n *\n * @custom:stateless\n */\nabstract contract ReentrancyGuardTransient {\n    using TransientSlot for *;\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant REENTRANCY_GUARD_STORAGE =\n        0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    /**\n     * @dev A `view` only version of {nonReentrant}. Use to block view functions\n     * from being called, preventing reading from inconsistent contract state.\n     *\n     * CAUTION: This is a \"view\" modifier and does not change the reentrancy\n     * status. Use it only on view functions. For payable or non-payable functions,\n     * use the standard {nonReentrant} modifier instead.\n     */\n    modifier nonReentrantView() {\n        _nonReentrantBeforeView();\n        _;\n    }\n\n    function _nonReentrantBeforeView() private view {\n        if (_reentrancyGuardEntered()) {\n            revert ReentrancyGuardReentrantCall();\n        }\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, REENTRANCY_GUARD_STORAGE.asBoolean().tload() will be false\n        _nonReentrantBeforeView();\n\n        // Any calls to nonReentrant after this point will fail\n        _reentrancyGuardStorageSlot().asBoolean().tstore(true);\n    }\n\n    function _nonReentrantAfter() private {\n        _reentrancyGuardStorageSlot().asBoolean().tstore(false);\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _reentrancyGuardStorageSlot().asBoolean().tload();\n    }\n\n    function _reentrancyGuardStorageSlot() internal pure virtual returns (bytes32) {\n        return REENTRANCY_GUARD_STORAGE;\n    }\n}\n"
    },
    "lib/openzeppelin-contracts/contracts/utils/TransientSlot.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/TransientSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/TransientSlot.js.\n\npragma solidity ^0.8.24;\n\n/**\n * @dev Library for reading and writing value-types to specific transient storage slots.\n *\n * Transient slots are often used to store temporary values that are removed after the current transaction.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n *  * Example reading and writing values using transient storage:\n * ```solidity\n * contract Lock {\n *     using TransientSlot for *;\n *\n *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n *     bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;\n *\n *     modifier locked() {\n *         require(!_LOCK_SLOT.asBoolean().tload());\n *\n *         _LOCK_SLOT.asBoolean().tstore(true);\n *         _;\n *         _LOCK_SLOT.asBoolean().tstore(false);\n *     }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary TransientSlot {\n    /**\n     * @dev UDVT that represents a slot holding an address.\n     */\n    type AddressSlot is bytes32;\n\n    /**\n     * @dev Cast an arbitrary slot to a AddressSlot.\n     */\n    function asAddress(bytes32 slot) internal pure returns (AddressSlot) {\n        return AddressSlot.wrap(slot);\n    }\n\n    /**\n     * @dev UDVT that represents a slot holding a bool.\n     */\n    type BooleanSlot is bytes32;\n\n    /**\n     * @dev Cast an arbitrary slot to a BooleanSlot.\n     */\n    function asBoolean(bytes32 slot) internal pure returns (BooleanSlot) {\n        return BooleanSlot.wrap(slot);\n    }\n\n    /**\n     * @dev UDVT that represents a slot holding a bytes32.\n     */\n    type Bytes32Slot is bytes32;\n\n    /**\n     * @dev Cast an arbitrary slot to a Bytes32Slot.\n     */\n    function asBytes32(bytes32 slot) internal pure returns (Bytes32Slot) {\n        return Bytes32Slot.wrap(slot);\n    }\n\n    /**\n     * @dev UDVT that represents a slot holding a uint256.\n     */\n    type Uint256Slot is bytes32;\n\n    /**\n     * @dev Cast an arbitrary slot to a Uint256Slot.\n     */\n    function asUint256(bytes32 slot) internal pure returns (Uint256Slot) {\n        return Uint256Slot.wrap(slot);\n    }\n\n    /**\n     * @dev UDVT that represents a slot holding a int256.\n     */\n    type Int256Slot is bytes32;\n\n    /**\n     * @dev Cast an arbitrary slot to a Int256Slot.\n     */\n    function asInt256(bytes32 slot) internal pure returns (Int256Slot) {\n        return Int256Slot.wrap(slot);\n    }\n\n    /**\n     * @dev Load the value held at location `slot` in transient storage.\n     */\n    function tload(AddressSlot slot) internal view returns (address value) {\n        assembly (\"memory-safe\") {\n            value := tload(slot)\n        }\n    }\n\n    /**\n     * @dev Store `value` at location `slot` in transient storage.\n     */\n    function tstore(AddressSlot slot, address value) internal {\n        assembly (\"memory-safe\") {\n            tstore(slot, value)\n        }\n    }\n\n    /**\n     * @dev Load the value held at location `slot` in transient storage.\n     */\n    function tload(BooleanSlot slot) internal view returns (bool value) {\n        assembly (\"memory-safe\") {\n            value := tload(slot)\n        }\n    }\n\n    /**\n     * @dev Store `value` at location `slot` in transient storage.\n     */\n    function tstore(BooleanSlot slot, bool value) internal {\n        assembly (\"memory-safe\") {\n            tstore(slot, value)\n        }\n    }\n\n    /**\n     * @dev Load the value held at location `slot` in transient storage.\n     */\n    function tload(Bytes32Slot slot) internal view returns (bytes32 value) {\n        assembly (\"memory-safe\") {\n            value := tload(slot)\n        }\n    }\n\n    /**\n     * @dev Store `value` at location `slot` in transient storage.\n     */\n    function tstore(Bytes32Slot slot, bytes32 value) internal {\n        assembly (\"memory-safe\") {\n            tstore(slot, value)\n        }\n    }\n\n    /**\n     * @dev Load the value held at location `slot` in transient storage.\n     */\n    function tload(Uint256Slot slot) internal view returns (uint256 value) {\n        assembly (\"memory-safe\") {\n            value := tload(slot)\n        }\n    }\n\n    /**\n     * @dev Store `value` at location `slot` in transient storage.\n     */\n    function tstore(Uint256Slot slot, uint256 value) internal {\n        assembly (\"memory-safe\") {\n            tstore(slot, value)\n        }\n    }\n\n    /**\n     * @dev Load the value held at location `slot` in transient storage.\n     */\n    function tload(Int256Slot slot) internal view returns (int256 value) {\n        assembly (\"memory-safe\") {\n            value := tload(slot)\n        }\n    }\n\n    /**\n     * @dev Store `value` at location `slot` in transient storage.\n     */\n    function tstore(Int256Slot slot, int256 value) internal {\n        assembly (\"memory-safe\") {\n            tstore(slot, value)\n        }\n    }\n}\n"
    },
    "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\nimport {Panic} from \"../Panic.sol\";\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Return the 512-bit addition of two uint256.\n     *\n     * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.\n     */\n    function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n        assembly (\"memory-safe\") {\n            low := add(a, b)\n            high := lt(low, a)\n        }\n    }\n\n    /**\n     * @dev Return the 512-bit multiplication of two uint256.\n     *\n     * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.\n     */\n    function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n        // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use\n        // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n        // variables such that product = high * 2²⁵⁶ + low.\n        assembly (\"memory-safe\") {\n            let mm := mulmod(a, b, not(0))\n            low := mul(a, b)\n            high := sub(sub(mm, low), lt(mm, low))\n        }\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a + b;\n            success = c >= a;\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a - b;\n            success = c <= a;\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a * b;\n            assembly (\"memory-safe\") {\n                // Only true when the multiplication doesn't overflow\n                // (c / a == b) || (a == 0)\n                success := or(eq(div(c, a), b), iszero(a))\n            }\n            // equivalent to: success ? c : 0\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            success = b > 0;\n            assembly (\"memory-safe\") {\n                // The `DIV` opcode returns zero when the denominator is 0.\n                result := div(a, b)\n            }\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            success = b > 0;\n            assembly (\"memory-safe\") {\n                // The `MOD` opcode returns zero when the denominator is 0.\n                result := mod(a, b)\n            }\n        }\n    }\n\n    /**\n     * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.\n     */\n    function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\n        (bool success, uint256 result) = tryAdd(a, b);\n        return ternary(success, result, type(uint256).max);\n    }\n\n    /**\n     * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\n     */\n    function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\n        (, uint256 result) = trySub(a, b);\n        return result;\n    }\n\n    /**\n     * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.\n     */\n    function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\n        (bool success, uint256 result) = tryMul(a, b);\n        return ternary(success, result, type(uint256).max);\n    }\n\n    /**\n     * @dev Branchless ternary evaluation for `condition ? a : b`. Gas costs are constant.\n     *\n     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n     * However, the compiler may optimize Solidity ternary operations (i.e. `condition ? a : b`) to only compute\n     * one branch when needed, making this function more expensive.\n     */\n    function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\n        unchecked {\n            // branchless ternary works because:\n            // b ^ (a ^ b) == a\n            // b ^ 0 == b\n            return b ^ ((a ^ b) * SafeCast.toUint(condition));\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return ternary(a > b, a, b);\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return ternary(a < b, a, b);\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        unchecked {\n            // (a + b) / 2 can overflow.\n            return (a & b) + (a ^ b) / 2;\n        }\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n\n        // The following calculation ensures accurate ceiling division without overflow.\n        // Since a is non-zero, (a - 1) / b will not overflow.\n        // The largest possible result occurs when (a - 1) / b is type(uint256).max,\n        // but the largest value we can obtain is type(uint256).max - 1, which happens\n        // when a = type(uint256).max and b = 1.\n        unchecked {\n            return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\n        }\n    }\n\n    /**\n     * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n     * denominator == 0.\n     *\n     * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            (uint256 high, uint256 low) = mul512(x, y);\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (high == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return low / denominator;\n            }\n\n            // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.\n            if (denominator <= high) {\n                Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\n            }\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [high low].\n            uint256 remainder;\n            assembly (\"memory-safe\") {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                high := sub(high, gt(remainder, low))\n                low := sub(low, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\n            assembly (\"memory-safe\") {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [high low] by twos.\n                low := div(low, twos)\n\n                // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from high into low.\n            low |= high * twos;\n\n            // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such\n            // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv ≡ 1 mod 2⁴.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n            // works in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶\n            inverse *= 2 - denominator * inverse; // inverse mod 2³²\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is\n            // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high\n            // is no longer required.\n            result = low * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\n    }\n\n    /**\n     * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\n     */\n    function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\n        unchecked {\n            (uint256 high, uint256 low) = mul512(x, y);\n            if (high >= 1 << n) {\n                Panic.panic(Panic.UNDER_OVERFLOW);\n            }\n            return (high << (256 - n)) | (low >> n);\n        }\n    }\n\n    /**\n     * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\n     */\n    function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\n        return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\n    }\n\n    /**\n     * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\n     *\n     * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\n     * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\n     *\n     * If the input value is not inversible, 0 is returned.\n     *\n     * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\n     * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\n     */\n    function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\n        unchecked {\n            if (n == 0) return 0;\n\n            // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\n            // Used to compute integers x and y such that: ax + ny = gcd(a, n).\n            // When the gcd is 1, then the inverse of a modulo n exists and it's x.\n            // ax + ny = 1\n            // ax = 1 + (-y)n\n            // ax ≡ 1 (mod n) # x is the inverse of a modulo n\n\n            // If the remainder is 0 the gcd is n right away.\n            uint256 remainder = a % n;\n            uint256 gcd = n;\n\n            // Therefore the initial coefficients are:\n            // ax + ny = gcd(a, n) = n\n            // 0a + 1n = n\n            int256 x = 0;\n            int256 y = 1;\n\n            while (remainder != 0) {\n                uint256 quotient = gcd / remainder;\n\n                (gcd, remainder) = (\n                    // The old remainder is the next gcd to try.\n                    remainder,\n                    // Compute the next remainder.\n                    // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\n                    // where gcd is at most n (capped to type(uint256).max)\n                    gcd - remainder * quotient\n                );\n\n                (x, y) = (\n                    // Increment the coefficient of a.\n                    y,\n                    // Decrement the coefficient of n.\n                    // Can overflow, but the result is casted to uint256 so that the\n                    // next value of y is \"wrapped around\" to a value between 0 and n - 1.\n                    x - y * int256(quotient)\n                );\n            }\n\n            if (gcd != 1) return 0; // No inverse exists.\n            return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\n        }\n    }\n\n    /**\n     * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\n     *\n     * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\n     * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that\n     * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\n     *\n     * NOTE: this function does NOT check that `p` is a prime greater than `2`.\n     */\n    function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\n        unchecked {\n            return Math.modExp(a, p - 2, p);\n        }\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\n     *\n     * Requirements:\n     * - modulus can't be zero\n     * - underlying staticcall to precompile must succeed\n     *\n     * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\n     * sure the chain you're using it on supports the precompiled contract for modular exponentiation\n     * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\n     * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\n     * interpreted as 0.\n     */\n    function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\n        (bool success, uint256 result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\n     * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\n     * to operate modulo 0 or if the underlying precompile reverted.\n     *\n     * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\n     * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\n     * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\n     * of a revert, but the result may be incorrectly interpreted as 0.\n     */\n    function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\n        if (m == 0) return (false, 0);\n        assembly (\"memory-safe\") {\n            let ptr := mload(0x40)\n            // | Offset    | Content    | Content (Hex)                                                      |\n            // |-----------|------------|--------------------------------------------------------------------|\n            // | 0x00:0x1f | size of b  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x20:0x3f | size of e  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x40:0x5f | size of m  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x60:0x7f | value of b | 0x<.............................................................b> |\n            // | 0x80:0x9f | value of e | 0x<.............................................................e> |\n            // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\n            mstore(ptr, 0x20)\n            mstore(add(ptr, 0x20), 0x20)\n            mstore(add(ptr, 0x40), 0x20)\n            mstore(add(ptr, 0x60), b)\n            mstore(add(ptr, 0x80), e)\n            mstore(add(ptr, 0xa0), m)\n\n            // Given the result < m, it's guaranteed to fit in 32 bytes,\n            // so we can use the memory scratch space located at offset 0.\n            success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\n            result := mload(0x00)\n        }\n    }\n\n    /**\n     * @dev Variant of {modExp} that supports inputs of arbitrary length.\n     */\n    function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\n        (bool success, bytes memory result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\n     */\n    function tryModExp(\n        bytes memory b,\n        bytes memory e,\n        bytes memory m\n    ) internal view returns (bool success, bytes memory result) {\n        if (_zeroBytes(m)) return (false, new bytes(0));\n\n        uint256 mLen = m.length;\n\n        // Encode call args in result and move the free memory pointer\n        result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\n\n        assembly (\"memory-safe\") {\n            let dataPtr := add(result, 0x20)\n            // Write result on top of args to avoid allocating extra memory.\n            success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\n            // Overwrite the length.\n            // result.length > returndatasize() is guaranteed because returndatasize() == m.length\n            mstore(result, mLen)\n            // Set the memory pointer after the returned data.\n            mstore(0x40, add(dataPtr, mLen))\n        }\n    }\n\n    /**\n     * @dev Returns whether the provided byte array is zero.\n     */\n    function _zeroBytes(bytes memory buffer) private pure returns (bool) {\n        uint256 chunk;\n        for (uint256 i = 0; i < buffer.length; i += 0x20) {\n            // See _unsafeReadBytesOffset from utils/Bytes.sol\n            assembly (\"memory-safe\") {\n                chunk := mload(add(add(buffer, 0x20), i))\n            }\n            if (chunk >> (8 * saturatingSub(i + 0x20, buffer.length)) != 0) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n     * towards zero.\n     *\n     * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\n     * using integer operations.\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        unchecked {\n            // Take care of easy edge cases when a == 0 or a == 1\n            if (a <= 1) {\n                return a;\n            }\n\n            // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a\n            // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\n            // the current value as `ε_n = | x_n - sqrt(a) |`.\n            //\n            // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\n            // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is\n            // bigger than any uint256.\n            //\n            // By noticing that\n            // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`\n            // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\n            // to the msb function.\n            uint256 aa = a;\n            uint256 xn = 1;\n\n            if (aa >= (1 << 128)) {\n                aa >>= 128;\n                xn <<= 64;\n            }\n            if (aa >= (1 << 64)) {\n                aa >>= 64;\n                xn <<= 32;\n            }\n            if (aa >= (1 << 32)) {\n                aa >>= 32;\n                xn <<= 16;\n            }\n            if (aa >= (1 << 16)) {\n                aa >>= 16;\n                xn <<= 8;\n            }\n            if (aa >= (1 << 8)) {\n                aa >>= 8;\n                xn <<= 4;\n            }\n            if (aa >= (1 << 4)) {\n                aa >>= 4;\n                xn <<= 2;\n            }\n            if (aa >= (1 << 2)) {\n                xn <<= 1;\n            }\n\n            // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).\n            //\n            // We can refine our estimation by noticing that the middle of that interval minimizes the error.\n            // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).\n            // This is going to be our x_0 (and ε_0)\n            xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)\n\n            // From here, Newton's method give us:\n            // x_{n+1} = (x_n + a / x_n) / 2\n            //\n            // One should note that:\n            // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a\n            //              = ((x_n² + a) / (2 * x_n))² - a\n            //              = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a\n            //              = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)\n            //              = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)\n            //              = (x_n² - a)² / (2 * x_n)²\n            //              = ((x_n² - a) / (2 * x_n))²\n            //              ≥ 0\n            // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n\n            //\n            // This gives us the proof of quadratic convergence of the sequence:\n            // ε_{n+1} = | x_{n+1} - sqrt(a) |\n            //         = | (x_n + a / x_n) / 2 - sqrt(a) |\n            //         = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |\n            //         = | (x_n - sqrt(a))² / (2 * x_n) |\n            //         = | ε_n² / (2 * x_n) |\n            //         = ε_n² / | (2 * x_n) |\n            //\n            // For the first iteration, we have a special case where x_0 is known:\n            // ε_1 = ε_0² / | (2 * x_0) |\n            //     ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))\n            //     ≤ 2**(2*e-4) / (3 * 2**(e-1))\n            //     ≤ 2**(e-3) / 3\n            //     ≤ 2**(e-3-log2(3))\n            //     ≤ 2**(e-4.5)\n            //\n            // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:\n            // ε_{n+1} = ε_n² / | (2 * x_n) |\n            //         ≤ (2**(e-k))² / (2 * 2**(e-1))\n            //         ≤ 2**(2*e-2*k) / 2**e\n            //         ≤ 2**(e-2*k)\n            xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5)  -- special case, see above\n            xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9)    -- general case with k = 4.5\n            xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18)   -- general case with k = 9\n            xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36)   -- general case with k = 18\n            xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72)   -- general case with k = 36\n            xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144)  -- general case with k = 72\n\n            // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision\n            // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\n            // sqrt(a) or sqrt(a) + 1.\n            return xn - SafeCast.toUint(xn > a / xn);\n        }\n    }\n\n    /**\n     * @dev Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 x) internal pure returns (uint256 r) {\n        // If value has upper 128 bits set, log2 result is at least 128\n        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n        // If upper 64 bits of 128-bit half set, add 64 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n        // If upper 32 bits of 64-bit half set, add 32 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n        // If upper 16 bits of 32-bit half set, add 16 to result\n        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n        // If upper 8 bits of 16-bit half set, add 8 to result\n        r |= SafeCast.toUint((x >> r) > 0xff) << 3;\n        // If upper 4 bits of 8-bit half set, add 4 to result\n        r |= SafeCast.toUint((x >> r) > 0xf) << 2;\n\n        // Shifts value right by the current result and use it as an index into this lookup table:\n        //\n        // | x (4 bits) |  index  | table[index] = MSB position |\n        // |------------|---------|-----------------------------|\n        // |    0000    |    0    |        table[0] = 0         |\n        // |    0001    |    1    |        table[1] = 0         |\n        // |    0010    |    2    |        table[2] = 1         |\n        // |    0011    |    3    |        table[3] = 1         |\n        // |    0100    |    4    |        table[4] = 2         |\n        // |    0101    |    5    |        table[5] = 2         |\n        // |    0110    |    6    |        table[6] = 2         |\n        // |    0111    |    7    |        table[7] = 2         |\n        // |    1000    |    8    |        table[8] = 3         |\n        // |    1001    |    9    |        table[9] = 3         |\n        // |    1010    |   10    |        table[10] = 3        |\n        // |    1011    |   11    |        table[11] = 3        |\n        // |    1100    |   12    |        table[12] = 3        |\n        // |    1101    |   13    |        table[13] = 3        |\n        // |    1110    |   14    |        table[14] = 3        |\n        // |    1111    |   15    |        table[15] = 3        |\n        //\n        // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the first 16 bytes (most significant half).\n        assembly (\"memory-safe\") {\n            r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 x) internal pure returns (uint256 r) {\n        // If value has upper 128 bits set, log2 result is at least 128\n        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n        // If upper 64 bits of 128-bit half set, add 64 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n        // If upper 32 bits of 64-bit half set, add 32 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n        // If upper 16 bits of 32-bit half set, add 16 to result\n        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n        // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\n        return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n\n    /**\n     * @dev Counts the number of leading zero bits in a uint256.\n     */\n    function clz(uint256 x) internal pure returns (uint256) {\n        return ternary(x == 0, 256, 255 - log2(x));\n    }\n}\n"
    },
    "lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeCast {\n    /**\n     * @dev Value doesn't fit in a uint of `bits` size.\n     */\n    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\n\n    /**\n     * @dev An int value doesn't fit in a uint of `bits` size.\n     */\n    error SafeCastOverflowedIntToUint(int256 value);\n\n    /**\n     * @dev Value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\n\n    /**\n     * @dev A uint value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedUintToInt(uint256 value);\n\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        if (value > type(uint248).max) {\n            revert SafeCastOverflowedUintDowncast(248, value);\n        }\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        if (value > type(uint240).max) {\n            revert SafeCastOverflowedUintDowncast(240, value);\n        }\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        if (value > type(uint232).max) {\n            revert SafeCastOverflowedUintDowncast(232, value);\n        }\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        if (value > type(uint224).max) {\n            revert SafeCastOverflowedUintDowncast(224, value);\n        }\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        if (value > type(uint216).max) {\n            revert SafeCastOverflowedUintDowncast(216, value);\n        }\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        if (value > type(uint208).max) {\n            revert SafeCastOverflowedUintDowncast(208, value);\n        }\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        if (value > type(uint200).max) {\n            revert SafeCastOverflowedUintDowncast(200, value);\n        }\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        if (value > type(uint192).max) {\n            revert SafeCastOverflowedUintDowncast(192, value);\n        }\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        if (value > type(uint184).max) {\n            revert SafeCastOverflowedUintDowncast(184, value);\n        }\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        if (value > type(uint176).max) {\n            revert SafeCastOverflowedUintDowncast(176, value);\n        }\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        if (value > type(uint168).max) {\n            revert SafeCastOverflowedUintDowncast(168, value);\n        }\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        if (value > type(uint160).max) {\n            revert SafeCastOverflowedUintDowncast(160, value);\n        }\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        if (value > type(uint152).max) {\n            revert SafeCastOverflowedUintDowncast(152, value);\n        }\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        if (value > type(uint144).max) {\n            revert SafeCastOverflowedUintDowncast(144, value);\n        }\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        if (value > type(uint136).max) {\n            revert SafeCastOverflowedUintDowncast(136, value);\n        }\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        if (value > type(uint128).max) {\n            revert SafeCastOverflowedUintDowncast(128, value);\n        }\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        if (value > type(uint120).max) {\n            revert SafeCastOverflowedUintDowncast(120, value);\n        }\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        if (value > type(uint112).max) {\n            revert SafeCastOverflowedUintDowncast(112, value);\n        }\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        if (value > type(uint104).max) {\n            revert SafeCastOverflowedUintDowncast(104, value);\n        }\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        if (value > type(uint96).max) {\n            revert SafeCastOverflowedUintDowncast(96, value);\n        }\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        if (value > type(uint88).max) {\n            revert SafeCastOverflowedUintDowncast(88, value);\n        }\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        if (value > type(uint80).max) {\n            revert SafeCastOverflowedUintDowncast(80, value);\n        }\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        if (value > type(uint72).max) {\n            revert SafeCastOverflowedUintDowncast(72, value);\n        }\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        if (value > type(uint64).max) {\n            revert SafeCastOverflowedUintDowncast(64, value);\n        }\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        if (value > type(uint56).max) {\n            revert SafeCastOverflowedUintDowncast(56, value);\n        }\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        if (value > type(uint48).max) {\n            revert SafeCastOverflowedUintDowncast(48, value);\n        }\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        if (value > type(uint40).max) {\n            revert SafeCastOverflowedUintDowncast(40, value);\n        }\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        if (value > type(uint32).max) {\n            revert SafeCastOverflowedUintDowncast(32, value);\n        }\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        if (value > type(uint24).max) {\n            revert SafeCastOverflowedUintDowncast(24, value);\n        }\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        if (value > type(uint16).max) {\n            revert SafeCastOverflowedUintDowncast(16, value);\n        }\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        if (value > type(uint8).max) {\n            revert SafeCastOverflowedUintDowncast(8, value);\n        }\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        if (value < 0) {\n            revert SafeCastOverflowedIntToUint(value);\n        }\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(248, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(240, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(232, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(224, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(216, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(208, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(200, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(192, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(184, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(176, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(168, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(160, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(152, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(144, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(136, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(128, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(120, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(112, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(104, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(96, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(88, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(80, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(72, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(64, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(56, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(48, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(40, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(32, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(24, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(16, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(8, value);\n        }\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        if (value > uint256(type(int256).max)) {\n            revert SafeCastOverflowedUintToInt(value);\n        }\n        return int256(value);\n    }\n\n    /**\n     * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\n     */\n    function toUint(bool b) internal pure returns (uint256 u) {\n        assembly (\"memory-safe\") {\n            u := iszero(iszero(b))\n        }\n    }\n}\n"
    },
    "src/Luckotto.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.36;\n\nimport {\n    ReentrancyGuardTransient\n} from \"@openzeppelin/contracts/utils/ReentrancyGuardTransient.sol\";\nimport { Math } from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { EthereumBlockHeader } from \"./libraries/EthereumBlockHeader.sol\";\nimport { QuicknetBLS } from \"./libraries/QuicknetBLS.sol\";\n\n/// @title Luckotto V1 Edge-Capped Round Lottery\n/// @notice Native-ETH bankroll with committed ERC-20 bankroll shares and variable-payout boundary\n/// rounds.\ncontract Luckotto is ERC20, ReentrancyGuardTransient {\n    uint256 public constant ROUND_BLOCKS = 10_000;\n    uint256 public constant HISTORY_WINDOW_BLOCKS = 8191;\n    uint256 public constant SUNSET_PERIOD = 365 days;\n    uint256 public constant DRAIN_DELAY = 365 days;\n    uint256 public constant EDGE_SCALE = 1 << 32;\n    uint64 public constant MAX_FUTURE_ROUNDS = 10;\n\n    uint256 private constant DRAND_DELAY_SECONDS = 30 minutes;\n    uint256 private constant PROBABILITY_SCALE = 1 << 128;\n    uint256 private constant MAINNET_CHAIN_ID = 1;\n    uint256 private constant SEPOLIA_CHAIN_ID = 11_155_111;\n    address private constant HISTORY_STORAGE_ADDRESS = 0x0000F90827F1C53a10cb7A02335B175320002935;\n    bytes32 private constant DRAND_CHAIN_HASH =\n        0x52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971;\n    uint256 private constant DRAND_PERIOD_SECONDS = 3;\n    uint256 private constant DRAND_GENESIS_TIME = 1_692_803_367;\n\n    bytes32 private constant PROTOCOL_DOMAIN = keccak256(\"LUCKOTTO_PROTOCOL_V1\");\n    bytes32 private constant DRAW_DOMAIN = keccak256(\"LUCKOTTO_DRAW_V1\");\n    bytes32 private constant CANDIDATE_DRAW_DOMAIN = keccak256(\"LUCKOTTO_CANDIDATE_DRAW_V1\");\n    bytes32 private constant COVERAGE_DRAW_DOMAIN = keccak256(\"LUCKOTTO_COVERAGE_DRAW_V1\");\n    bytes32 private constant RISK_DRAW_DOMAIN = keccak256(\"LUCKOTTO_RISK_DRAW_V1\");\n\n    enum RoundState {\n        Pending,\n        WinnerClaimable,\n        WinnerPaid,\n        NoWinner,\n        Expired\n    }\n\n    struct Round {\n        RoundState state;\n        uint64 positionCount;\n        uint64 selectedPositionIndex;\n        uint128 settlementBankroll;\n        uint128 aggregateStake;\n    }\n\n    struct Position {\n        address beneficiary;\n        uint96 stake;\n        uint96 targetPayout;\n        uint32 maxEdgeQ32;\n        uint128 rangeStart;\n    }\n\n    struct ProofData {\n        bytes32 seed;\n        bytes32 prevRandao;\n        bytes32 signatureHash;\n        uint64 drandRound;\n    }\n\n    struct DrawData {\n        uint256 payout;\n        uint256 gap;\n        bool won;\n    }\n\n    address public immutable owner;\n    uint64 public immutable roundOffset;\n    bytes32 public immutable deploymentDomain;\n    uint64 public frozenAt;\n    uint64 public sunsetAt;\n    uint64 public oldestPendingRoundId;\n    uint128 public bankrollAssets;\n    uint128 public reservedAssets;\n\n    mapping(uint64 roundId => Round round) private _rounds;\n    mapping(uint64 roundId => mapping(uint64 positionIndex => Position position)) private\n        _positions;\n\n    event Invested(\n        address indexed investor,\n        uint256 assets,\n        uint256 shares,\n        uint256 bankrollAssets,\n        uint256 totalSupply\n    );\n    event Divested(\n        address indexed investor,\n        address indexed recipient,\n        uint256 shares,\n        uint256 assets,\n        uint256 bankrollAssets,\n        uint256 totalSupply\n    );\n    event BetPlaced(\n        uint64 indexed roundId,\n        uint64 indexed positionIndex,\n        address indexed beneficiary,\n        uint96 targetPayout,\n        uint32 maxEdgeQ32,\n        uint96 stake,\n        uint128 aggregateStake,\n        bytes32 positionCommitment\n    );\n    event RoundResolved(\n        uint64 indexed roundId,\n        uint64 indexed selectedPositionIndex,\n        address indexed resolver,\n        bool won,\n        uint256 payout,\n        uint256 aggregateStake,\n        uint256 settlementBankroll,\n        bytes32 prevRandao,\n        uint64 drandRound,\n        bytes32 drandSignatureHash\n    );\n    event BetClaimed(\n        uint64 indexed roundId,\n        uint64 indexed positionIndex,\n        address indexed beneficiary,\n        address recipient,\n        address claimer,\n        uint256 stake,\n        uint256 payout\n    );\n    event RoundExpired(\n        uint64 indexed roundId,\n        address indexed expirer,\n        uint64 targetBlock,\n        uint256 forfeitedStake,\n        uint256 settlementBankroll\n    );\n    event Frozen(address indexed caller, uint256 frozenAt);\n    event SunsetExtended(address indexed owner, uint256 previousSunsetAt, uint256 nextSunsetAt);\n    event Drained(address indexed owner, address indexed recipient, uint256 amount);\n\n    error ZeroAddress();\n    error ZeroValue();\n    error ZeroShares();\n    error InvalidConstructorParameters();\n    error InvalidBeneficiary(address beneficiary);\n    error InvalidRecipient(address recipient);\n    error BettingFrozen();\n    error InvestingFrozen();\n    error AlreadyFrozen();\n    error NotFrozen();\n    error SunsetNotReached(uint256 sunsetAt);\n    error DrainNotReady(uint256 availableAt);\n    error Unauthorized();\n    error InvalidRound();\n    error InvalidPosition();\n    error InvalidTargetRound(uint64 earliestRoundId, uint64 actualRoundId);\n    error TargetRoundTooFar(uint64 latestRoundId, uint64 actualRoundId);\n    error RoundNotPending();\n    error EarlierRoundPending(uint64 roundId);\n    error WinnerNotClaimable();\n    error RoundStillOpen(uint256 targetBlock);\n    error ResolutionWindowExpired(uint256 lastBlock);\n    error ResolutionWindowStillOpen(uint256 lastBlock);\n    error CandidatePositionRequired();\n    error PositionDidNotWin();\n    error StakeTooLarge(uint256 maximum, uint256 actual);\n    error AggregateStakeTooLarge(uint256 maximum, uint256 actual);\n    error PositionLimitReached(uint64 roundId);\n    error AccountingCapacityExceeded(uint256 required, uint256 maximum);\n    error InsufficientShares(uint256 required, uint256 available);\n    error InsufficientCash(uint256 required, uint256 available);\n    error InvalidBankrollState(uint256 bankroll, uint256 totalSupply);\n    error OrphanedBankroll(uint256 assets);\n    error BankrollLocked(uint64 roundId, uint256 lastBlock);\n    error NativeTransferFailed();\n    error InvalidShareRecipient();\n    error BlockHashUnavailable(uint256 targetBlock);\n    error InvalidBlockHeader();\n    error DrandNotReady(uint256 readyAt);\n    error InvalidDrandSignature();\n    error InvalidSchedule();\n    error BLSPrecompileSelfTestFailed();\n    error UnsupportedChain(uint256 actual);\n\n    modifier onlyOwner() {\n        if (msg.sender != owner) revert Unauthorized();\n        _;\n    }\n\n    constructor(address owner_) payable ERC20(\"LUCKOTTO\", \"LUCKOTTO\") {\n        if (block.chainid != MAINNET_CHAIN_ID && block.chainid != SEPOLIA_CHAIN_ID) {\n            revert UnsupportedChain(block.chainid);\n        }\n        if (owner_ == address(0) || owner_ == address(this)) revert InvalidConstructorParameters();\n        if (msg.value == 0) revert ZeroValue();\n        if (!QuicknetBLS.selfTest()) revert BLSPrecompileSelfTestFailed();\n\n        uint256 offset = block.number / ROUND_BLOCKS;\n        if (offset >= type(uint64).max / ROUND_BLOCKS) revert InvalidSchedule();\n        owner = owner_;\n        sunsetAt = uint64(block.timestamp + SUNSET_PERIOD);\n        roundOffset = uint64(offset);\n        deploymentDomain = keccak256(\n            abi.encode(\n                PROTOCOL_DOMAIN,\n                block.chainid,\n                address(this),\n                ROUND_BLOCKS,\n                roundOffset,\n                DRAND_CHAIN_HASH,\n                QuicknetBLS.publicKeyHash()\n            )\n        );\n        _invest(owner_, msg.value);\n    }\n\n    function invest() external payable returns (uint256 shares) {\n        if (frozenAt != 0) revert InvestingFrozen();\n        shares = _invest(msg.sender, msg.value);\n    }\n\n    /// @notice Burns shares for pro-rata bankroll assets after wind-down rounds are finalized.\n    function divest(uint256 shares, address payable recipient)\n        external\n        nonReentrant\n        returns (uint256 assets)\n    {\n        if (frozenAt == 0) revert NotFrozen();\n        _requireNoPendingRound();\n        if (shares == 0) revert ZeroShares();\n        if (recipient == address(0)) revert ZeroAddress();\n        if (recipient == address(this)) revert InvalidRecipient(recipient);\n        uint256 investorShares = balanceOf(msg.sender);\n        if (shares > investorShares) revert InsufficientShares(shares, investorShares);\n\n        uint256 bankroll = bankrollAssets;\n        uint256 supply = totalSupply();\n        assets = shares == supply ? bankroll : Math.mulDiv(shares, bankroll, supply);\n        if (assets == 0) revert ZeroValue();\n\n        bankrollAssets = uint128(bankroll - assets);\n        _burn(msg.sender, shares);\n        emit Divested(msg.sender, recipient, shares, assets, bankrollAssets, totalSupply());\n        (bool sent,) = recipient.call{ value: assets }(\"\");\n        if (!sent) revert NativeTransferFailed();\n    }\n\n    /// @dev Shares sent directly to this contract cannot be recovered through the bankroll\n    /// lifecycle.\n    function _update(address from, address to, uint256 value) internal override {\n        if (to == address(this)) revert InvalidShareRecipient();\n        super._update(from, to, value);\n    }\n\n    /// @notice Returns the unresolved boundary round currently pausing bankroll investment.\n    function bankrollBlockedRound() public view returns (uint64 roundId) {\n        roundId = oldestPendingRoundId;\n        if (roundId == 0 || block.number < targetBlockForRound(roundId)) return 0;\n    }\n\n    /// @notice The earliest boundary round that can accept a position at `blockNumber`.\n    function roundIdForBlock(uint256 blockNumber) public view returns (uint64 roundId) {\n        uint256 absoluteRound = blockNumber / ROUND_BLOCKS;\n        if (absoluteRound < roundOffset) return 1;\n        uint256 candidate = absoluteRound - roundOffset + 1;\n        if (candidate > type(uint64).max) revert InvalidSchedule();\n        roundId = uint64(candidate);\n    }\n\n    /// @notice The latest of the ten boundary rounds that can accept a position.\n    function latestRoundIdForBlock(uint256 blockNumber) public view returns (uint64 roundId) {\n        uint256 earliestRoundId = roundIdForBlock(blockNumber);\n        uint256 candidate = earliestRoundId + MAX_FUTURE_ROUNDS - 1;\n        roundId = candidate > type(uint64).max ? type(uint64).max : uint64(candidate);\n    }\n\n    function targetBlockForRound(uint64 roundId) public view returns (uint64 targetBlock) {\n        uint256 absoluteRound = uint256(roundOffset) + roundId;\n        if (roundId == 0 || absoluteRound > type(uint64).max / ROUND_BLOCKS) {\n            revert InvalidSchedule();\n        }\n        targetBlock = uint64(absoluteRound * ROUND_BLOCKS);\n    }\n\n    /// @notice Appends one immutable edge-capped position to one of the next ten boundary rounds.\n    /// @dev `positionCommitment` is opaque caller data emitted without interpretation,\n    /// validation, or incorporation into the draw. It is not retained in contract storage.\n    function placeBet(\n        uint64 roundId,\n        uint96 targetPayout,\n        uint32 maxEdgeQ32,\n        address beneficiary,\n        bytes32 positionCommitment\n    ) external payable returns (uint64 positionIndex, uint256 rangeStart, uint256 aggregateStake) {\n        _validateBetInput(beneficiary);\n        _requireNoExpiredRound();\n        uint64 earliestRoundId = roundIdForBlock(block.number);\n        if (roundId < earliestRoundId) revert InvalidTargetRound(earliestRoundId, roundId);\n        uint64 latestRoundId = latestRoundIdForBlock(block.number);\n        if (roundId > latestRoundId) revert TargetRoundTooFar(latestRoundId, roundId);\n\n        // Also rejects round identifiers whose target would not fit the supported block range.\n        targetBlockForRound(roundId);\n        Round storage round = _rounds[roundId];\n        bool firstPosition = round.aggregateStake == 0;\n\n        uint256 nextAggregate = uint256(round.aggregateStake) + msg.value;\n        if (nextAggregate > type(uint128).max) {\n            revert AggregateStakeTooLarge(type(uint128).max, nextAggregate);\n        }\n        uint256 nextAccountedAssets = uint256(bankrollAssets) + uint256(reservedAssets) + msg.value;\n        if (nextAccountedAssets > type(uint128).max) {\n            revert AccountingCapacityExceeded(nextAccountedAssets, type(uint128).max);\n        }\n        if (round.positionCount == type(uint64).max) revert PositionLimitReached(roundId);\n        positionIndex = round.positionCount + 1;\n        rangeStart = round.aggregateStake;\n        _positions[roundId][positionIndex] = Position({\n            beneficiary: beneficiary,\n            stake: uint96(msg.value),\n            targetPayout: targetPayout,\n            maxEdgeQ32: maxEdgeQ32,\n            rangeStart: uint128(rangeStart)\n        });\n        round.positionCount = positionIndex;\n        round.aggregateStake = uint128(nextAggregate);\n        reservedAssets = uint128(uint256(reservedAssets) + msg.value);\n        if (firstPosition) _trackPendingRound(roundId);\n\n        emit BetPlaced(\n            roundId,\n            positionIndex,\n            beneficiary,\n            targetPayout,\n            maxEdgeQ32,\n            uint96(msg.value),\n            uint128(nextAggregate),\n            positionCommitment\n        );\n        return (positionIndex, rangeStart, nextAggregate);\n    }\n\n    function _validateBetInput(address beneficiary) private view {\n        if (frozenAt != 0) revert BettingFrozen();\n        if (msg.value == 0) revert ZeroValue();\n        if (beneficiary == address(0)) revert ZeroAddress();\n        if (beneficiary == address(this)) revert InvalidBeneficiary(beneficiary);\n        if (msg.value > type(uint96).max) {\n            revert StakeTooLarge(type(uint96).max, msg.value);\n        }\n    }\n\n    /// @notice Describes any round identifier without reverting for empty or invalid rounds.\n    /// @dev `validRoundId` reports whether the identifier maps to a supported target block, while\n    /// `hasPositions` reports whether any round storage has been initialized by a bet.\n    function getRoundInfo(uint64 roundId)\n        external\n        view\n        returns (bool validRoundId, bool hasPositions, uint64 targetBlock, Round memory round)\n    {\n        round = _rounds[roundId];\n        hasPositions = round.aggregateStake != 0;\n        uint256 absoluteRound = uint256(roundOffset) + roundId;\n        validRoundId = roundId != 0 && absoluteRound <= type(uint64).max / ROUND_BLOCKS;\n        if (validRoundId) targetBlock = uint64(absoluteRound * ROUND_BLOCKS);\n    }\n\n    function getPosition(uint64 roundId, uint64 positionIndex)\n        external\n        view\n        returns (Position memory position)\n    {\n        position = _requirePosition(roundId, positionIndex);\n    }\n\n    /// @notice Quotes a position with final known stake and the current or settled bankroll.\n    function quotePosition(uint64 roundId, uint64 positionIndex)\n        external\n        view\n        returns (uint256 payout, uint256 gap, uint256 edge, uint256 winProbability)\n    {\n        Round storage round = _requireRound(roundId);\n        Position storage position = _requirePosition(roundId, positionIndex);\n        return _quotePosition(\n            round.aggregateStake,\n            position.stake,\n            position.targetPayout,\n            position.maxEdgeQ32,\n            _quoteBankroll(round)\n        );\n    }\n\n    /// @notice Resolves a round using the unique stake interval containing the candidate point.\n    function settle(\n        uint64 roundId,\n        uint64 candidatePositionIndex,\n        bytes calldata rlpHeader,\n        bytes calldata drandSignature\n    ) external returns (bool won) {\n        if (candidatePositionIndex == 0) {\n            revert CandidatePositionRequired();\n        }\n        Round storage round = _requireRound(roundId);\n        if (round.state != RoundState.Pending) revert RoundNotPending();\n        _requireOldestPendingRound(roundId);\n        Position storage position = _requirePosition(roundId, candidatePositionIndex);\n        uint128 settlementBankroll = bankrollAssets;\n        ProofData memory proof =\n            _validateProof(roundId, round, settlementBankroll, rlpHeader, drandSignature);\n        DrawData memory draw = _evaluateDraw(\n            candidatePositionIndex, round, position, settlementBankroll, proof.seed\n        );\n        won = draw.won;\n        _finalizeRound(roundId, candidatePositionIndex, round, settlementBankroll, draw, proof);\n    }\n\n    function claimWinner(uint64 roundId) external nonReentrant {\n        Round storage round = _requireRound(roundId);\n        Position storage position = _claimablePosition(roundId, round);\n        _payWinner(\n            roundId,\n            round.selectedPositionIndex,\n            round,\n            position,\n            payable(position.beneficiary),\n            msg.sender\n        );\n    }\n\n    /// @notice Lets the immutable beneficiary redirect a claim if it cannot receive native ETH.\n    function claimWinnerTo(uint64 roundId, address payable recipient) external nonReentrant {\n        Round storage round = _requireRound(roundId);\n        Position storage position = _claimablePosition(roundId, round);\n        if (msg.sender != position.beneficiary) revert Unauthorized();\n        if (recipient == address(0)) revert ZeroAddress();\n        if (recipient == address(this)) revert InvalidRecipient(recipient);\n        _payWinner(roundId, round.selectedPositionIndex, round, position, recipient, msg.sender);\n    }\n\n    function expireRound(uint64 roundId) external {\n        Round storage round = _requireRound(roundId);\n        if (round.state != RoundState.Pending) revert RoundNotPending();\n        uint256 lastBlock = uint256(targetBlockForRound(roundId)) + HISTORY_WINDOW_BLOCKS;\n        if (block.number <= lastBlock) revert ResolutionWindowStillOpen(lastBlock);\n        _requireOldestPendingRound(roundId);\n        _expireRound(roundId, round);\n    }\n\n    function freeze() external {\n        if (frozenAt != 0) revert AlreadyFrozen();\n        if (msg.sender != owner && block.timestamp < sunsetAt) {\n            revert SunsetNotReached(sunsetAt);\n        }\n        frozenAt = uint64(block.timestamp);\n        emit Frozen(msg.sender, block.timestamp);\n    }\n\n    function extendSunset() external onlyOwner {\n        if (frozenAt != 0) revert AlreadyFrozen();\n        uint256 previousSunsetAt = sunsetAt;\n        uint256 nextSunsetAt = block.timestamp + SUNSET_PERIOD;\n        sunsetAt = uint64(nextSunsetAt);\n        emit SunsetExtended(msg.sender, previousSunsetAt, nextSunsetAt);\n    }\n\n    /// @notice Transfers all cash to the selected recipient one year after freezing without\n    /// changing accounting.\n    function drain(address payable recipient) external onlyOwner nonReentrant {\n        uint256 frozen = frozenAt;\n        if (frozen == 0) revert NotFrozen();\n        if (recipient == address(0)) revert ZeroAddress();\n        if (recipient == address(this)) revert InvalidRecipient(recipient);\n        uint256 availableAt = frozen + DRAIN_DELAY;\n        if (block.timestamp < availableAt) revert DrainNotReady(availableAt);\n        uint256 amount = address(this).balance;\n        emit Drained(msg.sender, recipient, amount);\n        if (amount != 0) {\n            (bool sent,) = recipient.call{ value: amount }(\"\");\n            if (!sent) revert NativeTransferFailed();\n        }\n    }\n\n    function _invest(address investor, uint256 assets) private returns (uint256 shares) {\n        _requireBankrollOpen();\n        if (assets == 0) revert ZeroValue();\n        uint256 bankroll = bankrollAssets;\n        uint256 nextBankroll = bankroll + assets;\n        uint256 nextAccountedAssets = nextBankroll + uint256(reservedAssets);\n        if (nextAccountedAssets > type(uint128).max) {\n            revert AccountingCapacityExceeded(nextAccountedAssets, type(uint128).max);\n        }\n        uint256 supply = totalSupply();\n        if (supply == 0) {\n            if (bankroll != 0) revert OrphanedBankroll(bankroll);\n            shares = assets;\n        } else {\n            if (bankroll == 0) revert InvalidBankrollState(bankroll, supply);\n            shares = Math.mulDiv(assets, supply, bankroll);\n            if (shares == 0) revert ZeroShares();\n        }\n        bankrollAssets = uint128(nextBankroll);\n        _mint(investor, shares);\n        emit Invested(investor, assets, shares, bankrollAssets, totalSupply());\n    }\n\n    function _requireBankrollOpen() private view {\n        uint64 blockedRoundId = bankrollBlockedRound();\n        if (blockedRoundId != 0) {\n            revert BankrollLocked(\n                blockedRoundId, uint256(targetBlockForRound(blockedRoundId)) + HISTORY_WINDOW_BLOCKS\n            );\n        }\n    }\n\n    function _requireNoPendingRound() private view {\n        uint64 roundId = oldestPendingRoundId;\n        if (roundId != 0) revert EarlierRoundPending(roundId);\n    }\n\n    function _requireNoExpiredRound() private view {\n        uint64 roundId = oldestPendingRoundId;\n        if (\n            roundId != 0\n                && block.number > uint256(targetBlockForRound(roundId)) + HISTORY_WINDOW_BLOCKS\n        ) {\n            revert EarlierRoundPending(roundId);\n        }\n    }\n\n    function _requireOldestPendingRound(uint64 roundId) private view {\n        uint64 oldestRoundId = oldestPendingRoundId;\n        if (roundId != oldestRoundId) revert EarlierRoundPending(oldestRoundId);\n    }\n\n    function _trackPendingRound(uint64 roundId) private {\n        uint64 oldestRoundId = oldestPendingRoundId;\n        if (oldestRoundId == 0 || roundId < oldestRoundId) oldestPendingRoundId = roundId;\n    }\n\n    function _advanceOldestPendingRound(uint64 finalizedRoundId) private {\n        oldestPendingRoundId = 0;\n        // Before this round's proof window closes, placement can reach at most ten rounds beyond\n        // it. Once overdue, _requireNoExpiredRound prevents the pending set from growing further.\n        uint256 lastCandidate = uint256(finalizedRoundId) + MAX_FUTURE_ROUNDS;\n        if (lastCandidate > type(uint64).max) lastCandidate = type(uint64).max;\n        for (\n            uint256 candidate = uint256(finalizedRoundId) + 1;\n            candidate <= lastCandidate;\n            ++candidate\n        ) {\n            Round storage round = _rounds[uint64(candidate)];\n            if (round.aggregateStake != 0 && round.state == RoundState.Pending) {\n                oldestPendingRoundId = uint64(candidate);\n                break;\n            }\n        }\n    }\n\n    function _quoteBankroll(Round storage round) private view returns (uint256) {\n        return round.state == RoundState.Pending ? bankrollAssets : round.settlementBankroll;\n    }\n\n    function _quotePayout(\n        uint256 aggregateStake,\n        uint256 targetPayout,\n        uint256 maxEdgeQ32,\n        uint256 bankroll\n    ) private pure returns (uint256 payout, uint256 gap) {\n        payout = aggregateStake > targetPayout ? aggregateStake : targetPayout;\n        uint256 requestedGap = payout - aggregateStake;\n        uint256 maximumGap = Math.mulDiv(bankroll, maxEdgeQ32, EDGE_SCALE);\n        gap = requestedGap > maximumGap ? maximumGap : requestedGap;\n        payout = aggregateStake + gap;\n    }\n\n    function _quotePosition(\n        uint256 aggregateStake,\n        uint256 stake,\n        uint256 targetPayout,\n        uint256 maxEdgeQ32,\n        uint256 bankroll\n    ) internal pure returns (uint256 payout, uint256 gap, uint256 edge, uint256 winProbability) {\n        (payout, gap) = _quotePayout(aggregateStake, targetPayout, maxEdgeQ32, bankroll);\n        edge = bankroll == 0 ? 0 : Math.mulDiv(gap, PROBABILITY_SCALE, bankroll);\n        if (bankroll == 0) {\n            winProbability = Math.mulDiv(stake, PROBABILITY_SCALE, payout);\n        } else {\n            uint256 probabilityNumerator = stake * (bankroll - gap);\n            uint256 probabilityDenominator = payout * bankroll;\n            winProbability =\n                Math.mulDiv(probabilityNumerator, PROBABILITY_SCALE, probabilityDenominator);\n        }\n    }\n\n    function _validateProof(\n        uint64 roundId,\n        Round storage round,\n        uint128 settlementBankroll,\n        bytes calldata rlpHeader,\n        bytes calldata drandSignature\n    ) private view returns (ProofData memory proof) {\n        uint256 targetBlock = targetBlockForRound(roundId);\n        if (block.number <= targetBlock) revert RoundStillOpen(targetBlock);\n        uint256 lastBlock = targetBlock + HISTORY_WINDOW_BLOCKS;\n        if (block.number > lastBlock) revert ResolutionWindowExpired(lastBlock);\n        (uint64 headerBlock, uint64 headerTimestamp, bytes32 prevRandao) =\n            EthereumBlockHeader.parse(rlpHeader);\n        if (headerBlock != targetBlock || keccak256(rlpHeader) != _historicalBlockHash(headerBlock))\n        {\n            revert InvalidBlockHeader();\n        }\n        uint64 drandRound = _roundAtOrAfter(uint256(headerTimestamp) + DRAND_DELAY_SECONDS);\n        uint256 readyAt = _roundTime(drandRound);\n        if (block.timestamp < readyAt) revert DrandNotReady(readyAt);\n        (bool validSignature, bytes32 signatureHash) =\n            _verifyDrandSignature(drandSignature, drandRound);\n        if (!validSignature) revert InvalidDrandSignature();\n\n        proof.prevRandao = prevRandao;\n        proof.drandRound = drandRound;\n        proof.signatureHash = signatureHash;\n        proof.seed =\n            _drawSeed(roundId, round, settlementBankroll, prevRandao, drandRound, signatureHash);\n    }\n\n    function _evaluateDraw(\n        uint64 candidatePositionIndex,\n        Round storage round,\n        Position storage position,\n        uint128 settlementBankroll,\n        bytes32 seed\n    ) private view returns (DrawData memory draw) {\n        uint256 candidatePoint = _candidatePoint(seed, round.aggregateStake);\n        if (!_contains(position, candidatePoint)) revert PositionDidNotWin();\n        (draw.payout, draw.gap) = _quotePayout(\n            round.aggregateStake, position.targetPayout, position.maxEdgeQ32, settlementBankroll\n        );\n        (uint256 coveragePoint, uint256 riskPoint) =\n            _gatePoints(seed, candidatePositionIndex, draw.payout, settlementBankroll);\n        draw.won = coveragePoint < round.aggregateStake\n            && (settlementBankroll == 0 || riskPoint < settlementBankroll - draw.gap);\n    }\n\n    function _finalizeRound(\n        uint64 roundId,\n        uint64 candidatePositionIndex,\n        Round storage round,\n        uint128 settlementBankroll,\n        DrawData memory draw,\n        ProofData memory proof\n    ) private {\n        round.selectedPositionIndex = candidatePositionIndex;\n        round.settlementBankroll = settlementBankroll;\n\n        uint256 aggregateStake = round.aggregateStake;\n        if (draw.won) {\n            round.state = RoundState.WinnerClaimable;\n            bankrollAssets = uint128(uint256(settlementBankroll) - draw.gap);\n            reservedAssets = uint128(uint256(reservedAssets) + draw.gap);\n        } else {\n            round.state = RoundState.NoWinner;\n            bankrollAssets = uint128(uint256(settlementBankroll) + aggregateStake);\n            reservedAssets = uint128(uint256(reservedAssets) - aggregateStake);\n        }\n        _advanceOldestPendingRound(roundId);\n        emit RoundResolved(\n            roundId,\n            candidatePositionIndex,\n            msg.sender,\n            draw.won,\n            draw.payout,\n            aggregateStake,\n            settlementBankroll,\n            proof.prevRandao,\n            proof.drandRound,\n            proof.signatureHash\n        );\n    }\n\n    function _expireRound(uint64 roundId, Round storage round) private {\n        uint128 settlementBankroll = bankrollAssets;\n        uint256 forfeitedStake = round.aggregateStake;\n        round.state = RoundState.Expired;\n        round.settlementBankroll = settlementBankroll;\n        bankrollAssets = uint128(uint256(settlementBankroll) + forfeitedStake);\n        reservedAssets = uint128(uint256(reservedAssets) - forfeitedStake);\n        _advanceOldestPendingRound(roundId);\n        emit RoundExpired(\n            roundId, msg.sender, targetBlockForRound(roundId), forfeitedStake, settlementBankroll\n        );\n    }\n\n    function _roundAtOrAfter(uint256 timestamp) internal pure returns (uint64 round) {\n        if (timestamp <= DRAND_GENESIS_TIME) return 1;\n        uint256 candidate =\n            (timestamp - DRAND_GENESIS_TIME + DRAND_PERIOD_SECONDS - 1) / DRAND_PERIOD_SECONDS + 1;\n        if (candidate > type(uint64).max) revert InvalidSchedule();\n        round = uint64(candidate);\n    }\n\n    function _roundTime(uint64 round) internal pure returns (uint256) {\n        if (round == 0) revert InvalidSchedule();\n        return DRAND_GENESIS_TIME + (uint256(round) - 1) * DRAND_PERIOD_SECONDS;\n    }\n\n    function _drawSeed(\n        uint64 roundId,\n        Round storage round,\n        uint128 settlementBankroll,\n        bytes32 prevRandao,\n        uint64 drandRound,\n        bytes32 drandSignatureHash\n    ) internal view returns (bytes32) {\n        return keccak256(\n            abi.encode(\n                DRAW_DOMAIN,\n                deploymentDomain,\n                roundId,\n                targetBlockForRound(roundId),\n                round.aggregateStake,\n                settlementBankroll,\n                prevRandao,\n                drandRound,\n                drandSignatureHash\n            )\n        );\n    }\n\n    function _candidatePoint(bytes32 seed, uint256 aggregateStake) internal pure returns (uint256) {\n        return uint256(keccak256(abi.encode(CANDIDATE_DRAW_DOMAIN, seed))) % aggregateStake;\n    }\n\n    function _gatePoints(\n        bytes32 seed,\n        uint64 positionIndex,\n        uint256 payout,\n        uint256 settlementBankroll\n    ) internal pure returns (uint256 coveragePoint, uint256 riskPoint) {\n        coveragePoint =\n            uint256(keccak256(abi.encode(COVERAGE_DRAW_DOMAIN, seed, positionIndex))) % payout;\n        if (settlementBankroll != 0) {\n            riskPoint = uint256(keccak256(abi.encode(RISK_DRAW_DOMAIN, seed, positionIndex)))\n                % settlementBankroll;\n        }\n    }\n\n    function _historicalBlockHash(uint64 targetBlock)\n        internal\n        view\n        virtual\n        returns (bytes32 trustedHash)\n    {\n        (bool ok, bytes memory result) =\n            HISTORY_STORAGE_ADDRESS.staticcall(abi.encode(uint256(targetBlock)));\n        if (!ok || result.length != 32) revert BlockHashUnavailable(targetBlock);\n        trustedHash = abi.decode(result, (bytes32));\n        if (trustedHash == bytes32(0)) revert BlockHashUnavailable(targetBlock);\n    }\n\n    function _requireRound(uint64 roundId) internal view returns (Round storage round) {\n        round = _rounds[roundId];\n        if (round.aggregateStake == 0) revert InvalidRound();\n    }\n\n    function _requirePosition(uint64 roundId, uint64 positionIndex)\n        internal\n        view\n        returns (Position storage position)\n    {\n        position = _positions[roundId][positionIndex];\n        if (position.beneficiary == address(0)) revert InvalidPosition();\n    }\n\n    function _contains(Position storage position, uint256 point) private view returns (bool) {\n        uint256 rangeEnd = uint256(position.rangeStart) + position.stake;\n        return point >= position.rangeStart && point < rangeEnd;\n    }\n\n    function _claimablePosition(uint64 roundId, Round storage round)\n        private\n        view\n        returns (Position storage position)\n    {\n        if (round.state != RoundState.WinnerClaimable) revert WinnerNotClaimable();\n        position = _requirePosition(roundId, round.selectedPositionIndex);\n    }\n\n    function _payWinner(\n        uint64 roundId,\n        uint64 positionIndex,\n        Round storage round,\n        Position storage position,\n        address payable recipient,\n        address claimer\n    ) private {\n        (uint256 payout,) = _quotePayout(\n            round.aggregateStake,\n            position.targetPayout,\n            position.maxEdgeQ32,\n            round.settlementBankroll\n        );\n        uint256 cash = address(this).balance;\n        if (cash < payout) revert InsufficientCash(payout, cash);\n        round.state = RoundState.WinnerPaid;\n        reservedAssets = uint128(uint256(reservedAssets) - payout);\n        emit BetClaimed(\n            roundId, positionIndex, position.beneficiary, recipient, claimer, position.stake, payout\n        );\n        (bool sent,) = recipient.call{ value: payout }(\"\");\n        if (!sent) revert NativeTransferFailed();\n    }\n\n    function _verifyDrandSignature(bytes memory signature, uint64 targetRound)\n        internal\n        view\n        virtual\n        returns (bool valid, bytes32 canonicalHash)\n    {\n        return QuicknetBLS.verifyAndHash(signature, targetRound);\n    }\n}\n"
    },
    "src/libraries/EthereumBlockHeader.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.36;\n\n/// @notice Minimal canonical RLP reader for post-merge Ethereum block headers.\nlibrary EthereumBlockHeader {\n    error InvalidRlp();\n\n    struct Item {\n        uint256 payloadOffset;\n        uint256 payloadLength;\n        uint256 totalLength;\n        bool isList;\n    }\n\n    function parse(bytes calldata encoded)\n        internal\n        pure\n        returns (uint64 blockNumber, uint64 timestamp, bytes32 prevRandao)\n    {\n        Item memory header = _item(encoded, 0);\n        if (!header.isList || header.totalLength != encoded.length) revert InvalidRlp();\n\n        uint256 cursor = header.payloadOffset;\n        uint256 end = cursor + header.payloadLength;\n        uint256 field;\n        bool foundNumber;\n        bool foundTimestamp;\n        bool foundPrevRandao;\n        while (cursor < end) {\n            Item memory value = _item(encoded, cursor);\n            if (cursor + value.totalLength > end) revert InvalidRlp();\n            if (field == 8) {\n                blockNumber = _uint64(encoded, value);\n                foundNumber = true;\n            } else if (field == 11) {\n                timestamp = _uint64(encoded, value);\n                foundTimestamp = true;\n            } else if (field == 13) {\n                if (value.isList || value.payloadLength != 32) revert InvalidRlp();\n                bytes32 extracted;\n                assembly (\"memory-safe\") {\n                    extracted := calldataload(add(encoded.offset, mload(value)))\n                }\n                prevRandao = extracted;\n                foundPrevRandao = true;\n            }\n            cursor += value.totalLength;\n            field += 1;\n        }\n        if (cursor != end || !foundNumber || !foundTimestamp || !foundPrevRandao) {\n            revert InvalidRlp();\n        }\n    }\n\n    function _uint64(bytes calldata encoded, Item memory item) private pure returns (uint64 value) {\n        if (item.isList || item.payloadLength == 0 || item.payloadLength > 8) revert InvalidRlp();\n        uint256 result = 0;\n        for (uint256 index; index < item.payloadLength; ++index) {\n            uint8 next = uint8(encoded[item.payloadOffset + index]);\n            if (index == 0 && next == 0) revert InvalidRlp();\n            result = (result << 8) | next;\n        }\n        value = uint64(result);\n    }\n\n    function _item(bytes calldata encoded, uint256 offset) private pure returns (Item memory item) {\n        if (offset >= encoded.length) revert InvalidRlp();\n        uint8 prefix = uint8(encoded[offset]);\n        if (prefix <= 0x7f) {\n            item = Item(offset, 1, 1, false);\n        } else if (prefix <= 0xb7) {\n            uint256 length = prefix - 0x80;\n            item = Item(offset + 1, length, length + 1, false);\n            if (length == 1 && offset + 1 < encoded.length && uint8(encoded[offset + 1]) <= 0x7f) {\n                revert InvalidRlp();\n            }\n        } else if (prefix <= 0xbf) {\n            uint256 lengthOfLength = prefix - 0xb7;\n            uint256 length = _length(encoded, offset + 1, lengthOfLength);\n            if (length <= 55) revert InvalidRlp();\n            item = Item(offset + 1 + lengthOfLength, length, 1 + lengthOfLength + length, false);\n        } else if (prefix <= 0xf7) {\n            uint256 length = prefix - 0xc0;\n            item = Item(offset + 1, length, length + 1, true);\n        } else {\n            uint256 lengthOfLength = prefix - 0xf7;\n            uint256 length = _length(encoded, offset + 1, lengthOfLength);\n            if (length <= 55) revert InvalidRlp();\n            item = Item(offset + 1 + lengthOfLength, length, 1 + lengthOfLength + length, true);\n        }\n        if (item.payloadOffset + item.payloadLength > encoded.length) revert InvalidRlp();\n    }\n\n    function _length(bytes calldata encoded, uint256 offset, uint256 count)\n        private\n        pure\n        returns (uint256 value)\n    {\n        if (count == 0 || count > 8 || offset + count > encoded.length) revert InvalidRlp();\n        for (uint256 index; index < count; ++index) {\n            uint8 next = uint8(encoded[offset + index]);\n            if (index == 0 && next == 0) revert InvalidRlp();\n            value = (value << 8) | next;\n        }\n    }\n}\n"
    },
    "src/libraries/QuicknetBLS.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.36;\n\n/// @title Quicknet BLS12-381 verification through EIP-2537\n/// @notice Verifies unchained quicknet signatures supplied as canonical, uncompressed G1 points.\n/// @dev Derived from randa-mu/bls-solidity commit\n///      11af179a8287d978659aae07adb66aa60f64b8a6 (MIT).\nlibrary QuicknetBLS {\n    uint256 private constant MODEXP = 0x05;\n    uint256 private constant BLS12_G1ADD = 0x0b;\n    uint256 private constant BLS12_PAIRING_CHECK = 0x0f;\n    uint256 private constant BLS12_MAP_FP_TO_G1 = 0x10;\n    /// @dev EIP-2537 charges 102,900 gas for a two-pair check. The margin covers future client\n    ///      accounting differences without allowing invalid caller-supplied points to burn all gas.\n    uint256 private constant PAIRING_CHECK_GAS = 120_000;\n\n    bytes internal constant DST = \"BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_\";\n    uint64 internal constant SELF_TEST_ROUND = 20_791_007;\n    bytes internal constant SELF_TEST_SIGNATURE =\n        hex\"0d2c8bbc37170dbacc5e280a21d4e195cff5f32a19fd6a58633fa4e4670478b5fb39bc13dd8f8c4372c5a76191198ac50823ff37364b4060af65c7ec4dde05a428e4a444713680d95c34a4b109f112af1792643c742b75d85940c4bdcfdfbfa1\";\n\n    struct PointG1 {\n        uint128 xHi;\n        uint256 xLo;\n        uint128 yHi;\n        uint256 yLo;\n    }\n\n    struct PointG2 {\n        uint128 x1Hi;\n        uint256 x1Lo;\n        uint128 x0Hi;\n        uint256 x0Lo;\n        uint128 y1Hi;\n        uint256 y1Lo;\n        uint128 y0Hi;\n        uint256 y0Lo;\n    }\n\n    // BLS12-381 base-field modulus.\n    uint128 private constant P_HI = 0x1a0111ea397fe69a4b1ba7b6434bacd7;\n    uint256 private constant P_LO =\n        0x64774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab;\n\n    // Negated G2 generator used in e(signature, -G2) * e(message, publicKey) == 1.\n    uint128 private constant N_G2_X0_HI = 0x024aa2b2f08f0a91260805272dc51051;\n    uint256 private constant N_G2_X0_LO =\n        0xc6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8;\n    uint128 private constant N_G2_X1_HI = 0x13e02b6052719f607dacd3a088274f65;\n    uint256 private constant N_G2_X1_LO =\n        0x596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e;\n    uint128 private constant N_G2_Y0_HI = 0x0d1b3cc2c7027888be51d9ef691d77bc;\n    uint256 private constant N_G2_Y0_LO =\n        0xb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa;\n    uint128 private constant N_G2_Y1_HI = 0x13fa4d4a0ad8b1ce186ed5061789213d;\n    uint256 private constant N_G2_Y1_LO =\n        0x993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed;\n\n    // Fixed quicknet distributed public key.\n    uint128 private constant QUICKNET_X1_HI = 0x03cf0f2896adee7eb8b5f01fcad39122;\n    uint256 private constant QUICKNET_X1_LO =\n        0x12c437e0073e911fb90022d3e760183c8c4b450b6a0a6c3ac6a5776a2d106451;\n    uint128 private constant QUICKNET_X0_HI = 0x0d1fec758c921cc22b0e17e63aaf4bcb;\n    uint256 private constant QUICKNET_X0_LO =\n        0x5ed66304de9cf809bd274ca73bab4af5a6e9c76a4bc09e76eae8991ef5ece45a;\n    uint128 private constant QUICKNET_Y1_HI = 0x01a714f2edb74119a2f2b0d5a7c75ba9;\n    uint256 private constant QUICKNET_Y1_LO =\n        0x02d163700a61bc224ededd8e63aef7be1aaf8e93d7a9718b047ccddb3eb5d68b;\n    uint128 private constant QUICKNET_Y0_HI = 0x0e5db2b6bfbb01c867749cadffca88b3;\n    uint256 private constant QUICKNET_Y0_LO =\n        0x6c24f3012ba09fc4d3022c5c37dce0f977d3adb5d183c7477c442b1f04515273;\n\n    /// @notice Verifies a signature under quicknet's fixed distributed public key.\n    function verify(bytes memory signature, uint64 round) internal view returns (bool) {\n        (bool valid,) = verifyAndHash(signature, round);\n        return valid;\n    }\n\n    /// @notice Verifies and hashes the unique canonical signature representation used by Luckotto.\n    /// @dev Returning the hash from the verifier keeps seed derivation coupled to the validated\n    ///      96-byte affine encoding even if other signature encodings are supported in the future.\n    function verifyAndHash(bytes memory signature, uint64 round)\n        internal\n        view\n        returns (bool valid, bytes32 canonicalHash)\n    {\n        if (round == 0 || signature.length != 96) return (false, bytes32(0));\n\n        PointG1 memory sig = unmarshalG1(signature);\n        if (!_isCanonical(sig) || _isInfinity(sig)) return (false, bytes32(0));\n\n        bytes32 roundDigest = sha256(abi.encodePacked(round));\n        PointG1 memory message = hashToPoint(DST, abi.encodePacked(roundDigest));\n        (bool pairingSuccess, bool callSuccess) = _verifyPinnedPairing(sig, message);\n        if (!callSuccess || !pairingSuccess) return (false, bytes32(0));\n        return (true, sha256(signature));\n    }\n\n    /// @notice Exercises the complete verifier path with a pinned public quicknet beacon.\n    /// @dev Used during lottery construction so deployment fails on chains without working\n    ///      EIP-2537 precompiles.\n    function selfTest() internal view returns (bool) {\n        return verify(SELF_TEST_SIGNATURE, SELF_TEST_ROUND);\n    }\n\n    /// @dev Exposed internally so the test harness can exercise wrong-key rejection.\n    function verifyWithPublicKey(bytes memory signature, uint64 round, PointG2 memory key)\n        internal\n        view\n        returns (bool)\n    {\n        if (round == 0 || signature.length != 96) return false;\n\n        PointG1 memory sig = unmarshalG1(signature);\n        if (!_isCanonical(sig) || _isInfinity(sig)) return false;\n\n        bytes32 roundDigest = sha256(abi.encodePacked(round));\n        PointG1 memory message = hashToPoint(DST, abi.encodePacked(roundDigest));\n        (bool pairingSuccess, bool callSuccess) = _verifyPairing(sig, key, message);\n        return callSuccess && pairingSuccess;\n    }\n\n    /// @notice The fixed quicknet G2 key in the coordinate order required by EIP-2537.\n    function publicKey() internal pure returns (PointG2 memory) {\n        return PointG2({\n            x1Hi: QUICKNET_X1_HI,\n            x1Lo: QUICKNET_X1_LO,\n            x0Hi: QUICKNET_X0_HI,\n            x0Lo: QUICKNET_X0_LO,\n            y1Hi: QUICKNET_Y1_HI,\n            y1Lo: QUICKNET_Y1_LO,\n            y0Hi: QUICKNET_Y0_HI,\n            y0Lo: QUICKNET_Y0_LO\n        });\n    }\n\n    function publicKeyHash() internal pure returns (bytes32) {\n        PointG2 memory key = publicKey();\n        return keccak256(\n            abi.encode(\n                key.x1Hi, key.x1Lo, key.x0Hi, key.x0Lo, key.y1Hi, key.y1Lo, key.y0Hi, key.y0Lo\n            )\n        );\n    }\n\n    function unmarshalG1(bytes memory encoded) private pure returns (PointG1 memory point) {\n        assembly (\"memory-safe\") {\n            mstore(point, shr(128, mload(add(encoded, 0x20))))\n            mstore(add(point, 0x20), mload(add(encoded, 0x30)))\n            mstore(add(point, 0x40), shr(128, mload(add(encoded, 0x50))))\n            mstore(add(point, 0x60), mload(add(encoded, 0x60)))\n        }\n    }\n\n    /// @notice RFC 9380 hash_to_field + EIP-2537 mapping for quicknet's G1 ciphersuite.\n    function hashToPoint(bytes memory dst, bytes memory message)\n        internal\n        view\n        returns (PointG1 memory out)\n    {\n        bytes memory uniformBytes = expandMessage(dst, message);\n        bytes memory modexpInput = new bytes(225);\n        bytes memory mappedPoints = new bytes(256);\n\n        bool ok;\n        for (uint256 i; i < 2; ++i) {\n            assembly (\"memory-safe\") {\n                let fieldInput := add(add(uniformBytes, 0x20), mul(64, i))\n                let cursor := add(modexpInput, 0x20)\n\n                mstore(cursor, 64)\n                cursor := add(cursor, 0x20)\n                mstore(cursor, 1)\n                cursor := add(cursor, 0x20)\n                mstore(cursor, 64)\n                cursor := add(cursor, 0x20)\n                mcopy(cursor, fieldInput, 64)\n                cursor := add(cursor, 64)\n                mstore8(cursor, 1)\n                cursor := add(cursor, 1)\n                mstore(cursor, P_HI)\n                cursor := add(cursor, 0x20)\n                mstore(cursor, P_LO)\n\n                ok := staticcall(gas(), MODEXP, add(modexpInput, 0x20), 225, fieldInput, 64)\n                ok := and(ok, eq(returndatasize(), 64))\n            }\n            if (!ok) revert PrecompileFailure(MODEXP);\n\n            assembly (\"memory-safe\") {\n                let fieldInput := add(add(uniformBytes, 0x20), mul(64, i))\n                let mappedOutput := add(add(mappedPoints, 0x20), mul(128, i))\n                ok := staticcall(gas(), BLS12_MAP_FP_TO_G1, fieldInput, 64, mappedOutput, 128)\n                ok := and(ok, eq(returndatasize(), 128))\n            }\n            if (!ok) revert PrecompileFailure(BLS12_MAP_FP_TO_G1);\n        }\n\n        assembly (\"memory-safe\") {\n            ok := staticcall(gas(), BLS12_G1ADD, add(mappedPoints, 0x20), 256, out, 128)\n            ok := and(ok, eq(returndatasize(), 128))\n        }\n        if (!ok) revert PrecompileFailure(BLS12_G1ADD);\n    }\n\n    /// @notice RFC 9380 expand_message_xmd using SHA-256.\n    function expandMessage(bytes memory dst, bytes memory message)\n        internal\n        pure\n        returns (bytes memory out)\n    {\n        if (dst.length > 255) revert InvalidDomainLength();\n\n        bytes32 b0 = sha256(\n            abi.encodePacked(\n                bytes32(0),\n                bytes32(0),\n                message,\n                uint8(0),\n                uint8(128),\n                uint8(0),\n                dst,\n                uint8(dst.length)\n            )\n        );\n        bytes32 bi = sha256(abi.encodePacked(b0, uint8(1), dst, uint8(dst.length)));\n        out = new bytes(128);\n\n        for (uint256 i = 1; i < 4; ++i) {\n            assembly (\"memory-safe\") {\n                mstore(add(add(out, 0x20), mul(0x20, sub(i, 1))), bi)\n            }\n            bi = sha256(abi.encodePacked(b0 ^ bi, uint8(i + 1), dst, uint8(dst.length)));\n        }\n        assembly (\"memory-safe\") {\n            mstore(add(out, 0x80), bi)\n        }\n    }\n\n    function _verifyPairing(PointG1 memory signature, PointG2 memory key, PointG1 memory message)\n        private\n        view\n        returns (bool pairingSuccess, bool callSuccess)\n    {\n        uint256[24] memory input = [\n            signature.xHi,\n            signature.xLo,\n            signature.yHi,\n            signature.yLo,\n            N_G2_X0_HI,\n            N_G2_X0_LO,\n            N_G2_X1_HI,\n            N_G2_X1_LO,\n            N_G2_Y0_HI,\n            N_G2_Y0_LO,\n            N_G2_Y1_HI,\n            N_G2_Y1_LO,\n            message.xHi,\n            message.xLo,\n            message.yHi,\n            message.yLo,\n            key.x0Hi,\n            key.x0Lo,\n            key.x1Hi,\n            key.x1Lo,\n            key.y0Hi,\n            key.y0Lo,\n            key.y1Hi,\n            key.y1Lo\n        ];\n        return _callPairing(input);\n    }\n\n    function _verifyPinnedPairing(PointG1 memory signature, PointG1 memory message)\n        private\n        view\n        returns (bool pairingSuccess, bool callSuccess)\n    {\n        uint256[24] memory input = [\n            signature.xHi,\n            signature.xLo,\n            signature.yHi,\n            signature.yLo,\n            N_G2_X0_HI,\n            N_G2_X0_LO,\n            N_G2_X1_HI,\n            N_G2_X1_LO,\n            N_G2_Y0_HI,\n            N_G2_Y0_LO,\n            N_G2_Y1_HI,\n            N_G2_Y1_LO,\n            message.xHi,\n            message.xLo,\n            message.yHi,\n            message.yLo,\n            QUICKNET_X0_HI,\n            QUICKNET_X0_LO,\n            QUICKNET_X1_HI,\n            QUICKNET_X1_LO,\n            QUICKNET_Y0_HI,\n            QUICKNET_Y0_LO,\n            QUICKNET_Y1_HI,\n            QUICKNET_Y1_LO\n        ];\n        return _callPairing(input);\n    }\n\n    function _callPairing(uint256[24] memory input)\n        private\n        view\n        returns (bool pairingSuccess, bool callSuccess)\n    {\n        uint256[1] memory output;\n        assembly (\"memory-safe\") {\n            callSuccess := staticcall(\n                PAIRING_CHECK_GAS,\n                BLS12_PAIRING_CHECK,\n                input,\n                768,\n                output,\n                0x20\n            )\n            callSuccess := and(callSuccess, eq(returndatasize(), 0x20))\n        }\n        pairingSuccess = callSuccess && output[0] == 1;\n    }\n\n    function _isCanonical(PointG1 memory point) private pure returns (bool) {\n        return _isFieldElement(point.xHi, point.xLo) && _isFieldElement(point.yHi, point.yLo);\n    }\n\n    function _isFieldElement(uint128 hi, uint256 lo) private pure returns (bool) {\n        return hi < P_HI || (hi == P_HI && lo < P_LO);\n    }\n\n    function _isInfinity(PointG1 memory point) private pure returns (bool) {\n        return point.xHi == 0 && point.xLo == 0 && point.yHi == 0 && point.yLo == 0;\n    }\n\n    error InvalidDomainLength();\n    error PrecompileFailure(uint256 precompile);\n}\n"
    }
  },
  "settings": {
    "remappings": [
      "forge-std/=lib/forge-std/src/",
      "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
      "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
      "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
      "openzeppelin-contracts/=lib/openzeppelin-contracts/"
    ],
    "optimizer": {
      "enabled": true,
      "runs": 10000
    },
    "metadata": {
      "useLiteralContent": false,
      "bytecodeHash": "none",
      "appendCBOR": false
    },
    "outputSelection": {
      "*": {
        "": [
          "ast"
        ],
        "*": [
          "abi",
          "evm.bytecode.object",
          "evm.bytecode.sourceMap",
          "evm.bytecode.linkReferences",
          "evm.deployedBytecode.object",
          "evm.deployedBytecode.sourceMap",
          "evm.deployedBytecode.linkReferences",
          "evm.deployedBytecode.immutableReferences",
          "evm.methodIdentifiers",
          "metadata"
        ]
      }
    },
    "evmVersion": "prague",
    "viaIR": true,
    "libraries": {}
  }
}
