creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/ITokenURIGenerator.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >=0.8.9 <0.9.0;\n\ninterface ITokenURIGenerator {\n  function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n"
      },
      "contracts/NamedLadyRenderer.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >=0.8.9 <0.9.0;\n\n// StringLib\nimport {LibString} from \"solady/src/utils/LibString.sol\";\nimport {OwnableRoles} from \"solady/src/auth/OwnableRoles.sol\";\nimport {ITokenURIGenerator} from \"./ITokenURIGenerator.sol\";\nimport {SignatureCheckerLib} from \"solady/src/utils/SignatureCheckerLib.sol\";\n\ninterface ITokenMetadataEmit {\n  function emitMetadataUpdate(uint256 tokenId) external;\n  function ownerOf(uint256 tokenId) external view returns (address);\n  function isApprovedForAll(\n    address owner,\n    address operator\n  ) external view returns (bool);\n}\n\ncontract NamedLadyRenderer is ITokenURIGenerator, OwnableRoles {\n  using LibString for uint256;\n  using SignatureCheckerLib for address;\n\n  string private baseURI;\n  ITokenMetadataEmit public metadataEmit;\n  address private signer;\n\n  mapping(uint256 => string) private tokenUris;\n  mapping(address => uint256) private signatureNonces;\n\n  error NotTokenOwnerOrApproved();\n  error InvalidSignature();\n\n  constructor(string memory _baseURI, address emitableNft, address _signer) {\n    baseURI = _baseURI;\n    metadataEmit = ITokenMetadataEmit(emitableNft);\n    signer = _signer;\n    _grantRoles(msg.sender, TRUST_AND_SAFETY | METADATA | SIGNER);\n    _initializeOwner(msg.sender);\n  }\n\n  uint256 internal constant TRUST_AND_SAFETY = 1 << 0;\n\n  /**\n   * @dev Returns the role that controls the trust and safety of the contract. This role can clear the metadata of a token in cases of vulgar or illegal content.\n   */\n  function trustRole() public pure returns (uint256) {\n    return TRUST_AND_SAFETY;\n  }\n\n  uint256 internal constant METADATA = 1 << 1;\n\n  /*\n   * @dev Returns the role that controls the metadata of the contract. This role can set the base URI.\n   */\n  function metadataRole() public pure returns (uint256) {\n    return METADATA;\n  }\n\n  uint256 internal constant SIGNER = 1 << 2;\n\n  /*\n   * @dev Returns the role that controls the signer of the contract. This role can set the signer address.\n   */\n  function signerRole() public pure returns (uint256) {\n    return SIGNER;\n  }\n\n  /**\n   * @dev Throws if called by any account other than the owner or an approved operator of the token.\n   */\n  modifier onlyTokenOwnerOrApproved(uint256 tokenId) {\n    address owner = metadataEmit.ownerOf(tokenId);\n    if (\n      msg.sender != owner && !metadataEmit.isApprovedForAll(owner, msg.sender)\n    ) {\n      revert NotTokenOwnerOrApproved();\n    }\n    _;\n  }\n\n  /**\n   * @dev Returns the URI for a token ID.\n   */\n  function tokenURI(\n    uint256 tokenId\n  ) external view override returns (string memory) {\n    if (bytes(tokenUris[tokenId]).length > 0) {\n      return tokenUris[tokenId];\n    }\n    return string(abi.encodePacked(baseURI, tokenId.toString()));\n  }\n\n  /**\n   * @dev Sets the token URI for a token.\n   * @param tokenId uint256 ID of the token to set its URI.\n   * @param uri string URI to assign.\n   * @param signature bytes Signature of the update request.\n   */\n  function setTokenUri(\n    uint256 tokenId,\n    string calldata uri,\n    bytes calldata signature\n  ) external onlyTokenOwnerOrApproved(tokenId) {\n    bytes32 hash = hashUpdateRequest(tokenId, uri, signatureNonces[msg.sender]);\n    signatureNonces[msg.sender]++;\n    if (\n      !signer.isValidSignatureNow(\n        SignatureCheckerLib.toEthSignedMessageHash(hash),\n        signature\n      )\n    ) {\n      revert InvalidSignature();\n    }\n    tokenUris[tokenId] = uri;\n    metadataEmit.emitMetadataUpdate(tokenId);\n  }\n\n  /**\n   * @dev Returns the current nonce for a given address.\n   */\n  function currentNonce(address sender) external view returns (uint256) {\n    return signatureNonces[sender];\n  }\n\n  /**\n   * @dev Bans a token by setting its URI to an empty string. To be only called by the trust and safety role in cases of vulgar or illegal content.\n   * @param tokenId uint256 ID of the token to ban.\n   */\n  function ban(uint256 tokenId) external onlyRolesOrOwner(TRUST_AND_SAFETY) {\n    tokenUris[tokenId] = \"\";\n    metadataEmit.emitMetadataUpdate(tokenId);\n  }\n\n  /**\n   * @dev Sets the base URI for all token IDs.\n   * @param _baseURI string URI to assign.\n   */\n  function setBaseURI(\n    string memory _baseURI\n  ) external onlyRolesOrOwner(METADATA) {\n    baseURI = _baseURI;\n  }\n\n  /**\n   * @dev Sets the signer address.\n   * @param _signer address Signer address to assign.\n   */\n  function setSigner(address _signer) external onlyRolesOrOwner(SIGNER) {\n    signer = _signer;\n  }\n\n  /**\n   * @dev Returns the hash of an update request.\n   * @param tokenId uint256 ID of the token to set its URI.\n   * @param uri string URI to assign.\n   * @param nonce uint256 Nonce of the update request.\n   */\n  function hashUpdateRequest(\n    uint256 tokenId,\n    string calldata uri,\n    uint256 nonce\n  ) public pure returns (bytes32) {\n    return keccak256(abi.encodePacked(tokenId, uri, nonce));\n  }\n}\n"
      },
      "solady/src/auth/Ownable.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Simple single owner authorization mixin.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)\n///\n/// @dev Note:\n/// This implementation does NOT auto-initialize the owner to `msg.sender`.\n/// You MUST call the `_initializeOwner` in the constructor / initializer.\n///\n/// While the ownable portion follows\n/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,\n/// the nomenclature for the 2-step ownership handover may be unique to this codebase.\nabstract contract Ownable {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                       CUSTOM ERRORS                        */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The caller is not authorized to call the function.\n    error Unauthorized();\n\n    /// @dev The `newOwner` cannot be the zero address.\n    error NewOwnerIsZeroAddress();\n\n    /// @dev The `pendingOwner` does not have a valid handover request.\n    error NoHandoverRequest();\n\n    /// @dev Cannot double-initialize.\n    error AlreadyInitialized();\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                           EVENTS                           */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The ownership is transferred from `oldOwner` to `newOwner`.\n    /// This event is intentionally kept the same as OpenZeppelin's Ownable to be\n    /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),\n    /// despite it not being as lightweight as a single argument event.\n    event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);\n\n    /// @dev An ownership handover to `pendingOwner` has been requested.\n    event OwnershipHandoverRequested(address indexed pendingOwner);\n\n    /// @dev The ownership handover to `pendingOwner` has been canceled.\n    event OwnershipHandoverCanceled(address indexed pendingOwner);\n\n    /// @dev `keccak256(bytes(\"OwnershipTransferred(address,address)\"))`.\n    uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =\n        0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;\n\n    /// @dev `keccak256(bytes(\"OwnershipHandoverRequested(address)\"))`.\n    uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =\n        0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;\n\n    /// @dev `keccak256(bytes(\"OwnershipHandoverCanceled(address)\"))`.\n    uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =\n        0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                          STORAGE                           */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The owner slot is given by:\n    /// `bytes32(~uint256(uint32(bytes4(keccak256(\"_OWNER_SLOT_NOT\")))))`.\n    /// It is intentionally chosen to be a high value\n    /// to avoid collision with lower slots.\n    /// The choice of manual storage layout is to enable compatibility\n    /// with both regular and upgradeable contracts.\n    bytes32 internal constant _OWNER_SLOT =\n        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;\n\n    /// The ownership handover slot of `newOwner` is given by:\n    /// ```\n    ///     mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))\n    ///     let handoverSlot := keccak256(0x00, 0x20)\n    /// ```\n    /// It stores the expiry timestamp of the two-step ownership handover.\n    uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                     INTERNAL FUNCTIONS                     */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Override to return true to make `_initializeOwner` prevent double-initialization.\n    function _guardInitializeOwner() internal pure virtual returns (bool guard) {}\n\n    /// @dev Initializes the owner directly without authorization guard.\n    /// This function must be called upon initialization,\n    /// regardless of whether the contract is upgradeable or not.\n    /// This is to enable generalization to both regular and upgradeable contracts,\n    /// and to save gas in case the initial owner is not the caller.\n    /// For performance reasons, this function will not check if there\n    /// is an existing owner.\n    function _initializeOwner(address newOwner) internal virtual {\n        if (_guardInitializeOwner()) {\n            /// @solidity memory-safe-assembly\n            assembly {\n                let ownerSlot := _OWNER_SLOT\n                if sload(ownerSlot) {\n                    mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.\n                    revert(0x1c, 0x04)\n                }\n                // Clean the upper 96 bits.\n                newOwner := shr(96, shl(96, newOwner))\n                // Store the new value.\n                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))\n                // Emit the {OwnershipTransferred} event.\n                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)\n            }\n        } else {\n            /// @solidity memory-safe-assembly\n            assembly {\n                // Clean the upper 96 bits.\n                newOwner := shr(96, shl(96, newOwner))\n                // Store the new value.\n                sstore(_OWNER_SLOT, newOwner)\n                // Emit the {OwnershipTransferred} event.\n                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)\n            }\n        }\n    }\n\n    /// @dev Sets the owner directly without authorization guard.\n    function _setOwner(address newOwner) internal virtual {\n        if (_guardInitializeOwner()) {\n            /// @solidity memory-safe-assembly\n            assembly {\n                let ownerSlot := _OWNER_SLOT\n                // Clean the upper 96 bits.\n                newOwner := shr(96, shl(96, newOwner))\n                // Emit the {OwnershipTransferred} event.\n                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)\n                // Store the new value.\n                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))\n            }\n        } else {\n            /// @solidity memory-safe-assembly\n            assembly {\n                let ownerSlot := _OWNER_SLOT\n                // Clean the upper 96 bits.\n                newOwner := shr(96, shl(96, newOwner))\n                // Emit the {OwnershipTransferred} event.\n                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)\n                // Store the new value.\n                sstore(ownerSlot, newOwner)\n            }\n        }\n    }\n\n    /// @dev Throws if the sender is not the owner.\n    function _checkOwner() internal view virtual {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // If the caller is not the stored owner, revert.\n            if iszero(eq(caller(), sload(_OWNER_SLOT))) {\n                mstore(0x00, 0x82b42900) // `Unauthorized()`.\n                revert(0x1c, 0x04)\n            }\n        }\n    }\n\n    /// @dev Returns how long a two-step ownership handover is valid for in seconds.\n    /// Override to return a different value if needed.\n    /// Made internal to conserve bytecode. Wrap it in a public function if needed.\n    function _ownershipHandoverValidFor() internal view virtual returns (uint64) {\n        return 48 * 3600;\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                  PUBLIC UPDATE FUNCTIONS                   */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Allows the owner to transfer the ownership to `newOwner`.\n    function transferOwnership(address newOwner) public payable virtual onlyOwner {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if iszero(shl(96, newOwner)) {\n                mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.\n                revert(0x1c, 0x04)\n            }\n        }\n        _setOwner(newOwner);\n    }\n\n    /// @dev Allows the owner to renounce their ownership.\n    function renounceOwnership() public payable virtual onlyOwner {\n        _setOwner(address(0));\n    }\n\n    /// @dev Request a two-step ownership handover to the caller.\n    /// The request will automatically expire in 48 hours (172800 seconds) by default.\n    function requestOwnershipHandover() public payable virtual {\n        unchecked {\n            uint256 expires = block.timestamp + _ownershipHandoverValidFor();\n            /// @solidity memory-safe-assembly\n            assembly {\n                // Compute and set the handover slot to `expires`.\n                mstore(0x0c, _HANDOVER_SLOT_SEED)\n                mstore(0x00, caller())\n                sstore(keccak256(0x0c, 0x20), expires)\n                // Emit the {OwnershipHandoverRequested} event.\n                log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())\n            }\n        }\n    }\n\n    /// @dev Cancels the two-step ownership handover to the caller, if any.\n    function cancelOwnershipHandover() public payable virtual {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Compute and set the handover slot to 0.\n            mstore(0x0c, _HANDOVER_SLOT_SEED)\n            mstore(0x00, caller())\n            sstore(keccak256(0x0c, 0x20), 0)\n            // Emit the {OwnershipHandoverCanceled} event.\n            log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())\n        }\n    }\n\n    /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.\n    /// Reverts if there is no existing ownership handover requested by `pendingOwner`.\n    function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Compute and set the handover slot to 0.\n            mstore(0x0c, _HANDOVER_SLOT_SEED)\n            mstore(0x00, pendingOwner)\n            let handoverSlot := keccak256(0x0c, 0x20)\n            // If the handover does not exist, or has expired.\n            if gt(timestamp(), sload(handoverSlot)) {\n                mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.\n                revert(0x1c, 0x04)\n            }\n            // Set the handover slot to 0.\n            sstore(handoverSlot, 0)\n        }\n        _setOwner(pendingOwner);\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                   PUBLIC READ FUNCTIONS                    */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns the owner of the contract.\n    function owner() public view virtual returns (address result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := sload(_OWNER_SLOT)\n        }\n    }\n\n    /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.\n    function ownershipHandoverExpiresAt(address pendingOwner)\n        public\n        view\n        virtual\n        returns (uint256 result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Compute the handover slot.\n            mstore(0x0c, _HANDOVER_SLOT_SEED)\n            mstore(0x00, pendingOwner)\n            // Load the handover slot.\n            result := sload(keccak256(0x0c, 0x20))\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                         MODIFIERS                          */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Marks a function as only callable by the owner.\n    modifier onlyOwner() virtual {\n        _checkOwner();\n        _;\n    }\n}\n"
      },
      "solady/src/auth/OwnableRoles.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport {Ownable} from \"./Ownable.sol\";\n\n/// @notice Simple single owner and multiroles authorization mixin.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)\n/// @dev While the ownable portion follows [EIP-173](https://eips.ethereum.org/EIPS/eip-173)\n/// for compatibility, the nomenclature for the 2-step ownership handover and roles\n/// may be unique to this codebase.\nabstract contract OwnableRoles is Ownable {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                           EVENTS                           */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The `user`'s roles is updated to `roles`.\n    /// Each bit of `roles` represents whether the role is set.\n    event RolesUpdated(address indexed user, uint256 indexed roles);\n\n    /// @dev `keccak256(bytes(\"RolesUpdated(address,uint256)\"))`.\n    uint256 private constant _ROLES_UPDATED_EVENT_SIGNATURE =\n        0x715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                          STORAGE                           */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The role slot of `user` is given by:\n    /// ```\n    ///     mstore(0x00, or(shl(96, user), _ROLE_SLOT_SEED))\n    ///     let roleSlot := keccak256(0x00, 0x20)\n    /// ```\n    /// This automatically ignores the upper bits of the `user` in case\n    /// they are not clean, as well as keep the `keccak256` under 32-bytes.\n    ///\n    /// Note: This is equivalent to `uint32(bytes4(keccak256(\"_OWNER_SLOT_NOT\")))`.\n    uint256 private constant _ROLE_SLOT_SEED = 0x8b78c6d8;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                     INTERNAL FUNCTIONS                     */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Overwrite the roles directly without authorization guard.\n    function _setRoles(address user, uint256 roles) internal virtual {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x0c, _ROLE_SLOT_SEED)\n            mstore(0x00, user)\n            // Store the new value.\n            sstore(keccak256(0x0c, 0x20), roles)\n            // Emit the {RolesUpdated} event.\n            log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), roles)\n        }\n    }\n\n    /// @dev Updates the roles directly without authorization guard.\n    /// If `on` is true, each set bit of `roles` will be turned on,\n    /// otherwise, each set bit of `roles` will be turned off.\n    function _updateRoles(address user, uint256 roles, bool on) internal virtual {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x0c, _ROLE_SLOT_SEED)\n            mstore(0x00, user)\n            let roleSlot := keccak256(0x0c, 0x20)\n            // Load the current value.\n            let current := sload(roleSlot)\n            // Compute the updated roles if `on` is true.\n            let updated := or(current, roles)\n            // Compute the updated roles if `on` is false.\n            // Use `and` to compute the intersection of `current` and `roles`,\n            // `xor` it with `current` to flip the bits in the intersection.\n            if iszero(on) { updated := xor(current, and(current, roles)) }\n            // Then, store the new value.\n            sstore(roleSlot, updated)\n            // Emit the {RolesUpdated} event.\n            log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), updated)\n        }\n    }\n\n    /// @dev Grants the roles directly without authorization guard.\n    /// Each bit of `roles` represents the role to turn on.\n    function _grantRoles(address user, uint256 roles) internal virtual {\n        _updateRoles(user, roles, true);\n    }\n\n    /// @dev Removes the roles directly without authorization guard.\n    /// Each bit of `roles` represents the role to turn off.\n    function _removeRoles(address user, uint256 roles) internal virtual {\n        _updateRoles(user, roles, false);\n    }\n\n    /// @dev Throws if the sender does not have any of the `roles`.\n    function _checkRoles(uint256 roles) internal view virtual {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Compute the role slot.\n            mstore(0x0c, _ROLE_SLOT_SEED)\n            mstore(0x00, caller())\n            // Load the stored value, and if the `and` intersection\n            // of the value and `roles` is zero, revert.\n            if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {\n                mstore(0x00, 0x82b42900) // `Unauthorized()`.\n                revert(0x1c, 0x04)\n            }\n        }\n    }\n\n    /// @dev Throws if the sender is not the owner,\n    /// and does not have any of the `roles`.\n    /// Checks for ownership first, then lazily checks for roles.\n    function _checkOwnerOrRoles(uint256 roles) internal view virtual {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // If the caller is not the stored owner.\n            // Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`.\n            if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) {\n                // Compute the role slot.\n                mstore(0x0c, _ROLE_SLOT_SEED)\n                mstore(0x00, caller())\n                // Load the stored value, and if the `and` intersection\n                // of the value and `roles` is zero, revert.\n                if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {\n                    mstore(0x00, 0x82b42900) // `Unauthorized()`.\n                    revert(0x1c, 0x04)\n                }\n            }\n        }\n    }\n\n    /// @dev Throws if the sender does not have any of the `roles`,\n    /// and is not the owner.\n    /// Checks for roles first, then lazily checks for ownership.\n    function _checkRolesOrOwner(uint256 roles) internal view virtual {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Compute the role slot.\n            mstore(0x0c, _ROLE_SLOT_SEED)\n            mstore(0x00, caller())\n            // Load the stored value, and if the `and` intersection\n            // of the value and `roles` is zero, revert.\n            if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {\n                // If the caller is not the stored owner.\n                // Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`.\n                if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) {\n                    mstore(0x00, 0x82b42900) // `Unauthorized()`.\n                    revert(0x1c, 0x04)\n                }\n            }\n        }\n    }\n\n    /// @dev Convenience function to return a `roles` bitmap from an array of `ordinals`.\n    /// This is meant for frontends like Etherscan, and is therefore not fully optimized.\n    /// Not recommended to be called on-chain.\n    /// Made internal to conserve bytecode. Wrap it in a public function if needed.\n    function _rolesFromOrdinals(uint8[] memory ordinals) internal pure returns (uint256 roles) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            for { let i := shl(5, mload(ordinals)) } i { i := sub(i, 0x20) } {\n                // We don't need to mask the values of `ordinals`, as Solidity\n                // cleans dirty upper bits when storing variables into memory.\n                roles := or(shl(mload(add(ordinals, i)), 1), roles)\n            }\n        }\n    }\n\n    /// @dev Convenience function to return an array of `ordinals` from the `roles` bitmap.\n    /// This is meant for frontends like Etherscan, and is therefore not fully optimized.\n    /// Not recommended to be called on-chain.\n    /// Made internal to conserve bytecode. Wrap it in a public function if needed.\n    function _ordinalsFromRoles(uint256 roles) internal pure returns (uint8[] memory ordinals) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Grab the pointer to the free memory.\n            ordinals := mload(0x40)\n            let ptr := add(ordinals, 0x20)\n            let o := 0\n            // The absence of lookup tables, De Bruijn, etc., here is intentional for\n            // smaller bytecode, as this function is not meant to be called on-chain.\n            for { let t := roles } 1 {} {\n                mstore(ptr, o)\n                // `shr` 5 is equivalent to multiplying by 0x20.\n                // Push back into the ordinals array if the bit is set.\n                ptr := add(ptr, shl(5, and(t, 1)))\n                o := add(o, 1)\n                t := shr(o, roles)\n                if iszero(t) { break }\n            }\n            // Store the length of `ordinals`.\n            mstore(ordinals, shr(5, sub(ptr, add(ordinals, 0x20))))\n            // Allocate the memory.\n            mstore(0x40, ptr)\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                  PUBLIC UPDATE FUNCTIONS                   */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Allows the owner to grant `user` `roles`.\n    /// If the `user` already has a role, then it will be an no-op for the role.\n    function grantRoles(address user, uint256 roles) public payable virtual onlyOwner {\n        _grantRoles(user, roles);\n    }\n\n    /// @dev Allows the owner to remove `user` `roles`.\n    /// If the `user` does not have a role, then it will be an no-op for the role.\n    function revokeRoles(address user, uint256 roles) public payable virtual onlyOwner {\n        _removeRoles(user, roles);\n    }\n\n    /// @dev Allow the caller to remove their own roles.\n    /// If the caller does not have a role, then it will be an no-op for the role.\n    function renounceRoles(uint256 roles) public payable virtual {\n        _removeRoles(msg.sender, roles);\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                   PUBLIC READ FUNCTIONS                    */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns the roles of `user`.\n    function rolesOf(address user) public view virtual returns (uint256 roles) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Compute the role slot.\n            mstore(0x0c, _ROLE_SLOT_SEED)\n            mstore(0x00, user)\n            // Load the stored value.\n            roles := sload(keccak256(0x0c, 0x20))\n        }\n    }\n\n    /// @dev Returns whether `user` has any of `roles`.\n    function hasAnyRole(address user, uint256 roles) public view virtual returns (bool) {\n        return rolesOf(user) & roles != 0;\n    }\n\n    /// @dev Returns whether `user` has all of `roles`.\n    function hasAllRoles(address user, uint256 roles) public view virtual returns (bool) {\n        return rolesOf(user) & roles == roles;\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                         MODIFIERS                          */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Marks a function as only callable by an account with `roles`.\n    modifier onlyRoles(uint256 roles) virtual {\n        _checkRoles(roles);\n        _;\n    }\n\n    /// @dev Marks a function as only callable by the owner or by an account\n    /// with `roles`. Checks for ownership first, then lazily checks for roles.\n    modifier onlyOwnerOrRoles(uint256 roles) virtual {\n        _checkOwnerOrRoles(roles);\n        _;\n    }\n\n    /// @dev Marks a function as only callable by an account with `roles`\n    /// or the owner. Checks for roles first, then lazily checks for ownership.\n    modifier onlyRolesOrOwner(uint256 roles) virtual {\n        _checkRolesOrOwner(roles);\n        _;\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                       ROLE CONSTANTS                       */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    // IYKYK\n\n    uint256 internal constant _ROLE_0 = 1 << 0;\n    uint256 internal constant _ROLE_1 = 1 << 1;\n    uint256 internal constant _ROLE_2 = 1 << 2;\n    uint256 internal constant _ROLE_3 = 1 << 3;\n    uint256 internal constant _ROLE_4 = 1 << 4;\n    uint256 internal constant _ROLE_5 = 1 << 5;\n    uint256 internal constant _ROLE_6 = 1 << 6;\n    uint256 internal constant _ROLE_7 = 1 << 7;\n    uint256 internal constant _ROLE_8 = 1 << 8;\n    uint256 internal constant _ROLE_9 = 1 << 9;\n    uint256 internal constant _ROLE_10 = 1 << 10;\n    uint256 internal constant _ROLE_11 = 1 << 11;\n    uint256 internal constant _ROLE_12 = 1 << 12;\n    uint256 internal constant _ROLE_13 = 1 << 13;\n    uint256 internal constant _ROLE_14 = 1 << 14;\n    uint256 internal constant _ROLE_15 = 1 << 15;\n    uint256 internal constant _ROLE_16 = 1 << 16;\n    uint256 internal constant _ROLE_17 = 1 << 17;\n    uint256 internal constant _ROLE_18 = 1 << 18;\n    uint256 internal constant _ROLE_19 = 1 << 19;\n    uint256 internal constant _ROLE_20 = 1 << 20;\n    uint256 internal constant _ROLE_21 = 1 << 21;\n    uint256 internal constant _ROLE_22 = 1 << 22;\n    uint256 internal constant _ROLE_23 = 1 << 23;\n    uint256 internal constant _ROLE_24 = 1 << 24;\n    uint256 internal constant _ROLE_25 = 1 << 25;\n    uint256 internal constant _ROLE_26 = 1 << 26;\n    uint256 internal constant _ROLE_27 = 1 << 27;\n    uint256 internal constant _ROLE_28 = 1 << 28;\n    uint256 internal constant _ROLE_29 = 1 << 29;\n    uint256 internal constant _ROLE_30 = 1 << 30;\n    uint256 internal constant _ROLE_31 = 1 << 31;\n    uint256 internal constant _ROLE_32 = 1 << 32;\n    uint256 internal constant _ROLE_33 = 1 << 33;\n    uint256 internal constant _ROLE_34 = 1 << 34;\n    uint256 internal constant _ROLE_35 = 1 << 35;\n    uint256 internal constant _ROLE_36 = 1 << 36;\n    uint256 internal constant _ROLE_37 = 1 << 37;\n    uint256 internal constant _ROLE_38 = 1 << 38;\n    uint256 internal constant _ROLE_39 = 1 << 39;\n    uint256 internal constant _ROLE_40 = 1 << 40;\n    uint256 internal constant _ROLE_41 = 1 << 41;\n    uint256 internal constant _ROLE_42 = 1 << 42;\n    uint256 internal constant _ROLE_43 = 1 << 43;\n    uint256 internal constant _ROLE_44 = 1 << 44;\n    uint256 internal constant _ROLE_45 = 1 << 45;\n    uint256 internal constant _ROLE_46 = 1 << 46;\n    uint256 internal constant _ROLE_47 = 1 << 47;\n    uint256 internal constant _ROLE_48 = 1 << 48;\n    uint256 internal constant _ROLE_49 = 1 << 49;\n    uint256 internal constant _ROLE_50 = 1 << 50;\n    uint256 internal constant _ROLE_51 = 1 << 51;\n    uint256 internal constant _ROLE_52 = 1 << 52;\n    uint256 internal constant _ROLE_53 = 1 << 53;\n    uint256 internal constant _ROLE_54 = 1 << 54;\n    uint256 internal constant _ROLE_55 = 1 << 55;\n    uint256 internal constant _ROLE_56 = 1 << 56;\n    uint256 internal constant _ROLE_57 = 1 << 57;\n    uint256 internal constant _ROLE_58 = 1 << 58;\n    uint256 internal constant _ROLE_59 = 1 << 59;\n    uint256 internal constant _ROLE_60 = 1 << 60;\n    uint256 internal constant _ROLE_61 = 1 << 61;\n    uint256 internal constant _ROLE_62 = 1 << 62;\n    uint256 internal constant _ROLE_63 = 1 << 63;\n    uint256 internal constant _ROLE_64 = 1 << 64;\n    uint256 internal constant _ROLE_65 = 1 << 65;\n    uint256 internal constant _ROLE_66 = 1 << 66;\n    uint256 internal constant _ROLE_67 = 1 << 67;\n    uint256 internal constant _ROLE_68 = 1 << 68;\n    uint256 internal constant _ROLE_69 = 1 << 69;\n    uint256 internal constant _ROLE_70 = 1 << 70;\n    uint256 internal constant _ROLE_71 = 1 << 71;\n    uint256 internal constant _ROLE_72 = 1 << 72;\n    uint256 internal constant _ROLE_73 = 1 << 73;\n    uint256 internal constant _ROLE_74 = 1 << 74;\n    uint256 internal constant _ROLE_75 = 1 << 75;\n    uint256 internal constant _ROLE_76 = 1 << 76;\n    uint256 internal constant _ROLE_77 = 1 << 77;\n    uint256 internal constant _ROLE_78 = 1 << 78;\n    uint256 internal constant _ROLE_79 = 1 << 79;\n    uint256 internal constant _ROLE_80 = 1 << 80;\n    uint256 internal constant _ROLE_81 = 1 << 81;\n    uint256 internal constant _ROLE_82 = 1 << 82;\n    uint256 internal constant _ROLE_83 = 1 << 83;\n    uint256 internal constant _ROLE_84 = 1 << 84;\n    uint256 internal constant _ROLE_85 = 1 << 85;\n    uint256 internal constant _ROLE_86 = 1 << 86;\n    uint256 internal constant _ROLE_87 = 1 << 87;\n    uint256 internal constant _ROLE_88 = 1 << 88;\n    uint256 internal constant _ROLE_89 = 1 << 89;\n    uint256 internal constant _ROLE_90 = 1 << 90;\n    uint256 internal constant _ROLE_91 = 1 << 91;\n    uint256 internal constant _ROLE_92 = 1 << 92;\n    uint256 internal constant _ROLE_93 = 1 << 93;\n    uint256 internal constant _ROLE_94 = 1 << 94;\n    uint256 internal constant _ROLE_95 = 1 << 95;\n    uint256 internal constant _ROLE_96 = 1 << 96;\n    uint256 internal constant _ROLE_97 = 1 << 97;\n    uint256 internal constant _ROLE_98 = 1 << 98;\n    uint256 internal constant _ROLE_99 = 1 << 99;\n    uint256 internal constant _ROLE_100 = 1 << 100;\n    uint256 internal constant _ROLE_101 = 1 << 101;\n    uint256 internal constant _ROLE_102 = 1 << 102;\n    uint256 internal constant _ROLE_103 = 1 << 103;\n    uint256 internal constant _ROLE_104 = 1 << 104;\n    uint256 internal constant _ROLE_105 = 1 << 105;\n    uint256 internal constant _ROLE_106 = 1 << 106;\n    uint256 internal constant _ROLE_107 = 1 << 107;\n    uint256 internal constant _ROLE_108 = 1 << 108;\n    uint256 internal constant _ROLE_109 = 1 << 109;\n    uint256 internal constant _ROLE_110 = 1 << 110;\n    uint256 internal constant _ROLE_111 = 1 << 111;\n    uint256 internal constant _ROLE_112 = 1 << 112;\n    uint256 internal constant _ROLE_113 = 1 << 113;\n    uint256 internal constant _ROLE_114 = 1 << 114;\n    uint256 internal constant _ROLE_115 = 1 << 115;\n    uint256 internal constant _ROLE_116 = 1 << 116;\n    uint256 internal constant _ROLE_117 = 1 << 117;\n    uint256 internal constant _ROLE_118 = 1 << 118;\n    uint256 internal constant _ROLE_119 = 1 << 119;\n    uint256 internal constant _ROLE_120 = 1 << 120;\n    uint256 internal constant _ROLE_121 = 1 << 121;\n    uint256 internal constant _ROLE_122 = 1 << 122;\n    uint256 internal constant _ROLE_123 = 1 << 123;\n    uint256 internal constant _ROLE_124 = 1 << 124;\n    uint256 internal constant _ROLE_125 = 1 << 125;\n    uint256 internal constant _ROLE_126 = 1 << 126;\n    uint256 internal constant _ROLE_127 = 1 << 127;\n    uint256 internal constant _ROLE_128 = 1 << 128;\n    uint256 internal constant _ROLE_129 = 1 << 129;\n    uint256 internal constant _ROLE_130 = 1 << 130;\n    uint256 internal constant _ROLE_131 = 1 << 131;\n    uint256 internal constant _ROLE_132 = 1 << 132;\n    uint256 internal constant _ROLE_133 = 1 << 133;\n    uint256 internal constant _ROLE_134 = 1 << 134;\n    uint256 internal constant _ROLE_135 = 1 << 135;\n    uint256 internal constant _ROLE_136 = 1 << 136;\n    uint256 internal constant _ROLE_137 = 1 << 137;\n    uint256 internal constant _ROLE_138 = 1 << 138;\n    uint256 internal constant _ROLE_139 = 1 << 139;\n    uint256 internal constant _ROLE_140 = 1 << 140;\n    uint256 internal constant _ROLE_141 = 1 << 141;\n    uint256 internal constant _ROLE_142 = 1 << 142;\n    uint256 internal constant _ROLE_143 = 1 << 143;\n    uint256 internal constant _ROLE_144 = 1 << 144;\n    uint256 internal constant _ROLE_145 = 1 << 145;\n    uint256 internal constant _ROLE_146 = 1 << 146;\n    uint256 internal constant _ROLE_147 = 1 << 147;\n    uint256 internal constant _ROLE_148 = 1 << 148;\n    uint256 internal constant _ROLE_149 = 1 << 149;\n    uint256 internal constant _ROLE_150 = 1 << 150;\n    uint256 internal constant _ROLE_151 = 1 << 151;\n    uint256 internal constant _ROLE_152 = 1 << 152;\n    uint256 internal constant _ROLE_153 = 1 << 153;\n    uint256 internal constant _ROLE_154 = 1 << 154;\n    uint256 internal constant _ROLE_155 = 1 << 155;\n    uint256 internal constant _ROLE_156 = 1 << 156;\n    uint256 internal constant _ROLE_157 = 1 << 157;\n    uint256 internal constant _ROLE_158 = 1 << 158;\n    uint256 internal constant _ROLE_159 = 1 << 159;\n    uint256 internal constant _ROLE_160 = 1 << 160;\n    uint256 internal constant _ROLE_161 = 1 << 161;\n    uint256 internal constant _ROLE_162 = 1 << 162;\n    uint256 internal constant _ROLE_163 = 1 << 163;\n    uint256 internal constant _ROLE_164 = 1 << 164;\n    uint256 internal constant _ROLE_165 = 1 << 165;\n    uint256 internal constant _ROLE_166 = 1 << 166;\n    uint256 internal constant _ROLE_167 = 1 << 167;\n    uint256 internal constant _ROLE_168 = 1 << 168;\n    uint256 internal constant _ROLE_169 = 1 << 169;\n    uint256 internal constant _ROLE_170 = 1 << 170;\n    uint256 internal constant _ROLE_171 = 1 << 171;\n    uint256 internal constant _ROLE_172 = 1 << 172;\n    uint256 internal constant _ROLE_173 = 1 << 173;\n    uint256 internal constant _ROLE_174 = 1 << 174;\n    uint256 internal constant _ROLE_175 = 1 << 175;\n    uint256 internal constant _ROLE_176 = 1 << 176;\n    uint256 internal constant _ROLE_177 = 1 << 177;\n    uint256 internal constant _ROLE_178 = 1 << 178;\n    uint256 internal constant _ROLE_179 = 1 << 179;\n    uint256 internal constant _ROLE_180 = 1 << 180;\n    uint256 internal constant _ROLE_181 = 1 << 181;\n    uint256 internal constant _ROLE_182 = 1 << 182;\n    uint256 internal constant _ROLE_183 = 1 << 183;\n    uint256 internal constant _ROLE_184 = 1 << 184;\n    uint256 internal constant _ROLE_185 = 1 << 185;\n    uint256 internal constant _ROLE_186 = 1 << 186;\n    uint256 internal constant _ROLE_187 = 1 << 187;\n    uint256 internal constant _ROLE_188 = 1 << 188;\n    uint256 internal constant _ROLE_189 = 1 << 189;\n    uint256 internal constant _ROLE_190 = 1 << 190;\n    uint256 internal constant _ROLE_191 = 1 << 191;\n    uint256 internal constant _ROLE_192 = 1 << 192;\n    uint256 internal constant _ROLE_193 = 1 << 193;\n    uint256 internal constant _ROLE_194 = 1 << 194;\n    uint256 internal constant _ROLE_195 = 1 << 195;\n    uint256 internal constant _ROLE_196 = 1 << 196;\n    uint256 internal constant _ROLE_197 = 1 << 197;\n    uint256 internal constant _ROLE_198 = 1 << 198;\n    uint256 internal constant _ROLE_199 = 1 << 199;\n    uint256 internal constant _ROLE_200 = 1 << 200;\n    uint256 internal constant _ROLE_201 = 1 << 201;\n    uint256 internal constant _ROLE_202 = 1 << 202;\n    uint256 internal constant _ROLE_203 = 1 << 203;\n    uint256 internal constant _ROLE_204 = 1 << 204;\n    uint256 internal constant _ROLE_205 = 1 << 205;\n    uint256 internal constant _ROLE_206 = 1 << 206;\n    uint256 internal constant _ROLE_207 = 1 << 207;\n    uint256 internal constant _ROLE_208 = 1 << 208;\n    uint256 internal constant _ROLE_209 = 1 << 209;\n    uint256 internal constant _ROLE_210 = 1 << 210;\n    uint256 internal constant _ROLE_211 = 1 << 211;\n    uint256 internal constant _ROLE_212 = 1 << 212;\n    uint256 internal constant _ROLE_213 = 1 << 213;\n    uint256 internal constant _ROLE_214 = 1 << 214;\n    uint256 internal constant _ROLE_215 = 1 << 215;\n    uint256 internal constant _ROLE_216 = 1 << 216;\n    uint256 internal constant _ROLE_217 = 1 << 217;\n    uint256 internal constant _ROLE_218 = 1 << 218;\n    uint256 internal constant _ROLE_219 = 1 << 219;\n    uint256 internal constant _ROLE_220 = 1 << 220;\n    uint256 internal constant _ROLE_221 = 1 << 221;\n    uint256 internal constant _ROLE_222 = 1 << 222;\n    uint256 internal constant _ROLE_223 = 1 << 223;\n    uint256 internal constant _ROLE_224 = 1 << 224;\n    uint256 internal constant _ROLE_225 = 1 << 225;\n    uint256 internal constant _ROLE_226 = 1 << 226;\n    uint256 internal constant _ROLE_227 = 1 << 227;\n    uint256 internal constant _ROLE_228 = 1 << 228;\n    uint256 internal constant _ROLE_229 = 1 << 229;\n    uint256 internal constant _ROLE_230 = 1 << 230;\n    uint256 internal constant _ROLE_231 = 1 << 231;\n    uint256 internal constant _ROLE_232 = 1 << 232;\n    uint256 internal constant _ROLE_233 = 1 << 233;\n    uint256 internal constant _ROLE_234 = 1 << 234;\n    uint256 internal constant _ROLE_235 = 1 << 235;\n    uint256 internal constant _ROLE_236 = 1 << 236;\n    uint256 internal constant _ROLE_237 = 1 << 237;\n    uint256 internal constant _ROLE_238 = 1 << 238;\n    uint256 internal constant _ROLE_239 = 1 << 239;\n    uint256 internal constant _ROLE_240 = 1 << 240;\n    uint256 internal constant _ROLE_241 = 1 << 241;\n    uint256 internal constant _ROLE_242 = 1 << 242;\n    uint256 internal constant _ROLE_243 = 1 << 243;\n    uint256 internal constant _ROLE_244 = 1 << 244;\n    uint256 internal constant _ROLE_245 = 1 << 245;\n    uint256 internal constant _ROLE_246 = 1 << 246;\n    uint256 internal constant _ROLE_247 = 1 << 247;\n    uint256 internal constant _ROLE_248 = 1 << 248;\n    uint256 internal constant _ROLE_249 = 1 << 249;\n    uint256 internal constant _ROLE_250 = 1 << 250;\n    uint256 internal constant _ROLE_251 = 1 << 251;\n    uint256 internal constant _ROLE_252 = 1 << 252;\n    uint256 internal constant _ROLE_253 = 1 << 253;\n    uint256 internal constant _ROLE_254 = 1 << 254;\n    uint256 internal constant _ROLE_255 = 1 << 255;\n}\n"
      },
      "solady/src/utils/LibString.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Library for converting numbers into strings and other string operations.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibString.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol)\nlibrary LibString {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                        CUSTOM ERRORS                       */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The `length` of the output is too small to contain all the hex digits.\n    error HexLengthInsufficient();\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                         CONSTANTS                          */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The constant returned when the `search` is not found in the string.\n    uint256 internal constant NOT_FOUND = type(uint256).max;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                     DECIMAL OPERATIONS                     */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns the base 10 decimal representation of `value`.\n    function toString(uint256 value) internal pure returns (string memory str) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // The maximum value of a uint256 contains 78 digits (1 byte per digit), but\n            // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned.\n            // We will need 1 word for the trailing zeros padding, 1 word for the length,\n            // and 3 words for a maximum of 78 digits.\n            str := add(mload(0x40), 0x80)\n            // Update the free memory pointer to allocate.\n            mstore(0x40, add(str, 0x20))\n            // Zeroize the slot after the string.\n            mstore(str, 0)\n\n            // Cache the end of the memory to calculate the length later.\n            let end := str\n\n            let w := not(0) // Tsk.\n            // We write the string from rightmost digit to leftmost digit.\n            // The following is essentially a do-while loop that also handles the zero case.\n            for { let temp := value } 1 {} {\n                str := add(str, w) // `sub(str, 1)`.\n                // Write the character to the pointer.\n                // The ASCII index of the '0' character is 48.\n                mstore8(str, add(48, mod(temp, 10)))\n                // Keep dividing `temp` until zero.\n                temp := div(temp, 10)\n                if iszero(temp) { break }\n            }\n\n            let length := sub(end, str)\n            // Move the pointer 32 bytes leftwards to make room for the length.\n            str := sub(str, 0x20)\n            // Store the length.\n            mstore(str, length)\n        }\n    }\n\n    /// @dev Returns the base 10 decimal representation of `value`.\n    function toString(int256 value) internal pure returns (string memory str) {\n        if (value >= 0) {\n            return toString(uint256(value));\n        }\n        unchecked {\n            str = toString(uint256(-value));\n        }\n        /// @solidity memory-safe-assembly\n        assembly {\n            // We still have some spare memory space on the left,\n            // as we have allocated 3 words (96 bytes) for up to 78 digits.\n            let length := mload(str) // Load the string length.\n            mstore(str, 0x2d) // Store the '-' character.\n            str := sub(str, 1) // Move back the string pointer by a byte.\n            mstore(str, add(length, 1)) // Update the string length.\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                   HEXADECIMAL OPERATIONS                   */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns the hexadecimal representation of `value`,\n    /// left-padded to an input length of `length` bytes.\n    /// The output is prefixed with \"0x\" encoded using 2 hexadecimal digits per byte,\n    /// giving a total length of `length * 2 + 2` bytes.\n    /// Reverts if `length` is too small for the output to contain all the digits.\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory str) {\n        str = toHexStringNoPrefix(value, length);\n        /// @solidity memory-safe-assembly\n        assembly {\n            let strLength := add(mload(str), 2) // Compute the length.\n            mstore(str, 0x3078) // Write the \"0x\" prefix.\n            str := sub(str, 2) // Move the pointer.\n            mstore(str, strLength) // Write the length.\n        }\n    }\n\n    /// @dev Returns the hexadecimal representation of `value`,\n    /// left-padded to an input length of `length` bytes.\n    /// The output is prefixed with \"0x\" encoded using 2 hexadecimal digits per byte,\n    /// giving a total length of `length * 2` bytes.\n    /// Reverts if `length` is too small for the output to contain all the digits.\n    function toHexStringNoPrefix(uint256 value, uint256 length)\n        internal\n        pure\n        returns (string memory str)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // We need 0x20 bytes for the trailing zeros padding, `length * 2` bytes\n            // for the digits, 0x02 bytes for the prefix, and 0x20 bytes for the length.\n            // We add 0x20 to the total and round down to a multiple of 0x20.\n            // (0x20 + 0x20 + 0x02 + 0x20) = 0x62.\n            str := add(mload(0x40), and(add(shl(1, length), 0x42), not(0x1f)))\n            // Allocate the memory.\n            mstore(0x40, add(str, 0x20))\n            // Zeroize the slot after the string.\n            mstore(str, 0)\n\n            // Cache the end to calculate the length later.\n            let end := str\n            // Store \"0123456789abcdef\" in scratch space.\n            mstore(0x0f, 0x30313233343536373839616263646566)\n\n            let start := sub(str, add(length, length))\n            let w := not(1) // Tsk.\n            let temp := value\n            // We write the string from rightmost digit to leftmost digit.\n            // The following is essentially a do-while loop that also handles the zero case.\n            for {} 1 {} {\n                str := add(str, w) // `sub(str, 2)`.\n                mstore8(add(str, 1), mload(and(temp, 15)))\n                mstore8(str, mload(and(shr(4, temp), 15)))\n                temp := shr(8, temp)\n                if iszero(xor(str, start)) { break }\n            }\n\n            if temp {\n                // Store the function selector of `HexLengthInsufficient()`.\n                mstore(0x00, 0x2194895a)\n                // Revert with (offset, size).\n                revert(0x1c, 0x04)\n            }\n\n            // Compute the string's length.\n            let strLength := sub(end, str)\n            // Move the pointer and write the length.\n            str := sub(str, 0x20)\n            mstore(str, strLength)\n        }\n    }\n\n    /// @dev Returns the hexadecimal representation of `value`.\n    /// The output is prefixed with \"0x\" and encoded using 2 hexadecimal digits per byte.\n    /// As address are 20 bytes long, the output will left-padded to have\n    /// a length of `20 * 2 + 2` bytes.\n    function toHexString(uint256 value) internal pure returns (string memory str) {\n        str = toHexStringNoPrefix(value);\n        /// @solidity memory-safe-assembly\n        assembly {\n            let strLength := add(mload(str), 2) // Compute the length.\n            mstore(str, 0x3078) // Write the \"0x\" prefix.\n            str := sub(str, 2) // Move the pointer.\n            mstore(str, strLength) // Write the length.\n        }\n    }\n\n    /// @dev Returns the hexadecimal representation of `value`.\n    /// The output is prefixed with \"0x\".\n    /// The output excludes leading \"0\" from the `toHexString` output.\n    /// `0x00: \"0x0\", 0x01: \"0x1\", 0x12: \"0x12\", 0x123: \"0x123\"`.\n    function toMinimalHexString(uint256 value) internal pure returns (string memory str) {\n        str = toHexStringNoPrefix(value);\n        /// @solidity memory-safe-assembly\n        assembly {\n            let o := eq(byte(0, mload(add(str, 0x20))), 0x30) // Whether leading zero is present.\n            let strLength := add(mload(str), 2) // Compute the length.\n            mstore(add(str, o), 0x3078) // Write the \"0x\" prefix, accounting for leading zero.\n            str := sub(add(str, o), 2) // Move the pointer, accounting for leading zero.\n            mstore(str, sub(strLength, o)) // Write the length, accounting for leading zero.\n        }\n    }\n\n    /// @dev Returns the hexadecimal representation of `value`.\n    /// The output excludes leading \"0\" from the `toHexStringNoPrefix` output.\n    /// `0x00: \"0\", 0x01: \"1\", 0x12: \"12\", 0x123: \"123\"`.\n    function toMinimalHexStringNoPrefix(uint256 value) internal pure returns (string memory str) {\n        str = toHexStringNoPrefix(value);\n        /// @solidity memory-safe-assembly\n        assembly {\n            let o := eq(byte(0, mload(add(str, 0x20))), 0x30) // Whether leading zero is present.\n            let strLength := mload(str) // Get the length.\n            str := add(str, o) // Move the pointer, accounting for leading zero.\n            mstore(str, sub(strLength, o)) // Write the length, accounting for leading zero.\n        }\n    }\n\n    /// @dev Returns the hexadecimal representation of `value`.\n    /// The output is encoded using 2 hexadecimal digits per byte.\n    /// As address are 20 bytes long, the output will left-padded to have\n    /// a length of `20 * 2` bytes.\n    function toHexStringNoPrefix(uint256 value) internal pure returns (string memory str) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,\n            // 0x02 bytes for the prefix, and 0x40 bytes for the digits.\n            // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x40) is 0xa0.\n            str := add(mload(0x40), 0x80)\n            // Allocate the memory.\n            mstore(0x40, add(str, 0x20))\n            // Zeroize the slot after the string.\n            mstore(str, 0)\n\n            // Cache the end to calculate the length later.\n            let end := str\n            // Store \"0123456789abcdef\" in scratch space.\n            mstore(0x0f, 0x30313233343536373839616263646566)\n\n            let w := not(1) // Tsk.\n            // We write the string from rightmost digit to leftmost digit.\n            // The following is essentially a do-while loop that also handles the zero case.\n            for { let temp := value } 1 {} {\n                str := add(str, w) // `sub(str, 2)`.\n                mstore8(add(str, 1), mload(and(temp, 15)))\n                mstore8(str, mload(and(shr(4, temp), 15)))\n                temp := shr(8, temp)\n                if iszero(temp) { break }\n            }\n\n            // Compute the string's length.\n            let strLength := sub(end, str)\n            // Move the pointer and write the length.\n            str := sub(str, 0x20)\n            mstore(str, strLength)\n        }\n    }\n\n    /// @dev Returns the hexadecimal representation of `value`.\n    /// The output is prefixed with \"0x\", encoded using 2 hexadecimal digits per byte,\n    /// and the alphabets are capitalized conditionally according to\n    /// https://eips.ethereum.org/EIPS/eip-55\n    function toHexStringChecksummed(address value) internal pure returns (string memory str) {\n        str = toHexString(value);\n        /// @solidity memory-safe-assembly\n        assembly {\n            let mask := shl(6, div(not(0), 255)) // `0b010000000100000000 ...`\n            let o := add(str, 0x22)\n            let hashed := and(keccak256(o, 40), mul(34, mask)) // `0b10001000 ... `\n            let t := shl(240, 136) // `0b10001000 << 240`\n            for { let i := 0 } 1 {} {\n                mstore(add(i, i), mul(t, byte(i, hashed)))\n                i := add(i, 1)\n                if eq(i, 20) { break }\n            }\n            mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask)))))\n            o := add(o, 0x20)\n            mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask)))))\n        }\n    }\n\n    /// @dev Returns the hexadecimal representation of `value`.\n    /// The output is prefixed with \"0x\" and encoded using 2 hexadecimal digits per byte.\n    function toHexString(address value) internal pure returns (string memory str) {\n        str = toHexStringNoPrefix(value);\n        /// @solidity memory-safe-assembly\n        assembly {\n            let strLength := add(mload(str), 2) // Compute the length.\n            mstore(str, 0x3078) // Write the \"0x\" prefix.\n            str := sub(str, 2) // Move the pointer.\n            mstore(str, strLength) // Write the length.\n        }\n    }\n\n    /// @dev Returns the hexadecimal representation of `value`.\n    /// The output is encoded using 2 hexadecimal digits per byte.\n    function toHexStringNoPrefix(address value) internal pure returns (string memory str) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            str := mload(0x40)\n\n            // Allocate the memory.\n            // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,\n            // 0x02 bytes for the prefix, and 0x28 bytes for the digits.\n            // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x28) is 0x80.\n            mstore(0x40, add(str, 0x80))\n\n            // Store \"0123456789abcdef\" in scratch space.\n            mstore(0x0f, 0x30313233343536373839616263646566)\n\n            str := add(str, 2)\n            mstore(str, 40)\n\n            let o := add(str, 0x20)\n            mstore(add(o, 40), 0)\n\n            value := shl(96, value)\n\n            // We write the string from rightmost digit to leftmost digit.\n            // The following is essentially a do-while loop that also handles the zero case.\n            for { let i := 0 } 1 {} {\n                let p := add(o, add(i, i))\n                let temp := byte(i, value)\n                mstore8(add(p, 1), mload(and(temp, 15)))\n                mstore8(p, mload(shr(4, temp)))\n                i := add(i, 1)\n                if eq(i, 20) { break }\n            }\n        }\n    }\n\n    /// @dev Returns the hex encoded string from the raw bytes.\n    /// The output is encoded using 2 hexadecimal digits per byte.\n    function toHexString(bytes memory raw) internal pure returns (string memory str) {\n        str = toHexStringNoPrefix(raw);\n        /// @solidity memory-safe-assembly\n        assembly {\n            let strLength := add(mload(str), 2) // Compute the length.\n            mstore(str, 0x3078) // Write the \"0x\" prefix.\n            str := sub(str, 2) // Move the pointer.\n            mstore(str, strLength) // Write the length.\n        }\n    }\n\n    /// @dev Returns the hex encoded string from the raw bytes.\n    /// The output is encoded using 2 hexadecimal digits per byte.\n    function toHexStringNoPrefix(bytes memory raw) internal pure returns (string memory str) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let length := mload(raw)\n            str := add(mload(0x40), 2) // Skip 2 bytes for the optional prefix.\n            mstore(str, add(length, length)) // Store the length of the output.\n\n            // Store \"0123456789abcdef\" in scratch space.\n            mstore(0x0f, 0x30313233343536373839616263646566)\n\n            let o := add(str, 0x20)\n            let end := add(raw, length)\n\n            for {} iszero(eq(raw, end)) {} {\n                raw := add(raw, 1)\n                mstore8(add(o, 1), mload(and(mload(raw), 15)))\n                mstore8(o, mload(and(shr(4, mload(raw)), 15)))\n                o := add(o, 2)\n            }\n            mstore(o, 0) // Zeroize the slot after the string.\n            mstore(0x40, add(o, 0x20)) // Allocate the memory.\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                   RUNE STRING OPERATIONS                   */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns the number of UTF characters in the string.\n    function runeCount(string memory s) internal pure returns (uint256 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if mload(s) {\n                mstore(0x00, div(not(0), 255))\n                mstore(0x20, 0x0202020202020202020202020202020202020202020202020303030304040506)\n                let o := add(s, 0x20)\n                let end := add(o, mload(s))\n                for { result := 1 } 1 { result := add(result, 1) } {\n                    o := add(o, byte(0, mload(shr(250, mload(o)))))\n                    if iszero(lt(o, end)) { break }\n                }\n            }\n        }\n    }\n\n    /// @dev Returns if this string is a 7-bit ASCII string.\n    /// (i.e. all characters codes are in [0..127])\n    function is7BitASCII(string memory s) internal pure returns (bool result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let mask := shl(7, div(not(0), 255))\n            result := 1\n            let n := mload(s)\n            if n {\n                let o := add(s, 0x20)\n                let end := add(o, n)\n                let last := mload(end)\n                mstore(end, 0)\n                for {} 1 {} {\n                    if and(mask, mload(o)) {\n                        result := 0\n                        break\n                    }\n                    o := add(o, 0x20)\n                    if iszero(lt(o, end)) { break }\n                }\n                mstore(end, last)\n            }\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                   BYTE STRING OPERATIONS                   */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    // For performance and bytecode compactness, all indices of the following operations\n    // are byte (ASCII) offsets, not UTF character offsets.\n\n    /// @dev Returns `subject` all occurrences of `search` replaced with `replacement`.\n    function replace(string memory subject, string memory search, string memory replacement)\n        internal\n        pure\n        returns (string memory result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let subjectLength := mload(subject)\n            let searchLength := mload(search)\n            let replacementLength := mload(replacement)\n\n            subject := add(subject, 0x20)\n            search := add(search, 0x20)\n            replacement := add(replacement, 0x20)\n            result := add(mload(0x40), 0x20)\n\n            let subjectEnd := add(subject, subjectLength)\n            if iszero(gt(searchLength, subjectLength)) {\n                let subjectSearchEnd := add(sub(subjectEnd, searchLength), 1)\n                let h := 0\n                if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) }\n                let m := shl(3, sub(0x20, and(searchLength, 0x1f)))\n                let s := mload(search)\n                for {} 1 {} {\n                    let t := mload(subject)\n                    // Whether the first `searchLength % 32` bytes of\n                    // `subject` and `search` matches.\n                    if iszero(shr(m, xor(t, s))) {\n                        if h {\n                            if iszero(eq(keccak256(subject, searchLength), h)) {\n                                mstore(result, t)\n                                result := add(result, 1)\n                                subject := add(subject, 1)\n                                if iszero(lt(subject, subjectSearchEnd)) { break }\n                                continue\n                            }\n                        }\n                        // Copy the `replacement` one word at a time.\n                        for { let o := 0 } 1 {} {\n                            mstore(add(result, o), mload(add(replacement, o)))\n                            o := add(o, 0x20)\n                            if iszero(lt(o, replacementLength)) { break }\n                        }\n                        result := add(result, replacementLength)\n                        subject := add(subject, searchLength)\n                        if searchLength {\n                            if iszero(lt(subject, subjectSearchEnd)) { break }\n                            continue\n                        }\n                    }\n                    mstore(result, t)\n                    result := add(result, 1)\n                    subject := add(subject, 1)\n                    if iszero(lt(subject, subjectSearchEnd)) { break }\n                }\n            }\n\n            let resultRemainder := result\n            result := add(mload(0x40), 0x20)\n            let k := add(sub(resultRemainder, result), sub(subjectEnd, subject))\n            // Copy the rest of the string one word at a time.\n            for {} lt(subject, subjectEnd) {} {\n                mstore(resultRemainder, mload(subject))\n                resultRemainder := add(resultRemainder, 0x20)\n                subject := add(subject, 0x20)\n            }\n            result := sub(result, 0x20)\n            let last := add(add(result, 0x20), k) // Zeroize the slot after the string.\n            mstore(last, 0)\n            mstore(0x40, add(last, 0x20)) // Allocate the memory.\n            mstore(result, k) // Store the length.\n        }\n    }\n\n    /// @dev Returns the byte index of the first location of `search` in `subject`,\n    /// searching from left to right, starting from `from`.\n    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.\n    function indexOf(string memory subject, string memory search, uint256 from)\n        internal\n        pure\n        returns (uint256 result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            for { let subjectLength := mload(subject) } 1 {} {\n                if iszero(mload(search)) {\n                    if iszero(gt(from, subjectLength)) {\n                        result := from\n                        break\n                    }\n                    result := subjectLength\n                    break\n                }\n                let searchLength := mload(search)\n                let subjectStart := add(subject, 0x20)\n\n                result := not(0) // Initialize to `NOT_FOUND`.\n\n                subject := add(subjectStart, from)\n                let end := add(sub(add(subjectStart, subjectLength), searchLength), 1)\n\n                let m := shl(3, sub(0x20, and(searchLength, 0x1f)))\n                let s := mload(add(search, 0x20))\n\n                if iszero(and(lt(subject, end), lt(from, subjectLength))) { break }\n\n                if iszero(lt(searchLength, 0x20)) {\n                    for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} {\n                        if iszero(shr(m, xor(mload(subject), s))) {\n                            if eq(keccak256(subject, searchLength), h) {\n                                result := sub(subject, subjectStart)\n                                break\n                            }\n                        }\n                        subject := add(subject, 1)\n                        if iszero(lt(subject, end)) { break }\n                    }\n                    break\n                }\n                for {} 1 {} {\n                    if iszero(shr(m, xor(mload(subject), s))) {\n                        result := sub(subject, subjectStart)\n                        break\n                    }\n                    subject := add(subject, 1)\n                    if iszero(lt(subject, end)) { break }\n                }\n                break\n            }\n        }\n    }\n\n    /// @dev Returns the byte index of the first location of `search` in `subject`,\n    /// searching from left to right.\n    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.\n    function indexOf(string memory subject, string memory search)\n        internal\n        pure\n        returns (uint256 result)\n    {\n        result = indexOf(subject, search, 0);\n    }\n\n    /// @dev Returns the byte index of the first location of `search` in `subject`,\n    /// searching from right to left, starting from `from`.\n    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.\n    function lastIndexOf(string memory subject, string memory search, uint256 from)\n        internal\n        pure\n        returns (uint256 result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            for {} 1 {} {\n                result := not(0) // Initialize to `NOT_FOUND`.\n                let searchLength := mload(search)\n                if gt(searchLength, mload(subject)) { break }\n                let w := result\n\n                let fromMax := sub(mload(subject), searchLength)\n                if iszero(gt(fromMax, from)) { from := fromMax }\n\n                let end := add(add(subject, 0x20), w)\n                subject := add(add(subject, 0x20), from)\n                if iszero(gt(subject, end)) { break }\n                // As this function is not too often used,\n                // we shall simply use keccak256 for smaller bytecode size.\n                for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} {\n                    if eq(keccak256(subject, searchLength), h) {\n                        result := sub(subject, add(end, 1))\n                        break\n                    }\n                    subject := add(subject, w) // `sub(subject, 1)`.\n                    if iszero(gt(subject, end)) { break }\n                }\n                break\n            }\n        }\n    }\n\n    /// @dev Returns the byte index of the first location of `search` in `subject`,\n    /// searching from right to left.\n    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.\n    function lastIndexOf(string memory subject, string memory search)\n        internal\n        pure\n        returns (uint256 result)\n    {\n        result = lastIndexOf(subject, search, uint256(int256(-1)));\n    }\n\n    /// @dev Returns whether `subject` starts with `search`.\n    function startsWith(string memory subject, string memory search)\n        internal\n        pure\n        returns (bool result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let searchLength := mload(search)\n            // Just using keccak256 directly is actually cheaper.\n            // forgefmt: disable-next-item\n            result := and(\n                iszero(gt(searchLength, mload(subject))),\n                eq(\n                    keccak256(add(subject, 0x20), searchLength),\n                    keccak256(add(search, 0x20), searchLength)\n                )\n            )\n        }\n    }\n\n    /// @dev Returns whether `subject` ends with `search`.\n    function endsWith(string memory subject, string memory search)\n        internal\n        pure\n        returns (bool result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let searchLength := mload(search)\n            let subjectLength := mload(subject)\n            // Whether `search` is not longer than `subject`.\n            let withinRange := iszero(gt(searchLength, subjectLength))\n            // Just using keccak256 directly is actually cheaper.\n            // forgefmt: disable-next-item\n            result := and(\n                withinRange,\n                eq(\n                    keccak256(\n                        // `subject + 0x20 + max(subjectLength - searchLength, 0)`.\n                        add(add(subject, 0x20), mul(withinRange, sub(subjectLength, searchLength))),\n                        searchLength\n                    ),\n                    keccak256(add(search, 0x20), searchLength)\n                )\n            )\n        }\n    }\n\n    /// @dev Returns `subject` repeated `times`.\n    function repeat(string memory subject, uint256 times)\n        internal\n        pure\n        returns (string memory result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let subjectLength := mload(subject)\n            if iszero(or(iszero(times), iszero(subjectLength))) {\n                subject := add(subject, 0x20)\n                result := mload(0x40)\n                let output := add(result, 0x20)\n                for {} 1 {} {\n                    // Copy the `subject` one word at a time.\n                    for { let o := 0 } 1 {} {\n                        mstore(add(output, o), mload(add(subject, o)))\n                        o := add(o, 0x20)\n                        if iszero(lt(o, subjectLength)) { break }\n                    }\n                    output := add(output, subjectLength)\n                    times := sub(times, 1)\n                    if iszero(times) { break }\n                }\n                mstore(output, 0) // Zeroize the slot after the string.\n                let resultLength := sub(output, add(result, 0x20))\n                mstore(result, resultLength) // Store the length.\n                // Allocate the memory.\n                mstore(0x40, add(result, add(resultLength, 0x20)))\n            }\n        }\n    }\n\n    /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive).\n    /// `start` and `end` are byte offsets.\n    function slice(string memory subject, uint256 start, uint256 end)\n        internal\n        pure\n        returns (string memory result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let subjectLength := mload(subject)\n            if iszero(gt(subjectLength, end)) { end := subjectLength }\n            if iszero(gt(subjectLength, start)) { start := subjectLength }\n            if lt(start, end) {\n                result := mload(0x40)\n                let resultLength := sub(end, start)\n                mstore(result, resultLength)\n                subject := add(subject, start)\n                let w := not(0x1f)\n                // Copy the `subject` one word at a time, backwards.\n                for { let o := and(add(resultLength, 0x1f), w) } 1 {} {\n                    mstore(add(result, o), mload(add(subject, o)))\n                    o := add(o, w) // `sub(o, 0x20)`.\n                    if iszero(o) { break }\n                }\n                // Zeroize the slot after the string.\n                mstore(add(add(result, 0x20), resultLength), 0)\n                // Allocate memory for the length and the bytes,\n                // rounded up to a multiple of 32.\n                mstore(0x40, add(result, and(add(resultLength, 0x3f), w)))\n            }\n        }\n    }\n\n    /// @dev Returns a copy of `subject` sliced from `start` to the end of the string.\n    /// `start` is a byte offset.\n    function slice(string memory subject, uint256 start)\n        internal\n        pure\n        returns (string memory result)\n    {\n        result = slice(subject, start, uint256(int256(-1)));\n    }\n\n    /// @dev Returns all the indices of `search` in `subject`.\n    /// The indices are byte offsets.\n    function indicesOf(string memory subject, string memory search)\n        internal\n        pure\n        returns (uint256[] memory result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let subjectLength := mload(subject)\n            let searchLength := mload(search)\n\n            if iszero(gt(searchLength, subjectLength)) {\n                subject := add(subject, 0x20)\n                search := add(search, 0x20)\n                result := add(mload(0x40), 0x20)\n\n                let subjectStart := subject\n                let subjectSearchEnd := add(sub(add(subject, subjectLength), searchLength), 1)\n                let h := 0\n                if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) }\n                let m := shl(3, sub(0x20, and(searchLength, 0x1f)))\n                let s := mload(search)\n                for {} 1 {} {\n                    let t := mload(subject)\n                    // Whether the first `searchLength % 32` bytes of\n                    // `subject` and `search` matches.\n                    if iszero(shr(m, xor(t, s))) {\n                        if h {\n                            if iszero(eq(keccak256(subject, searchLength), h)) {\n                                subject := add(subject, 1)\n                                if iszero(lt(subject, subjectSearchEnd)) { break }\n                                continue\n                            }\n                        }\n                        // Append to `result`.\n                        mstore(result, sub(subject, subjectStart))\n                        result := add(result, 0x20)\n                        // Advance `subject` by `searchLength`.\n                        subject := add(subject, searchLength)\n                        if searchLength {\n                            if iszero(lt(subject, subjectSearchEnd)) { break }\n                            continue\n                        }\n                    }\n                    subject := add(subject, 1)\n                    if iszero(lt(subject, subjectSearchEnd)) { break }\n                }\n                let resultEnd := result\n                // Assign `result` to the free memory pointer.\n                result := mload(0x40)\n                // Store the length of `result`.\n                mstore(result, shr(5, sub(resultEnd, add(result, 0x20))))\n                // Allocate memory for result.\n                // We allocate one more word, so this array can be recycled for {split}.\n                mstore(0x40, add(resultEnd, 0x20))\n            }\n        }\n    }\n\n    /// @dev Returns a arrays of strings based on the `delimiter` inside of the `subject` string.\n    function split(string memory subject, string memory delimiter)\n        internal\n        pure\n        returns (string[] memory result)\n    {\n        uint256[] memory indices = indicesOf(subject, delimiter);\n        /// @solidity memory-safe-assembly\n        assembly {\n            let w := not(0x1f)\n            let indexPtr := add(indices, 0x20)\n            let indicesEnd := add(indexPtr, shl(5, add(mload(indices), 1)))\n            mstore(add(indicesEnd, w), mload(subject))\n            mstore(indices, add(mload(indices), 1))\n            let prevIndex := 0\n            for {} 1 {} {\n                let index := mload(indexPtr)\n                mstore(indexPtr, 0x60)\n                if iszero(eq(index, prevIndex)) {\n                    let element := mload(0x40)\n                    let elementLength := sub(index, prevIndex)\n                    mstore(element, elementLength)\n                    // Copy the `subject` one word at a time, backwards.\n                    for { let o := and(add(elementLength, 0x1f), w) } 1 {} {\n                        mstore(add(element, o), mload(add(add(subject, prevIndex), o)))\n                        o := add(o, w) // `sub(o, 0x20)`.\n                        if iszero(o) { break }\n                    }\n                    // Zeroize the slot after the string.\n                    mstore(add(add(element, 0x20), elementLength), 0)\n                    // Allocate memory for the length and the bytes,\n                    // rounded up to a multiple of 32.\n                    mstore(0x40, add(element, and(add(elementLength, 0x3f), w)))\n                    // Store the `element` into the array.\n                    mstore(indexPtr, element)\n                }\n                prevIndex := add(index, mload(delimiter))\n                indexPtr := add(indexPtr, 0x20)\n                if iszero(lt(indexPtr, indicesEnd)) { break }\n            }\n            result := indices\n            if iszero(mload(delimiter)) {\n                result := add(indices, 0x20)\n                mstore(result, sub(mload(indices), 2))\n            }\n        }\n    }\n\n    /// @dev Returns a concatenated string of `a` and `b`.\n    /// Cheaper than `string.concat()` and does not de-align the free memory pointer.\n    function concat(string memory a, string memory b)\n        internal\n        pure\n        returns (string memory result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let w := not(0x1f)\n            result := mload(0x40)\n            let aLength := mload(a)\n            // Copy `a` one word at a time, backwards.\n            for { let o := and(add(aLength, 0x20), w) } 1 {} {\n                mstore(add(result, o), mload(add(a, o)))\n                o := add(o, w) // `sub(o, 0x20)`.\n                if iszero(o) { break }\n            }\n            let bLength := mload(b)\n            let output := add(result, aLength)\n            // Copy `b` one word at a time, backwards.\n            for { let o := and(add(bLength, 0x20), w) } 1 {} {\n                mstore(add(output, o), mload(add(b, o)))\n                o := add(o, w) // `sub(o, 0x20)`.\n                if iszero(o) { break }\n            }\n            let totalLength := add(aLength, bLength)\n            let last := add(add(result, 0x20), totalLength)\n            // Zeroize the slot after the string.\n            mstore(last, 0)\n            // Stores the length.\n            mstore(result, totalLength)\n            // Allocate memory for the length and the bytes,\n            // rounded up to a multiple of 32.\n            mstore(0x40, and(add(last, 0x1f), w))\n        }\n    }\n\n    /// @dev Returns a copy of the string in either lowercase or UPPERCASE.\n    /// WARNING! This function is only compatible with 7-bit ASCII strings.\n    function toCase(string memory subject, bool toUpper)\n        internal\n        pure\n        returns (string memory result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let length := mload(subject)\n            if length {\n                result := add(mload(0x40), 0x20)\n                subject := add(subject, 1)\n                let flags := shl(add(70, shl(5, toUpper)), 0x3ffffff)\n                let w := not(0)\n                for { let o := length } 1 {} {\n                    o := add(o, w)\n                    let b := and(0xff, mload(add(subject, o)))\n                    mstore8(add(result, o), xor(b, and(shr(b, flags), 0x20)))\n                    if iszero(o) { break }\n                }\n                result := mload(0x40)\n                mstore(result, length) // Store the length.\n                let last := add(add(result, 0x20), length)\n                mstore(last, 0) // Zeroize the slot after the string.\n                mstore(0x40, add(last, 0x20)) // Allocate the memory.\n            }\n        }\n    }\n\n    /// @dev Returns a string from a small bytes32 string.\n    /// `smallString` must be null terminated, or behavior will be undefined.\n    function fromSmallString(bytes32 smallString) internal pure returns (string memory result) {\n        if (smallString == bytes32(0)) return result;\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := mload(0x40)\n            let n := 0\n            for {} 1 {} {\n                n := add(n, 1)\n                if iszero(byte(n, smallString)) { break } // Scan for '\\0'.\n            }\n            mstore(result, n)\n            let o := add(result, 0x20)\n            mstore(o, smallString)\n            mstore(add(o, n), 0)\n            mstore(0x40, add(result, 0x40))\n        }\n    }\n\n    /// @dev Returns a lowercased copy of the string.\n    /// WARNING! This function is only compatible with 7-bit ASCII strings.\n    function lower(string memory subject) internal pure returns (string memory result) {\n        result = toCase(subject, false);\n    }\n\n    /// @dev Returns an UPPERCASED copy of the string.\n    /// WARNING! This function is only compatible with 7-bit ASCII strings.\n    function upper(string memory subject) internal pure returns (string memory result) {\n        result = toCase(subject, true);\n    }\n\n    /// @dev Escapes the string to be used within HTML tags.\n    function escapeHTML(string memory s) internal pure returns (string memory result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let end := add(s, mload(s))\n            result := add(mload(0x40), 0x20)\n            // Store the bytes of the packed offsets and strides into the scratch space.\n            // `packed = (stride << 5) | offset`. Max offset is 20. Max stride is 6.\n            mstore(0x1f, 0x900094)\n            mstore(0x08, 0xc0000000a6ab)\n            // Store \"&quot;&amp;&#39;&lt;&gt;\" into the scratch space.\n            mstore(0x00, shl(64, 0x2671756f743b26616d703b262333393b266c743b2667743b))\n            for {} iszero(eq(s, end)) {} {\n                s := add(s, 1)\n                let c := and(mload(s), 0xff)\n                // Not in `[\"\\\"\",\"'\",\"&\",\"<\",\">\"]`.\n                if iszero(and(shl(c, 1), 0x500000c400000000)) {\n                    mstore8(result, c)\n                    result := add(result, 1)\n                    continue\n                }\n                let t := shr(248, mload(c))\n                mstore(result, mload(and(t, 0x1f)))\n                result := add(result, shr(5, t))\n            }\n            let last := result\n            mstore(last, 0) // Zeroize the slot after the string.\n            result := mload(0x40)\n            mstore(result, sub(last, add(result, 0x20))) // Store the length.\n            mstore(0x40, add(last, 0x20)) // Allocate the memory.\n        }\n    }\n\n    /// @dev Escapes the string to be used within double-quotes in a JSON.\n    /// If `addDoubleQuotes` is true, the result will be enclosed in double-quotes.\n    function escapeJSON(string memory s, bool addDoubleQuotes)\n        internal\n        pure\n        returns (string memory result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let end := add(s, mload(s))\n            result := add(mload(0x40), 0x20)\n            if addDoubleQuotes {\n                mstore8(result, 34)\n                result := add(1, result)\n            }\n            // Store \"\\\\u0000\" in scratch space.\n            // Store \"0123456789abcdef\" in scratch space.\n            // Also, store `{0x08:\"b\", 0x09:\"t\", 0x0a:\"n\", 0x0c:\"f\", 0x0d:\"r\"}`.\n            // into the scratch space.\n            mstore(0x15, 0x5c75303030303031323334353637383961626364656662746e006672)\n            // Bitmask for detecting `[\"\\\"\",\"\\\\\"]`.\n            let e := or(shl(0x22, 1), shl(0x5c, 1))\n            for {} iszero(eq(s, end)) {} {\n                s := add(s, 1)\n                let c := and(mload(s), 0xff)\n                if iszero(lt(c, 0x20)) {\n                    if iszero(and(shl(c, 1), e)) {\n                        // Not in `[\"\\\"\",\"\\\\\"]`.\n                        mstore8(result, c)\n                        result := add(result, 1)\n                        continue\n                    }\n                    mstore8(result, 0x5c) // \"\\\\\".\n                    mstore8(add(result, 1), c)\n                    result := add(result, 2)\n                    continue\n                }\n                if iszero(and(shl(c, 1), 0x3700)) {\n                    // Not in `[\"\\b\",\"\\t\",\"\\n\",\"\\f\",\"\\d\"]`.\n                    mstore8(0x1d, mload(shr(4, c))) // Hex value.\n                    mstore8(0x1e, mload(and(c, 15))) // Hex value.\n                    mstore(result, mload(0x19)) // \"\\\\u00XX\".\n                    result := add(result, 6)\n                    continue\n                }\n                mstore8(result, 0x5c) // \"\\\\\".\n                mstore8(add(result, 1), mload(add(c, 8)))\n                result := add(result, 2)\n            }\n            if addDoubleQuotes {\n                mstore8(result, 34)\n                result := add(1, result)\n            }\n            let last := result\n            mstore(last, 0) // Zeroize the slot after the string.\n            result := mload(0x40)\n            mstore(result, sub(last, add(result, 0x20))) // Store the length.\n            mstore(0x40, add(last, 0x20)) // Allocate the memory.\n        }\n    }\n\n    /// @dev Escapes the string to be used within double-quotes in a JSON.\n    function escapeJSON(string memory s) internal pure returns (string memory result) {\n        result = escapeJSON(s, false);\n    }\n\n    /// @dev Returns whether `a` equals `b`.\n    function eq(string memory a, string memory b) internal pure returns (bool result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b)))\n        }\n    }\n\n    /// @dev Returns whether `a` equals `b`. For small strings up to 32 bytes.\n    /// `b` must be null terminated, or behavior will be undefined.\n    function eqs(string memory a, bytes32 b) internal pure returns (bool result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // These should be evaluated on compile time, as far as possible.\n            let x := and(b, add(not(b), 1))\n            let r := or(shl(8, iszero(b)), shl(7, iszero(iszero(shr(128, x)))))\n            r := or(r, shl(6, iszero(iszero(shr(64, shr(r, x))))))\n            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n            r := or(r, shl(4, lt(0xffff, shr(r, x))))\n            r := or(r, shl(3, lt(0xff, shr(r, x))))\n            result := gt(eq(mload(a), sub(32, shr(3, r))), shr(r, xor(b, mload(add(a, 0x20)))))\n        }\n    }\n\n    /// @dev Packs a single string with its length into a single word.\n    /// Returns `bytes32(0)` if the length is zero or greater than 31.\n    function packOne(string memory a) internal pure returns (bytes32 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // We don't need to zero right pad the string,\n            // since this is our own custom non-standard packing scheme.\n            result :=\n                mul(\n                    // Load the length and the bytes.\n                    mload(add(a, 0x1f)),\n                    // `length != 0 && length < 32`. Abuses underflow.\n                    // Assumes that the length is valid and within the block gas limit.\n                    lt(sub(mload(a), 1), 0x1f)\n                )\n        }\n    }\n\n    /// @dev Unpacks a string packed using {packOne}.\n    /// Returns the empty string if `packed` is `bytes32(0)`.\n    /// If `packed` is not an output of {packOne}, the output behavior is undefined.\n    function unpackOne(bytes32 packed) internal pure returns (string memory result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Grab the free memory pointer.\n            result := mload(0x40)\n            // Allocate 2 words (1 for the length, 1 for the bytes).\n            mstore(0x40, add(result, 0x40))\n            // Zeroize the length slot.\n            mstore(result, 0)\n            // Store the length and bytes.\n            mstore(add(result, 0x1f), packed)\n            // Right pad with zeroes.\n            mstore(add(add(result, 0x20), mload(result)), 0)\n        }\n    }\n\n    /// @dev Packs two strings with their lengths into a single word.\n    /// Returns `bytes32(0)` if combined length is zero or greater than 30.\n    function packTwo(string memory a, string memory b) internal pure returns (bytes32 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let aLength := mload(a)\n            // We don't need to zero right pad the strings,\n            // since this is our own custom non-standard packing scheme.\n            result :=\n                mul(\n                    // Load the length and the bytes of `a` and `b`.\n                    or(\n                        shl(shl(3, sub(0x1f, aLength)), mload(add(a, aLength))),\n                        mload(sub(add(b, 0x1e), aLength))\n                    ),\n                    // `totalLength != 0 && totalLength < 31`. Abuses underflow.\n                    // Assumes that the lengths are valid and within the block gas limit.\n                    lt(sub(add(aLength, mload(b)), 1), 0x1e)\n                )\n        }\n    }\n\n    /// @dev Unpacks strings packed using {packTwo}.\n    /// Returns the empty strings if `packed` is `bytes32(0)`.\n    /// If `packed` is not an output of {packTwo}, the output behavior is undefined.\n    function unpackTwo(bytes32 packed)\n        internal\n        pure\n        returns (string memory resultA, string memory resultB)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Grab the free memory pointer.\n            resultA := mload(0x40)\n            resultB := add(resultA, 0x40)\n            // Allocate 2 words for each string (1 for the length, 1 for the byte). Total 4 words.\n            mstore(0x40, add(resultB, 0x40))\n            // Zeroize the length slots.\n            mstore(resultA, 0)\n            mstore(resultB, 0)\n            // Store the lengths and bytes.\n            mstore(add(resultA, 0x1f), packed)\n            mstore(add(resultB, 0x1f), mload(add(add(resultA, 0x20), mload(resultA))))\n            // Right pad with zeroes.\n            mstore(add(add(resultA, 0x20), mload(resultA)), 0)\n            mstore(add(add(resultB, 0x20), mload(resultB)), 0)\n        }\n    }\n\n    /// @dev Directly returns `a` without copying.\n    function directReturn(string memory a) internal pure {\n        assembly {\n            // Assumes that the string does not start from the scratch space.\n            let retStart := sub(a, 0x20)\n            let retSize := add(mload(a), 0x40)\n            // Right pad with zeroes. Just in case the string is produced\n            // by a method that doesn't zero right pad.\n            mstore(add(retStart, retSize), 0)\n            // Store the return offset.\n            mstore(retStart, 0x20)\n            // End the transaction, returning the string.\n            return(retStart, retSize)\n        }\n    }\n}\n"
      },
      "solady/src/utils/SignatureCheckerLib.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Signature verification helper that supports both ECDSA signatures from EOAs\n/// and ERC1271 signatures from smart contract wallets like Argent and Gnosis safe.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SignatureCheckerLib.sol)\n/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/SignatureChecker.sol)\n///\n/// @dev Note:\n/// - The signature checking functions use the ecrecover precompile (0x1).\n/// - The `bytes memory signature` variants use the identity precompile (0x4)\n///   to copy memory internally.\n/// - Unlike ECDSA signatures, contract signatures are revocable.\n/// - As of Solady version 0.0.134, all `bytes signature` variants accept both\n///   regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures.\n///   See: https://eips.ethereum.org/EIPS/eip-2098\n///   This is for calldata efficiency on smart accounts prevalent on L2s.\n///\n/// WARNING! Do NOT use signatures as unique identifiers:\n/// - Use a nonce in the digest to prevent replay attacks on the same contract.\n/// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts.\n///   EIP-712 also enables readable signing of typed data for better user safety.\n/// This implementation does NOT check if a signature is non-malleable.\nlibrary SignatureCheckerLib {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*               SIGNATURE CHECKING OPERATIONS                */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns whether `signature` is valid for `signer` and `hash`.\n    /// If `signer` is a smart contract, the signature is validated with ERC1271.\n    /// Otherwise, the signature is validated with `ECDSA.recover`.\n    function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature)\n        internal\n        view\n        returns (bool isValid)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Clean the upper 96 bits of `signer` in case they are dirty.\n            for { signer := shr(96, shl(96, signer)) } signer {} {\n                let m := mload(0x40)\n                mstore(0x00, hash)\n                mstore(0x40, mload(add(signature, 0x20))) // `r`.\n                if eq(mload(signature), 64) {\n                    let vs := mload(add(signature, 0x40))\n                    mstore(0x20, add(shr(255, vs), 27)) // `v`.\n                    mstore(0x60, shr(1, shl(1, vs))) // `s`.\n                    let t :=\n                        staticcall(\n                            gas(), // Amount of gas left for the transaction.\n                            1, // Address of `ecrecover`.\n                            0x00, // Start of input.\n                            0x80, // Size of input.\n                            0x01, // Start of output.\n                            0x20 // Size of output.\n                        )\n                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n                    if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {\n                        isValid := 1\n                        mstore(0x60, 0) // Restore the zero slot.\n                        mstore(0x40, m) // Restore the free memory pointer.\n                        break\n                    }\n                }\n                if eq(mload(signature), 65) {\n                    mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.\n                    mstore(0x60, mload(add(signature, 0x40))) // `s`.\n                    let t :=\n                        staticcall(\n                            gas(), // Amount of gas left for the transaction.\n                            1, // Address of `ecrecover`.\n                            0x00, // Start of input.\n                            0x80, // Size of input.\n                            0x01, // Start of output.\n                            0x20 // Size of output.\n                        )\n                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n                    if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {\n                        isValid := 1\n                        mstore(0x60, 0) // Restore the zero slot.\n                        mstore(0x40, m) // Restore the free memory pointer.\n                        break\n                    }\n                }\n                mstore(0x60, 0) // Restore the zero slot.\n                mstore(0x40, m) // Restore the free memory pointer.\n\n                let f := shl(224, 0x1626ba7e)\n                mstore(m, f) // `bytes4(keccak256(\"isValidSignature(bytes32,bytes)\"))`.\n                mstore(add(m, 0x04), hash)\n                let d := add(m, 0x24)\n                mstore(d, 0x40) // The offset of the `signature` in the calldata.\n                // Copy the `signature` over.\n                let n := add(0x20, mload(signature))\n                pop(staticcall(gas(), 4, signature, n, add(m, 0x44), n))\n                // forgefmt: disable-next-item\n                isValid := and(\n                    // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).\n                    eq(mload(d), f),\n                    // Whether the staticcall does not revert.\n                    // This must be placed at the end of the `and` clause,\n                    // as the arguments are evaluated from right to left.\n                    staticcall(\n                        gas(), // Remaining gas.\n                        signer, // The `signer` address.\n                        m, // Offset of calldata in memory.\n                        add(returndatasize(), 0x44), // Length of calldata in memory.\n                        d, // Offset of returndata.\n                        0x20 // Length of returndata to write.\n                    )\n                )\n                break\n            }\n        }\n    }\n\n    /// @dev Returns whether `signature` is valid for `signer` and `hash`.\n    /// If `signer` is a smart contract, the signature is validated with ERC1271.\n    /// Otherwise, the signature is validated with `ECDSA.recover`.\n    function isValidSignatureNowCalldata(address signer, bytes32 hash, bytes calldata signature)\n        internal\n        view\n        returns (bool isValid)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Clean the upper 96 bits of `signer` in case they are dirty.\n            for { signer := shr(96, shl(96, signer)) } signer {} {\n                let m := mload(0x40)\n                mstore(0x00, hash)\n                if eq(signature.length, 64) {\n                    let vs := calldataload(add(signature.offset, 0x20))\n                    mstore(0x20, add(shr(255, vs), 27)) // `v`.\n                    mstore(0x40, calldataload(signature.offset)) // `r`.\n                    mstore(0x60, shr(1, shl(1, vs))) // `s`.\n                    let t :=\n                        staticcall(\n                            gas(), // Amount of gas left for the transaction.\n                            1, // Address of `ecrecover`.\n                            0x00, // Start of input.\n                            0x80, // Size of input.\n                            0x01, // Start of output.\n                            0x20 // Size of output.\n                        )\n                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n                    if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {\n                        isValid := 1\n                        mstore(0x60, 0) // Restore the zero slot.\n                        mstore(0x40, m) // Restore the free memory pointer.\n                        break\n                    }\n                }\n                if eq(signature.length, 65) {\n                    mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.\n                    calldatacopy(0x40, signature.offset, 0x40) // `r`, `s`.\n                    let t :=\n                        staticcall(\n                            gas(), // Amount of gas left for the transaction.\n                            1, // Address of `ecrecover`.\n                            0x00, // Start of input.\n                            0x80, // Size of input.\n                            0x01, // Start of output.\n                            0x20 // Size of output.\n                        )\n                    // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n                    if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {\n                        isValid := 1\n                        mstore(0x60, 0) // Restore the zero slot.\n                        mstore(0x40, m) // Restore the free memory pointer.\n                        break\n                    }\n                }\n                mstore(0x60, 0) // Restore the zero slot.\n                mstore(0x40, m) // Restore the free memory pointer.\n\n                let f := shl(224, 0x1626ba7e)\n                mstore(m, f) // `bytes4(keccak256(\"isValidSignature(bytes32,bytes)\"))`.\n                mstore(add(m, 0x04), hash)\n                let d := add(m, 0x24)\n                mstore(d, 0x40) // The offset of the `signature` in the calldata.\n                mstore(add(m, 0x44), signature.length)\n                // Copy the `signature` over.\n                calldatacopy(add(m, 0x64), signature.offset, signature.length)\n                // forgefmt: disable-next-item\n                isValid := and(\n                    // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).\n                    eq(mload(d), f),\n                    // Whether the staticcall does not revert.\n                    // This must be placed at the end of the `and` clause,\n                    // as the arguments are evaluated from right to left.\n                    staticcall(\n                        gas(), // Remaining gas.\n                        signer, // The `signer` address.\n                        m, // Offset of calldata in memory.\n                        add(signature.length, 0x64), // Length of calldata in memory.\n                        d, // Offset of returndata.\n                        0x20 // Length of returndata to write.\n                    )\n                )\n                break\n            }\n        }\n    }\n\n    /// @dev Returns whether the signature (`r`, `vs`) is valid for `signer` and `hash`.\n    /// If `signer` is a smart contract, the signature is validated with ERC1271.\n    /// Otherwise, the signature is validated with `ECDSA.recover`.\n    function isValidSignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs)\n        internal\n        view\n        returns (bool isValid)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Clean the upper 96 bits of `signer` in case they are dirty.\n            for { signer := shr(96, shl(96, signer)) } signer {} {\n                let m := mload(0x40)\n                mstore(0x00, hash)\n                mstore(0x20, add(shr(255, vs), 27)) // `v`.\n                mstore(0x40, r) // `r`.\n                mstore(0x60, shr(1, shl(1, vs))) // `s`.\n                let t :=\n                    staticcall(\n                        gas(), // Amount of gas left for the transaction.\n                        1, // Address of `ecrecover`.\n                        0x00, // Start of input.\n                        0x80, // Size of input.\n                        0x01, // Start of output.\n                        0x20 // Size of output.\n                    )\n                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n                if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {\n                    isValid := 1\n                    mstore(0x60, 0) // Restore the zero slot.\n                    mstore(0x40, m) // Restore the free memory pointer.\n                    break\n                }\n\n                let f := shl(224, 0x1626ba7e)\n                mstore(m, f) // `bytes4(keccak256(\"isValidSignature(bytes32,bytes)\"))`.\n                mstore(add(m, 0x04), hash)\n                let d := add(m, 0x24)\n                mstore(d, 0x40) // The offset of the `signature` in the calldata.\n                mstore(add(m, 0x44), 65) // Length of the signature.\n                mstore(add(m, 0x64), r) // `r`.\n                mstore(add(m, 0x84), mload(0x60)) // `s`.\n                mstore8(add(m, 0xa4), mload(0x20)) // `v`.\n                // forgefmt: disable-next-item\n                isValid := and(\n                    // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).\n                    eq(mload(d), f),\n                    // Whether the staticcall does not revert.\n                    // This must be placed at the end of the `and` clause,\n                    // as the arguments are evaluated from right to left.\n                    staticcall(\n                        gas(), // Remaining gas.\n                        signer, // The `signer` address.\n                        m, // Offset of calldata in memory.\n                        0xa5, // Length of calldata in memory.\n                        d, // Offset of returndata.\n                        0x20 // Length of returndata to write.\n                    )\n                )\n                mstore(0x60, 0) // Restore the zero slot.\n                mstore(0x40, m) // Restore the free memory pointer.\n                break\n            }\n        }\n    }\n\n    /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `signer` and `hash`.\n    /// If `signer` is a smart contract, the signature is validated with ERC1271.\n    /// Otherwise, the signature is validated with `ECDSA.recover`.\n    function isValidSignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s)\n        internal\n        view\n        returns (bool isValid)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Clean the upper 96 bits of `signer` in case they are dirty.\n            for { signer := shr(96, shl(96, signer)) } signer {} {\n                let m := mload(0x40)\n                mstore(0x00, hash)\n                mstore(0x20, and(v, 0xff)) // `v`.\n                mstore(0x40, r) // `r`.\n                mstore(0x60, s) // `s`.\n                let t :=\n                    staticcall(\n                        gas(), // Amount of gas left for the transaction.\n                        1, // Address of `ecrecover`.\n                        0x00, // Start of input.\n                        0x80, // Size of input.\n                        0x01, // Start of output.\n                        0x20 // Size of output.\n                    )\n                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n                if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) {\n                    isValid := 1\n                    mstore(0x60, 0) // Restore the zero slot.\n                    mstore(0x40, m) // Restore the free memory pointer.\n                    break\n                }\n\n                let f := shl(224, 0x1626ba7e)\n                mstore(m, f) // `bytes4(keccak256(\"isValidSignature(bytes32,bytes)\"))`.\n                mstore(add(m, 0x04), hash)\n                let d := add(m, 0x24)\n                mstore(d, 0x40) // The offset of the `signature` in the calldata.\n                mstore(add(m, 0x44), 65) // Length of the signature.\n                mstore(add(m, 0x64), r) // `r`.\n                mstore(add(m, 0x84), s) // `s`.\n                mstore8(add(m, 0xa4), v) // `v`.\n                // forgefmt: disable-next-item\n                isValid := and(\n                    // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).\n                    eq(mload(d), f),\n                    // Whether the staticcall does not revert.\n                    // This must be placed at the end of the `and` clause,\n                    // as the arguments are evaluated from right to left.\n                    staticcall(\n                        gas(), // Remaining gas.\n                        signer, // The `signer` address.\n                        m, // Offset of calldata in memory.\n                        0xa5, // Length of calldata in memory.\n                        d, // Offset of returndata.\n                        0x20 // Length of returndata to write.\n                    )\n                )\n                mstore(0x60, 0) // Restore the zero slot.\n                mstore(0x40, m) // Restore the free memory pointer.\n                break\n            }\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                     ERC1271 OPERATIONS                     */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns whether `signature` is valid for `hash` for an ERC1271 `signer` contract.\n    function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes memory signature)\n        internal\n        view\n        returns (bool isValid)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40)\n            let f := shl(224, 0x1626ba7e)\n            mstore(m, f) // `bytes4(keccak256(\"isValidSignature(bytes32,bytes)\"))`.\n            mstore(add(m, 0x04), hash)\n            let d := add(m, 0x24)\n            mstore(d, 0x40) // The offset of the `signature` in the calldata.\n            // Copy the `signature` over.\n            let n := add(0x20, mload(signature))\n            pop(staticcall(gas(), 4, signature, n, add(m, 0x44), n))\n            // forgefmt: disable-next-item\n            isValid := and(\n                // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).\n                eq(mload(d), f),\n                // Whether the staticcall does not revert.\n                // This must be placed at the end of the `and` clause,\n                // as the arguments are evaluated from right to left.\n                staticcall(\n                    gas(), // Remaining gas.\n                    signer, // The `signer` address.\n                    m, // Offset of calldata in memory.\n                    add(returndatasize(), 0x44), // Length of calldata in memory.\n                    d, // Offset of returndata.\n                    0x20 // Length of returndata to write.\n                )\n            )\n        }\n    }\n\n    /// @dev Returns whether `signature` is valid for `hash` for an ERC1271 `signer` contract.\n    function isValidERC1271SignatureNowCalldata(\n        address signer,\n        bytes32 hash,\n        bytes calldata signature\n    ) internal view returns (bool isValid) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40)\n            let f := shl(224, 0x1626ba7e)\n            mstore(m, f) // `bytes4(keccak256(\"isValidSignature(bytes32,bytes)\"))`.\n            mstore(add(m, 0x04), hash)\n            let d := add(m, 0x24)\n            mstore(d, 0x40) // The offset of the `signature` in the calldata.\n            mstore(add(m, 0x44), signature.length)\n            // Copy the `signature` over.\n            calldatacopy(add(m, 0x64), signature.offset, signature.length)\n            // forgefmt: disable-next-item\n            isValid := and(\n                // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).\n                eq(mload(d), f),\n                // Whether the staticcall does not revert.\n                // This must be placed at the end of the `and` clause,\n                // as the arguments are evaluated from right to left.\n                staticcall(\n                    gas(), // Remaining gas.\n                    signer, // The `signer` address.\n                    m, // Offset of calldata in memory.\n                    add(signature.length, 0x64), // Length of calldata in memory.\n                    d, // Offset of returndata.\n                    0x20 // Length of returndata to write.\n                )\n            )\n        }\n    }\n\n    /// @dev Returns whether the signature (`r`, `vs`) is valid for `hash`\n    /// for an ERC1271 `signer` contract.\n    function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs)\n        internal\n        view\n        returns (bool isValid)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40)\n            let f := shl(224, 0x1626ba7e)\n            mstore(m, f) // `bytes4(keccak256(\"isValidSignature(bytes32,bytes)\"))`.\n            mstore(add(m, 0x04), hash)\n            let d := add(m, 0x24)\n            mstore(d, 0x40) // The offset of the `signature` in the calldata.\n            mstore(add(m, 0x44), 65) // Length of the signature.\n            mstore(add(m, 0x64), r) // `r`.\n            mstore(add(m, 0x84), shr(1, shl(1, vs))) // `s`.\n            mstore8(add(m, 0xa4), add(shr(255, vs), 27)) // `v`.\n            // forgefmt: disable-next-item\n            isValid := and(\n                // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).\n                eq(mload(d), f),\n                // Whether the staticcall does not revert.\n                // This must be placed at the end of the `and` clause,\n                // as the arguments are evaluated from right to left.\n                staticcall(\n                    gas(), // Remaining gas.\n                    signer, // The `signer` address.\n                    m, // Offset of calldata in memory.\n                    0xa5, // Length of calldata in memory.\n                    d, // Offset of returndata.\n                    0x20 // Length of returndata to write.\n                )\n            )\n        }\n    }\n\n    /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `hash`\n    /// for an ERC1271 `signer` contract.\n    function isValidERC1271SignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s)\n        internal\n        view\n        returns (bool isValid)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40)\n            let f := shl(224, 0x1626ba7e)\n            mstore(m, f) // `bytes4(keccak256(\"isValidSignature(bytes32,bytes)\"))`.\n            mstore(add(m, 0x04), hash)\n            let d := add(m, 0x24)\n            mstore(d, 0x40) // The offset of the `signature` in the calldata.\n            mstore(add(m, 0x44), 65) // Length of the signature.\n            mstore(add(m, 0x64), r) // `r`.\n            mstore(add(m, 0x84), s) // `s`.\n            mstore8(add(m, 0xa4), v) // `v`.\n            // forgefmt: disable-next-item\n            isValid := and(\n                // Whether the returndata is the magic value `0x1626ba7e` (left-aligned).\n                eq(mload(d), f),\n                // Whether the staticcall does not revert.\n                // This must be placed at the end of the `and` clause,\n                // as the arguments are evaluated from right to left.\n                staticcall(\n                    gas(), // Remaining gas.\n                    signer, // The `signer` address.\n                    m, // Offset of calldata in memory.\n                    0xa5, // Length of calldata in memory.\n                    d, // Offset of returndata.\n                    0x20 // Length of returndata to write.\n                )\n            )\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                     HASHING OPERATIONS                     */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns an Ethereum Signed Message, created from a `hash`.\n    /// This produces a hash corresponding to the one signed with the\n    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)\n    /// JSON-RPC method as part of EIP-191.\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x20, hash) // Store into scratch space for keccak256.\n            mstore(0x00, \"\\x00\\x00\\x00\\x00\\x19Ethereum Signed Message:\\n32\") // 28 bytes.\n            result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.\n        }\n    }\n\n    /// @dev Returns an Ethereum Signed Message, created from `s`.\n    /// This produces a hash corresponding to the one signed with the\n    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)\n    /// JSON-RPC method as part of EIP-191.\n    /// Note: Supports lengths of `s` up to 999999 bytes.\n    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let sLength := mload(s)\n            let o := 0x20\n            mstore(o, \"\\x19Ethereum Signed Message:\\n\") // 26 bytes, zero-right-padded.\n            mstore(0x00, 0x00)\n            // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.\n            for { let temp := sLength } 1 {} {\n                o := sub(o, 1)\n                mstore8(o, add(48, mod(temp, 10)))\n                temp := div(temp, 10)\n                if iszero(temp) { break }\n            }\n            let n := sub(0x3a, o) // Header length: `26 + 32 - o`.\n            // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.\n            returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))\n            mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.\n            result := keccak256(add(s, sub(0x20, n)), add(n, sLength))\n            mstore(s, sLength) // Restore the length.\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                   EMPTY CALLDATA HELPERS                   */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns an empty calldata bytes.\n    function emptySignature() internal pure returns (bytes calldata signature) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            signature.length := 0\n        }\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": false,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}