{"file_path":"contracts/core/ToriMinting.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: GPL-3.0\npragma solidity 0.8.28;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/access/extensions/AccessControlDefaultAdminRules.sol\";\nimport \"@openzeppelin/contracts/utils/Pausable.sol\";\nimport \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol\";\nimport \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\nimport \"@openzeppelin/contracts/interfaces/IERC1271.sol\";\n\ninterface ITrUSD {\n    function mint(address to, uint256 amount) external;\n    function burnFrom(address from, uint256 amount) external;\n}\n\n/**\n * @title ToriMinting\n * @notice Signature-based minting and redemption contract for TrUSD\n */\ncontract ToriMinting is AccessControlDefaultAdminRules, Pausable, ReentrancyGuard {\n    using SafeERC20 for IERC20;\n    using EnumerableSet for EnumerableSet.AddressSet;\n\n    /* ========== CONSTANTS ========== */\n\n    bytes32 private constant EIP712_DOMAIN =\n        keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n\n    bytes32 private constant ORDER_TYPE = keccak256(\n        \"Order(uint8 order_type,address sender,address recipient,address collateral_asset,uint128 collateral_amount,uint128 trusd_amount,uint128 expiry,uint256 nonce,string order_id)\"\n    );\n\n    bytes32 private constant EIP_712_NAME = keccak256(\"ToriMinting\");\n    bytes32 private constant EIP712_REVISION = keccak256(\"1\");\n    uint128 private constant STABLES_RATIO_MULTIPLIER = 10000;\n\n    /* ========== ROLES ========== */\n\n    bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n    bytes32 public constant REDEEMER_ROLE = keccak256(\"REDEEMER_ROLE\");\n    bytes32 public constant GATEKEEPER_ROLE = keccak256(\"GATEKEEPER_ROLE\");\n    bytes32 public constant COLLATERAL_MANAGER_ROLE = keccak256(\"COLLATERAL_MANAGER_ROLE\");\n    bytes32 public constant WHITELISTER_ROLE = keccak256(\"WHITELISTER_ROLE\");\n    /// @notice Role for timelock-protected operations (addAllowedToken)\n    bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256(\"TIMELOCK_ADMIN_ROLE\");\n\n    /* ========== ENUMS ========== */\n\n    enum OrderType {\n        MINT,\n        REDEEM\n    }\n\n    enum SignatureType {\n        EIP712,\n        EIP1271\n    }\n\n    enum TokenType {\n        STABLE\n    }\n\n    /* ========== STRUCTS ========== */\n\n    struct Order {\n        OrderType order_type;\n        address sender;\n        address recipient;\n        address collateral_asset;\n        uint128 collateral_amount;\n        uint128 trusd_amount;\n        uint128 expiry;\n        uint256 nonce;\n        string order_id;\n    }\n\n    struct Signature {\n        SignatureType signature_type;\n        bytes signature_bytes;\n    }\n\n    struct TokenConfig {\n        TokenType tokenType;\n        bool isActive;\n        uint128 maxMintPerBlock;\n        uint128 maxRedeemPerBlock;\n    }\n\n    struct BlockTotals {\n        uint128 mintedPerBlock;\n        uint128 redeemedPerBlock;\n    }\n\n    struct Route {\n        address[] addresses;\n        uint128[] ratios;\n    }\n\n    /* ========== STATE VARIABLES ========== */\n\n    address public immutable TRUSD_ADDRESS;\n\n    mapping(address => bool) public whitelisted;\n    mapping(address => EnumerableSet.AddressSet) private _approvedRecipientsPerSender;\n    mapping(address => TokenConfig) public tokenConfig;\n\n    uint128 public globalMaxMintPerBlock;\n    uint128 public globalMaxRedeemPerBlock;\n\n    mapping(uint256 => BlockTotals) public totalPerBlock;\n    mapping(uint256 => mapping(address => BlockTotals)) public totalPerBlockPerAsset;\n    mapping(address => mapping(uint256 => uint256)) private _orderBitmaps;\n\n    uint256 private immutable CHAIN_ID;\n    bytes32 private immutable DOMAIN_SEPARATOR;\n    uint128 public stablesDeltaLimit;\n\n    EnumerableSet.AddressSet private _custodianAddresses;\n    bool private _timelockAdminInitialized;\n\n    /* ========== EVENTS ========== */\n\n    event TokenAdded(address indexed token);\n    event TokenRemoved(address indexed token);\n    event MaxMintPerBlockChanged(uint128 oldMaxMintPerBlock, uint128 newMaxMintPerBlock, address indexed asset);\n    event MaxRedeemPerBlockChanged(uint128 oldMaxRedeemPerBlock, uint128 newMaxRedeemPerBlock, address indexed asset);\n    event GlobalLimitsUpdated(uint128 globalMaxMintPerBlock, uint128 globalMaxRedeemPerBlock);\n    event UserWhitelisted(address indexed user);\n    event UserRemovedFromWhitelist(address indexed user);\n    event Minted(\n        address indexed sender,\n        address indexed recipient,\n        address indexed collateral_asset,\n        uint128 collateral_amount,\n        uint128 trusd_amount,\n        string order_id\n    );\n    event Redeemed(\n        address indexed sender,\n        address indexed recipient,\n        address indexed collateral_asset,\n        uint128 trusd_amount,\n        uint128 collateral_amount,\n        string order_id\n    );\n    event CustodianAddressAdded(address indexed custodian);\n    event CustodianAddressRemoved(address indexed custodian);\n    event RecipientAdded(address indexed sender, address indexed recipient);\n    event RecipientRemoved(address indexed sender, address indexed recipient);\n    event TimelockAdminUpdated(address indexed oldTimelockAdmin, address indexed newTimelockAdmin);\n\n    /* ========== ERRORS ========== */\n\n    error ZeroAddress();\n    error UseSetTimelockAdmin();\n    error TimelockAdminAlreadyInitialized();\n    error NotWhitelisted(address user);\n    error TokenNotAllowed(address token);\n    error InvalidAmount();\n    error InvalidTokenAddress();\n    error UnsupportedAsset();\n    error MaxMintPerBlockExceeded();\n    error MaxRedeemPerBlockExceeded();\n    error GlobalMaxMintPerBlockExceeded();\n    error GlobalMaxRedeemPerBlockExceeded();\n    error InvalidOrder();\n    error InvalidNonce();\n    error InvalidEIP712Signature();\n    error InvalidEIP1271Signature();\n    error UnknownSignatureType();\n    error SignatureExpired();\n    error InvalidStablePrice();\n    error InvalidAddress();\n    error InvalidCustodianAddress();\n    error InvalidRoute();\n    error RecipientNotApproved();\n\n    /* ========== MODIFIERS ========== */\n\n    modifier belowMaxMintPerBlock(uint128 mintAmount, address asset) {\n        TokenConfig memory config = tokenConfig[asset];\n        if (!config.isActive) revert UnsupportedAsset();\n        if (totalPerBlockPerAsset[block.number][asset].mintedPerBlock + mintAmount > config.maxMintPerBlock) {\n            revert MaxMintPerBlockExceeded();\n        }\n        _;\n    }\n\n    modifier belowMaxRedeemPerBlock(uint128 redeemAmount, address asset) {\n        TokenConfig memory config = tokenConfig[asset];\n        if (!config.isActive) revert UnsupportedAsset();\n        if (totalPerBlockPerAsset[block.number][asset].redeemedPerBlock + redeemAmount > config.maxRedeemPerBlock) {\n            revert MaxRedeemPerBlockExceeded();\n        }\n        _;\n    }\n\n    modifier belowGlobalMaxMintPerBlock(uint128 mintAmount) {\n        if (totalPerBlock[block.number].mintedPerBlock + mintAmount > globalMaxMintPerBlock) {\n            revert GlobalMaxMintPerBlockExceeded();\n        }\n        _;\n    }\n\n    modifier belowGlobalMaxRedeemPerBlock(uint128 redeemAmount) {\n        if (totalPerBlock[block.number].redeemedPerBlock + redeemAmount > globalMaxRedeemPerBlock) {\n            revert GlobalMaxRedeemPerBlockExceeded();\n        }\n        _;\n    }\n\n    /* ========== CONSTRUCTOR ========== */\n\n    constructor(\n        address _trUSDAddress,\n        address[] memory _allowedTokens,\n        TokenConfig[] memory _tokenConfigs,\n        uint128 _globalMaxMintPerBlock,\n        uint128 _globalMaxRedeemPerBlock,\n        address _admin\n    ) AccessControlDefaultAdminRules(1 days, _admin) {\n        if (_admin == address(0)) revert ZeroAddress();\n        if (_trUSDAddress == address(0)) revert ZeroAddress();\n        if (_allowedTokens.length != _tokenConfigs.length) revert InvalidAmount();\n        if (_allowedTokens.length == 0) revert InvalidAmount();\n\n        TRUSD_ADDRESS = _trUSDAddress;\n        globalMaxMintPerBlock = _globalMaxMintPerBlock;\n        globalMaxRedeemPerBlock = _globalMaxRedeemPerBlock;\n\n        for (uint256 i = 0; i < _allowedTokens.length; i++) {\n            address token = _allowedTokens[i];\n            TokenConfig memory config = _tokenConfigs[i];\n\n            if (token == address(0) || token == _trUSDAddress || token.code.length == 0) {\n                revert InvalidTokenAddress();\n            }\n            if (config.maxMintPerBlock == 0 || config.maxRedeemPerBlock == 0) revert InvalidAmount();\n\n            tokenConfig[token] = TokenConfig({\n                tokenType: config.tokenType,\n                isActive: true,\n                maxMintPerBlock: config.maxMintPerBlock,\n                maxRedeemPerBlock: config.maxRedeemPerBlock\n            });\n            emit TokenAdded(token);\n        }\n\n        CHAIN_ID = block.chainid;\n        DOMAIN_SEPARATOR = _computeDomainSeparator();\n    }\n\n    /* ========== USER FUNCTIONS ========== */\n\n    /**\n     * @notice Mint TrUSD with user-signed order\n     * @param order Order details\n     * @param signature User's EIP-712 / EIP-1271 signature\n     * @param route Custody routing for collateral\n     */\n    function mint(Order calldata order, Signature calldata signature, Route calldata route)\n        external\n        nonReentrant\n        whenNotPaused\n        onlyRole(MINTER_ROLE)\n        belowMaxMintPerBlock(order.trusd_amount, order.collateral_asset)\n        belowGlobalMaxMintPerBlock(order.trusd_amount)\n    {\n        if (order.order_type != OrderType.MINT) revert InvalidOrder();\n        if (!whitelisted[order.sender]) revert NotWhitelisted(order.sender);\n\n        verifyOrder(order, signature);\n        if (!verifyRoute(route)) revert InvalidRoute();\n        _deduplicateOrder(order.sender, order.nonce);\n\n        totalPerBlockPerAsset[block.number][order.collateral_asset].mintedPerBlock += order.trusd_amount;\n        totalPerBlock[block.number].mintedPerBlock += order.trusd_amount;\n\n        _transferCollateral(order.collateral_amount, order.collateral_asset, order.sender, route.addresses, route.ratios);\n        ITrUSD(TRUSD_ADDRESS).mint(order.recipient, order.trusd_amount);\n\n        emit Minted(order.sender, order.recipient, order.collateral_asset, order.collateral_amount, order.trusd_amount, order.order_id);\n    }\n\n    /**\n     * @notice Redeem TrUSD for collateral\n     * @param order Order details\n     * @param signature User's EIP-712 signature\n     */\n    function redeem(Order calldata order, Signature calldata signature)\n        external\n        nonReentrant\n        whenNotPaused\n        onlyRole(REDEEMER_ROLE)\n        belowMaxRedeemPerBlock(order.trusd_amount, order.collateral_asset)\n        belowGlobalMaxRedeemPerBlock(order.trusd_amount)\n    {\n        if (order.order_type != OrderType.REDEEM) revert InvalidOrder();\n        if (!whitelisted[order.sender]) revert NotWhitelisted(order.sender);\n\n        verifyOrder(order, signature);\n        _deduplicateOrder(order.sender, order.nonce);\n\n        totalPerBlockPerAsset[block.number][order.collateral_asset].redeemedPerBlock += order.trusd_amount;\n        totalPerBlock[block.number].redeemedPerBlock += order.trusd_amount;\n\n        ITrUSD(TRUSD_ADDRESS).burnFrom(order.sender, order.trusd_amount);\n        IERC20(order.collateral_asset).safeTransfer(order.recipient, order.collateral_amount);\n\n        emit Redeemed(order.sender, order.recipient, order.collateral_asset, order.trusd_amount, order.collateral_amount, order.order_id);\n    }\n\n    /* ========== ADMIN FUNCTIONS ========== */\n\n    function addAllowedToken(address _token, TokenConfig memory _config) external onlyRole(TIMELOCK_ADMIN_ROLE) {\n        if (_token == address(0) || _token == TRUSD_ADDRESS || _token.code.length == 0) {\n            revert InvalidTokenAddress();\n        }\n        if (_config.maxMintPerBlock == 0 || _config.maxRedeemPerBlock == 0) revert InvalidAmount();\n\n        tokenConfig[_token] = TokenConfig({\n            isActive: true,\n            tokenType: _config.tokenType,\n            maxMintPerBlock: _config.maxMintPerBlock,\n            maxRedeemPerBlock: _config.maxRedeemPerBlock\n        });\n        emit TokenAdded(_token);\n    }\n\n    function removeAllowedToken(address _token) external onlyRole(DEFAULT_ADMIN_ROLE) {\n        if (_token == address(0)) revert ZeroAddress();\n        if (tokenConfig[_token].maxMintPerBlock == 0 && tokenConfig[_token].maxRedeemPerBlock == 0) revert TokenNotAllowed(_token);\n        delete tokenConfig[_token];\n        emit TokenRemoved(_token);\n    }\n\n    function enableAllowedToken(address _token) external onlyRole(TIMELOCK_ADMIN_ROLE) {\n        if (_token == address(0)) revert ZeroAddress();\n        if (tokenConfig[_token].maxMintPerBlock == 0) revert TokenNotAllowed(_token);\n        tokenConfig[_token].isActive = true;\n    }\n\n    function disableAllowedToken(address _token) external onlyRole(DEFAULT_ADMIN_ROLE) {\n        if (_token == address(0)) revert ZeroAddress();\n        if (!tokenConfig[_token].isActive) revert TokenNotAllowed(_token);\n        tokenConfig[_token].isActive = false;\n    }\n\n    function setStablesDeltaLimit(uint128 _stablesDeltaLimit) external onlyRole(TIMELOCK_ADMIN_ROLE) {\n        stablesDeltaLimit = _stablesDeltaLimit;\n    }\n\n    function setGlobalLimits(uint128 _globalMaxMintPerBlock, uint128 _globalMaxRedeemPerBlock)\n        external\n        onlyRole(DEFAULT_ADMIN_ROLE)\n    {\n        globalMaxMintPerBlock = _globalMaxMintPerBlock;\n        globalMaxRedeemPerBlock = _globalMaxRedeemPerBlock;\n        emit GlobalLimitsUpdated(_globalMaxMintPerBlock, _globalMaxRedeemPerBlock);\n    }\n\n    function setMaxMintPerBlock(uint128 _maxMintPerBlock, address asset) external onlyRole(DEFAULT_ADMIN_ROLE) {\n        if (!tokenConfig[asset].isActive) revert TokenNotAllowed(asset);\n        uint128 oldMaxMintPerBlock = tokenConfig[asset].maxMintPerBlock;\n        tokenConfig[asset].maxMintPerBlock = _maxMintPerBlock;\n        emit MaxMintPerBlockChanged(oldMaxMintPerBlock, _maxMintPerBlock, asset);\n    }\n\n    function setMaxRedeemPerBlock(uint128 _maxRedeemPerBlock, address asset) external onlyRole(DEFAULT_ADMIN_ROLE) {\n        if (!tokenConfig[asset].isActive) revert TokenNotAllowed(asset);\n        uint128 oldMaxRedeemPerBlock = tokenConfig[asset].maxRedeemPerBlock;\n        tokenConfig[asset].maxRedeemPerBlock = _maxRedeemPerBlock;\n        emit MaxRedeemPerBlockChanged(oldMaxRedeemPerBlock, _maxRedeemPerBlock, asset);\n    }\n\n    function addToWhitelist(address _user) external onlyRole(WHITELISTER_ROLE) {\n        if (_user == address(0)) revert ZeroAddress();\n        whitelisted[_user] = true;\n        emit UserWhitelisted(_user);\n    }\n\n    function addToWhitelistBatch(address[] calldata _users) external onlyRole(WHITELISTER_ROLE) {\n        for (uint256 i = 0; i < _users.length; i++) {\n            if (_users[i] != address(0)) {\n                whitelisted[_users[i]] = true;\n                emit UserWhitelisted(_users[i]);\n            }\n        }\n    }\n\n    function removeFromWhitelist(address _user) external onlyRole(WHITELISTER_ROLE) {\n        whitelisted[_user] = false;\n        emit UserRemovedFromWhitelist(_user);\n    }\n\n    function pause() external onlyRole(DEFAULT_ADMIN_ROLE) {\n        _pause();\n    }\n\n    function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) {\n        _unpause();\n    }\n\n    function disableMintRedeem() external onlyRole(GATEKEEPER_ROLE) {\n        globalMaxMintPerBlock = 0;\n        globalMaxRedeemPerBlock = 0;\n    }\n\n    /// @notice Removes the minter role from an account, this can ONLY be executed by the gatekeeper role\n    /// @param minter The address to remove the minter role from\n    function removeMinterRole(address minter) external onlyRole(GATEKEEPER_ROLE) {\n        _revokeRole(MINTER_ROLE, minter);\n    }\n\n    /// @notice Removes the redeemer role from an account, this can ONLY be executed by the gatekeeper role\n    /// @param redeemer The address to remove the redeemer role from\n    function removeRedeemerRole(address redeemer) external onlyRole(GATEKEEPER_ROLE) {\n        _revokeRole(REDEEMER_ROLE, redeemer);\n    }\n\n    /// @notice Removes the collateral manager role from an account, this can ONLY be executed by the gatekeeper role\n    /// @param collateralManager The address to remove the collateral manager role from\n    function removeCollateralManagerRole(address collateralManager) external onlyRole(GATEKEEPER_ROLE) {\n        _revokeRole(COLLATERAL_MANAGER_ROLE, collateralManager);\n    }\n\n    /**\n     * @notice Initialize the timelock admin - can only be called once by DEFAULT_ADMIN\n     * @param timelockAdmin Address of the timelock contract\n     * @dev This bootstraps the TIMELOCK_ADMIN_ROLE for the first time\n     */\n    function initializeTimelockAdmin(address timelockAdmin) external onlyRole(DEFAULT_ADMIN_ROLE) {\n        if (timelockAdmin == address(0)) revert ZeroAddress();\n        if (_timelockAdminInitialized) revert TimelockAdminAlreadyInitialized();\n\n        _timelockAdminInitialized = true;\n        _grantRole(TIMELOCK_ADMIN_ROLE, timelockAdmin);\n        emit TimelockAdminUpdated(address(0), timelockAdmin);\n    }\n\n    /**\n     * @notice Set a new timelock admin - must be called via timelock\n     * @param newTimelockAdmin New timelock admin address\n     * @dev This is the ONLY way to change TIMELOCK_ADMIN_ROLE after initialization\n     */\n    function setTimelockAdmin(address newTimelockAdmin) external onlyRole(TIMELOCK_ADMIN_ROLE) {\n        if (newTimelockAdmin == address(0)) revert ZeroAddress();\n\n        address currentAdmin = msg.sender;\n\n        _revokeRole(TIMELOCK_ADMIN_ROLE, currentAdmin);\n        _grantRole(TIMELOCK_ADMIN_ROLE, newTimelockAdmin);\n\n        emit TimelockAdminUpdated(currentAdmin, newTimelockAdmin);\n    }\n\n    /**\n     * @dev Override grantRole to block direct TIMELOCK_ADMIN_ROLE grants\n     */\n    function grantRole(bytes32 role, address account) public virtual override {\n        if (role == TIMELOCK_ADMIN_ROLE) revert UseSetTimelockAdmin();\n        super.grantRole(role, account);\n    }\n\n    /**\n     * @dev Override revokeRole to block direct TIMELOCK_ADMIN_ROLE revocations\n     */\n    function revokeRole(bytes32 role, address account) public virtual override {\n        if (role == TIMELOCK_ADMIN_ROLE) revert UseSetTimelockAdmin();\n        super.revokeRole(role, account);\n    }\n\n    /* ========== RECIPIENT MANAGEMENT ========== */\n\n    function setApprovedRecipient(address recipient, bool status) public {\n        if (recipient == address(0)) revert InvalidAddress();\n\n        if (status) {\n            if (!_approvedRecipientsPerSender[msg.sender].add(recipient)) {\n                revert InvalidAddress();\n            }\n            emit RecipientAdded(msg.sender, recipient);\n        } else {\n            if (!_approvedRecipientsPerSender[msg.sender].remove(recipient)) {\n                revert InvalidAddress();\n            }\n            emit RecipientRemoved(msg.sender, recipient);\n        }\n    }\n\n    function isApprovedRecipient(address sender, address recipient) public view returns (bool) {\n        return _approvedRecipientsPerSender[sender].contains(recipient);\n    }\n\n    /* ========== CUSTODIAN MANAGEMENT ========== */\n\n    function addCustodianAddress(address custodian) external onlyRole(TIMELOCK_ADMIN_ROLE) {\n        if (custodian == address(0) || custodian == address(this)) revert InvalidAddress();\n        if (_custodianAddresses.contains(custodian)) revert InvalidCustodianAddress();\n\n        _custodianAddresses.add(custodian);\n        emit CustodianAddressAdded(custodian);\n    }\n\n    function removeCustodianAddress(address custodian) external onlyRole(DEFAULT_ADMIN_ROLE) {\n        if (!_custodianAddresses.contains(custodian)) revert InvalidCustodianAddress();\n\n        _custodianAddresses.remove(custodian);\n        emit CustodianAddressRemoved(custodian);\n    }\n\n    function transferToCustody(address asset, uint256 amount, Route calldata route)\n        external\n        nonReentrant\n        onlyRole(COLLATERAL_MANAGER_ROLE)\n    {\n        uint256 totalRatio;\n        uint256 amountToTransfer;\n        uint256 totalTransferred;\n\n        if (route.addresses.length != route.ratios.length || route.addresses.length == 0) {\n            revert InvalidRoute();\n        }\n\n        for (uint256 i = 0; i < route.addresses.length;) {\n            if (!_custodianAddresses.contains(route.addresses[i])) {\n                revert InvalidCustodianAddress();\n            }\n            totalRatio += route.ratios[i];\n            unchecked {\n                ++i;\n            }\n        }\n\n        if (totalRatio != 10_000) revert InvalidRoute();\n\n        for (uint256 i = 0; i < route.addresses.length;) {\n            amountToTransfer = (amount * route.ratios[i]) / 10_000;\n            if (amountToTransfer > 0) {\n                IERC20(asset).safeTransfer(route.addresses[i], amountToTransfer);\n                totalTransferred += amountToTransfer;\n            }\n            unchecked {\n                ++i;\n            }\n        }\n\n        // Handle rounding remainder - send to last custodian\n        uint256 remainder = amount - totalTransferred;\n        if (remainder > 0) {\n            IERC20(asset).safeTransfer(route.addresses[route.addresses.length - 1], remainder);\n        }\n    }\n\n    function getCustodianAddresses() external view returns (address[] memory) {\n        return _custodianAddresses.values();\n    }\n\n    /* ========== VIEW FUNCTIONS ========== */\n\n    function getDomainSeparator() public view returns (bytes32) {\n        if (block.chainid == CHAIN_ID) {\n            return DOMAIN_SEPARATOR;\n        }\n        return _computeDomainSeparator();\n    }\n\n    function hashOrder(Order calldata order) public view returns (bytes32) {\n        return MessageHashUtils.toTypedDataHash(getDomainSeparator(), keccak256(encodeOrder(order)));\n    }\n\n    function encodeOrder(Order calldata order) public pure returns (bytes memory) {\n        return abi.encode(\n            ORDER_TYPE,\n            order.order_type,\n            order.sender,\n            order.recipient,\n            order.collateral_asset,\n            order.collateral_amount,\n            order.trusd_amount,\n            order.expiry,\n            order.nonce,\n            keccak256(bytes(order.order_id))\n        );\n    }\n\n    function verifyOrder(Order calldata order, Signature calldata signature) public view returns (bytes32) {\n        bytes32 orderHash = hashOrder(order);\n\n        if (signature.signature_type == SignatureType.EIP712) {\n            // EOA signature verification\n            address signer = ECDSA.recover(orderHash, signature.signature_bytes);\n            if (signer != order.sender) revert InvalidEIP712Signature();\n        } else if (signature.signature_type == SignatureType.EIP1271) {\n            // Smart contract wallet signature verification (Gnosis Safe, Argent, etc.)\n            if (\n                IERC1271(order.sender).isValidSignature(orderHash, signature.signature_bytes)\n                    != IERC1271.isValidSignature.selector\n            ) {\n                revert InvalidEIP1271Signature();\n            }\n        } else {\n            revert UnknownSignatureType();\n        }\n\n        if (order.sender != order.recipient) {\n            if (!_approvedRecipientsPerSender[order.sender].contains(order.recipient)) {\n                revert RecipientNotApproved();\n            }\n        }\n\n        if (order.recipient == address(0)) revert InvalidAddress();\n        if (!tokenConfig[order.collateral_asset].isActive) revert TokenNotAllowed(order.collateral_asset);\n\n        if (order.collateral_amount == 0 || order.trusd_amount == 0) revert InvalidAmount();\n\n        if (tokenConfig[order.collateral_asset].tokenType != TokenType.STABLE) {\n            revert UnsupportedAsset();\n        }\n        if (!verifyStablesLimit(order.collateral_amount, order.trusd_amount, order.collateral_asset, order.order_type)) {\n            revert InvalidStablePrice();\n        }\n        if (block.timestamp > order.expiry) revert SignatureExpired();\n\n        return orderHash;\n    }\n\n    function verifyNonce(address sender, uint256 nonce) public view returns (uint256, uint256, uint256) {\n        if (nonce == 0) revert InvalidNonce();\n        uint256 invalidatorSlot = uint128(nonce) >> 8;\n        uint256 invalidatorBit = 1 << uint8(nonce);\n        uint256 invalidator = _orderBitmaps[sender][invalidatorSlot];\n        if (invalidator & invalidatorBit != 0) revert InvalidNonce();\n\n        return (invalidatorSlot, invalidator, invalidatorBit);\n    }\n\n    function verifyRoute(Route calldata route) public view returns (bool) {\n        uint128 totalRatio = 0;\n\n        // Route must have matching lengths\n        if (route.addresses.length != route.ratios.length) {\n            return false;\n        }\n\n        // Route cannot be empty\n        if (route.addresses.length == 0) {\n            return false;\n        }\n\n        // Validate each address is approved custodian and sum ratios\n        for (uint128 i = 0; i < route.addresses.length;) {\n            if (!_custodianAddresses.contains(route.addresses[i]) ||\n                route.addresses[i] == address(0) ||\n                route.ratios[i] == 0) {\n                return false;\n            }\n            totalRatio += route.ratios[i];\n            unchecked {\n                ++i;\n            }\n        }\n\n        // Total ratio must equal 10000 (100%)\n        return (totalRatio == 10_000);\n    }\n\n    function isSupportedAsset(address asset) external view returns (bool) {\n        return tokenConfig[asset].isActive;\n    }\n\n    function verifyStablesLimit(\n        uint128 collateralAmount,\n        uint128 trusdAmount,\n        address collateralAsset,\n        OrderType orderType\n    ) public view returns (bool) {\n        uint128 trusdDecimals = _getDecimals(TRUSD_ADDRESS);\n        uint128 collateralDecimals = _getDecimals(collateralAsset);\n\n        uint128 normalizedCollateralAmount;\n        uint128 scale = uint128(\n            trusdDecimals > collateralDecimals\n                ? 10 ** (trusdDecimals - collateralDecimals)\n                : 10 ** (collateralDecimals - trusdDecimals)\n        );\n\n        normalizedCollateralAmount = trusdDecimals > collateralDecimals\n            ? collateralAmount * scale\n            : collateralAmount / scale;\n\n        uint128 difference = normalizedCollateralAmount > trusdAmount\n            ? normalizedCollateralAmount - trusdAmount\n            : trusdAmount - normalizedCollateralAmount;\n\n        uint128 differenceInBps = (difference * STABLES_RATIO_MULTIPLIER) / trusdAmount;\n\n        if (orderType == OrderType.MINT) {\n            return trusdAmount > normalizedCollateralAmount ? differenceInBps <= stablesDeltaLimit : true;\n        } else {\n            return normalizedCollateralAmount > trusdAmount ? differenceInBps <= stablesDeltaLimit : true;\n        }\n    }\n\n    /* ========== INTERNAL FUNCTIONS ========== */\n\n    function _deduplicateOrder(address sender, uint256 nonce) internal {\n        (uint256 invalidatorSlot, uint256 invalidator, uint256 invalidatorBit) = verifyNonce(sender, nonce);\n        _orderBitmaps[sender][invalidatorSlot] = invalidator | invalidatorBit;\n    }\n\n    function _transferCollateral(\n        uint128 amount,\n        address asset,\n        address from,\n        address[] calldata addresses,\n        uint128[] calldata ratios\n    ) internal {\n        if (!tokenConfig[asset].isActive) revert UnsupportedAsset();\n\n        IERC20 token = IERC20(asset);\n        uint128 totalTransferred = 0;\n\n        for (uint128 i = 0; i < addresses.length;) {\n            uint128 amountToTransfer = (amount * ratios[i]) / 10_000;\n            token.safeTransferFrom(from, addresses[i], amountToTransfer);\n            totalTransferred += amountToTransfer;\n            unchecked {\n                ++i;\n            }\n        }\n\n        uint128 remainingBalance = amount - totalTransferred;\n        if (remainingBalance > 0) {\n            token.safeTransferFrom(from, addresses[addresses.length - 1], remainingBalance);\n        }\n    }\n\n    function _computeDomainSeparator() internal view returns (bytes32) {\n        return keccak256(\n            abi.encode(EIP712_DOMAIN, EIP_712_NAME, EIP712_REVISION, block.chainid, address(this))\n        );\n    }\n\n    function _getDecimals(address token) internal view returns (uint128) {\n        uint8 decimals = IERC20Metadata(token).decimals();\n        return uint128(decimals);\n    }\n}\n","deployed_bytecode":"0x608060405234801561000f575f5ffd5b50600436106103eb575f3560e01c806389b66fe01161020b578063c5ff38bd1161011f578063d602b9fd116100b4578063e077020211610084578063e0770202146109c6578063e43252d7146109d9578063ed24911d146109ec578063f4ee2a8b146109f4578063fe136c4e14610a22575f5ffd5b8063d602b9fd14610975578063d6fd31751461097d578063d7d0a09414610991578063d936547e146109a4575f5ffd5b8063cf6eefb7116100ef578063cf6eefb7146108fa578063d539139314610928578063d547741f1461094f578063d58c2dee14610962575f5ffd5b8063c5ff38bd146108cf578063c7f2f0bf146108d7578063cc8463c8146108ea578063cefc1429146108f2575f5ffd5b80639be918e6116101a0578063a693635e11610170578063a693635e14610838578063af4eca3514610876578063afa774b314610889578063b3be507b146108a9578063be4088ee146108bc575f5ffd5b80639be918e6146107c7578063a1eda53c146107f7578063a217fddf1461081e578063a617713914610825575f5ffd5b806390469a9d116101db57806390469a9d1461073b57806391d148541461074e57806392408dc71461076157806392a3c04f146107b4575f5ffd5b806389b66fe0146106e65780638ab1d6811461070d5780638da5cb5b146107205780638dfd87e214610728575f5ffd5b80634ba87af9116103025780635c975abb1161029757806372c117981161026757806372c117981461066c5780637ac5f2d81461067f5780637fa46ab4146106925780638456cb59146106b957806384ef8ffc146106c1575f5ffd5b80635c975abb14610628578063634e93da14610633578063649a5ec7146106465780637274c25c14610659575f5ffd5b8063532c3f82116102d2578063532c3f82146105db57806354f1e126146105ee578063570618e114610601578063591c354414610615575f5ffd5b80634ba87af9146105885780634be7a64b1461059b5780634d9f73f2146105ae5780634e128fe0146105c1575f5ffd5b80632f2ff15d116103835780633bb935b4116103535780633bb935b41461051c5780633f1fda50146105475780633f4ba83a1461055a578063435a3ca914610562578063488e966b14610575575f5ffd5b80632f2ff15d146104ce57806331998fac146104e1578063334cfda4146104f457806336568abe14610509575f5ffd5b806312a4a10e116103be57806312a4a10e1461045f5780631f6c7da214610472578063248a9ca3146104855780632e718ab7146104a7575f5ffd5b806301ffc9a7146103ef578063022d63fb146104175780630aa6220b146104335780630d3cf6fc1461043d575b5f5ffd5b6104026103fd366004614062565b610a7a565b60405190151581526020015b60405180910390f35b620697805b60405165ffffffffffff909116815260200161040e565b61043b610aa4565b005b6104515f516020614aa25f395f51905f5281565b60405190815260200161040e565b61043b61046d3660046140ae565b610ab9565b6104026104803660046140f5565b610b93565b610451610493366004614126565b5f9081526020819052604090206001015490565b6104517f85e8f2d6819d6b24108062d87ea08f54651bcb8960d98062d3faf96e7873b8b981565b61043b6104dc36600461413d565b610d40565b61043b6104ef36600461415e565b610d7b565b6104fc610e2e565b60405161040e9190614177565b61043b61051736600461413d565b610e3f565b60085461052f906001600160801b031681565b6040516001600160801b03909116815260200161040e565b61043b61055536600461415e565b610ee5565b61043b610f9a565b61043b61057036600461415e565b610fac565b6104516105833660046141d3565b611047565b61043b61059636600461415e565b611082565b61043b6105a936600461415e565b6110f7565b61043b6105bc366004614204565b6111b6565b60085461052f90600160801b90046001600160801b031681565b61043b6105e936600461415e565b61170f565b61043b6105fc36600461415e565b611755565b6104515f516020614a825f395f51905f5281565b610402610623366004614267565b611796565b60035460ff16610402565b61043b61064136600461415e565b6117be565b61043b610654366004614281565b6117d1565b61043b61066736600461415e565b6117e4565b61043b61067a3660046142a6565b611825565b61043b61068d36600461415e565b611889565b6104517f44ac9762eec3a11893fefb11d028bb3102560094137c3ed4518712475b2577cc81565b61043b61193d565b6002546001600160a01b03165b6040516001600160a01b03909116815260200161040e565b6106ce7f000000000000000000000000d0580192e98ea6ceb9c7b6191ed2e2756091169781565b61043b61071b36600461415e565b61194f565b6106ce6119af565b61043b6107363660046142eb565b6119c2565b61043b61074936600461415e565b611bc6565b61040261075c36600461413d565b611ce0565b61079461076f366004614126565b60096020525f90815260409020546001600160801b0380821691600160801b90041682565b604080516001600160801b0393841681529290911660208301520161040e565b6104026107c23660046143a3565b611d08565b6104026107d536600461415e565b6001600160a01b03165f90815260076020526040902054610100900460ff1690565b6107ff611e91565b6040805165ffffffffffff93841681529290911660208301520161040e565b6104515f81565b61043b6108333660046143f6565b611ee3565b61079461084636600461413d565b600a60209081525f92835260408084209091529082529020546001600160801b0380821691600160801b90041682565b61043b610884366004614465565b611ff8565b61089c6108973660046141d3565b612032565b60405161040e919061447e565b6104516108b7366004614204565b612117565b600c5461052f906001600160801b031681565b61043b612560565b61043b6108e53660046144b3565b61257e565b61041c612806565b61043b612864565b6109026128a3565b604080516001600160a01b03909316835265ffffffffffff90911660208301520161040e565b6104517f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b61043b61095d36600461413d565b6128c4565b61043b610970366004614505565b6128fb565b61043b612e37565b6104515f516020614a625f395f51905f5281565b61043b61099f36600461457a565b612e49565b6104026109b236600461415e565b60056020525f908152604090205460ff1681565b61043b6109d43660046140ae565b612f52565b61043b6109e736600461415e565b613018565b6104516130a2565b610a07610a023660046145a2565b613196565b6040805193845260208401929092529082015260600161040e565b610a6a610a3036600461415e565b60076020525f90815260409020805460019091015460ff808316926101008104909116916001600160801b03620100009092048216911684565b60405161040e94939291906145de565b5f6001600160e01b031982166318a4c3c360e11b1480610a9e5750610a9e8261322b565b92915050565b5f610aae8161325f565b610ab6613269565b50565b5f610ac38161325f565b6001600160a01b0382165f90815260076020526040902054610100900460ff16610b105760405163094403b760e41b81526001600160a01b03831660048201526024015b60405180910390fd5b6001600160a01b0382165f8181526007602090815260409182902080546001600160801b038881166201000081810262010000600160901b031985161790945585519390920416808352928201529092917f78de14853e0ae0bbd014f1441c426f26b2b0f9e90ff56a2d70ed4e368674f11291015b60405180910390a250505050565b5f80610ba26020840184614617565b9050610bae8480614617565b905014610bbd57505f92915050565b610bc78380614617565b90505f03610bd757505f92915050565b5f5b610be38480614617565b9050816001600160801b03161015610d2c57610c38610c028580614617565b836001600160801b0316818110610c1b57610c1b614663565b9050602002016020810190610c30919061415e565b600d90613275565b1580610c8357505f610c4a8580614617565b836001600160801b0316818110610c6357610c63614663565b9050602002016020810190610c78919061415e565b6001600160a01b0316145b80610ccf5750610c966020850185614617565b826001600160801b0316818110610caf57610caf614663565b9050602002016020810190610cc49190614465565b6001600160801b0316155b15610cdd57505f9392505050565b610cea6020850185614617565b826001600160801b0316818110610d0357610d03614663565b9050602002016020810190610d189190614465565b610d22908361468b565b9150600101610bd9565b506001600160801b03166127101492915050565b5f516020614aa25f395f51905f528203610d6d5760405163043a0fe160e41b815260040160405180910390fd5b610d778282613296565b5050565b5f610d858161325f565b6001600160a01b038216610dac5760405163d92e233d60e01b815260040160405180910390fd5b600f5460ff1615610dd057604051631b6d030f60e11b815260040160405180910390fd5b600f805460ff19166001179055610df45f516020614aa25f395f51905f52836132be565b506040516001600160a01b038316905f907f6478bc9986cba0e8495ad193362a383cddc9142aa7f9bec227ade7bd95052cb7908290a35050565b6060610e3a600d613324565b905090565b81158015610e5a57506002546001600160a01b038281169116145b15610edb575f5f610e696128a3565b90925090506001600160a01b038216151580610e8b575065ffffffffffff8116155b80610e9e57504265ffffffffffff821610155b15610ec6576040516319ca5ebb60e01b815265ffffffffffff82166004820152602401610b07565b50506001805465ffffffffffff60a01b191690555b610d778282613330565b5f516020614aa25f395f51905f52610efc8161325f565b6001600160a01b038216610f235760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382165f908152600760205260408120546201000090046001600160801b03169003610f745760405163094403b760e41b81526001600160a01b0383166004820152602401610b07565b506001600160a01b03165f908152600760205260409020805461ff001916610100179055565b5f610fa48161325f565b610ab6613363565b5f610fb68161325f565b6001600160a01b038216610fdd5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382165f90815260076020526040902054610100900460ff166110255760405163094403b760e41b81526001600160a01b0383166004820152602401610b07565b506001600160a01b03165f908152600760205260409020805461ff0019169055565b5f610a9e6110536130a2565b61105c84612032565b8051906020012060405161190160f01b8152600281019290925260228201526042902090565b5f61108c8161325f565b611097600d83613275565b6110b45760405163565c062f60e11b815260040160405180910390fd5b6110bf600d836133b5565b506040516001600160a01b038316907f75567811df62a6b68bd5ee394d5808ad7282e19541858be466bc789cad9d4dfb905f90a25050565b5f516020614aa25f395f51905f5261110e8161325f565b6001600160a01b038216158061112c57506001600160a01b03821630145b1561114a5760405163e6c4247b60e01b815260040160405180910390fd5b611155600d83613275565b156111735760405163565c062f60e11b815260040160405180910390fd5b61117e600d836133c9565b506040516001600160a01b038316907ffbd30b5bdd51f5de989170dc23d65aac2de0a6099f5d9d200bc5779d883abcd4905f90a25050565b6111be6133dd565b6111c6613407565b7f44ac9762eec3a11893fefb11d028bb3102560094137c3ed4518712475b2577cc6111f08161325f565b61120060c0840160a08501614465565b611210608085016060860161415e565b6001600160a01b0381165f908152600760205260408082208151608081019092528054829060ff168015611246576112466145ca565b8015611254576112546145ca565b8152815460ff61010082041615156020808401919091526001600160801b036201000090920482166040840152600190930154166060909101528101519091506112b157604051630928045160e21b815260040160405180910390fd5b6060810151435f908152600a602090815260408083206001600160a01b03871684529091529020546001600160801b03918216916112f9918691600160801b9091041661468b565b6001600160801b03161115611321576040516326a753e760e11b815260040160405180910390fd5b61133160c0870160a08801614465565b600854435f908152600960205260409020546001600160801b03600160801b928390048116926113669285929190041661468b565b6001600160801b0316111561138e57604051637d11424760e01b815260040160405180910390fd5b600161139d60208901896146aa565b60018111156113ae576113ae6145ca565b146113cc5760405163af61069360e01b815260040160405180910390fd5b60055f6113df60408a0160208b0161415e565b6001600160a01b0316815260208101919091526040015f205460ff166114345761140f604088016020890161415e565b604051636f8bf18b60e11b81526001600160a01b039091166004820152602401610b07565b61143e8787612117565b5061145c6114526040890160208a0161415e565b8860e0013561342b565b61146c60c0880160a08901614465565b435f908152600a602052604081209061148b60808b0160608c0161415e565b6001600160a01b0316815260208101919091526040015f2080546010906114c3908490600160801b90046001600160801b031661468b565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508660a00160208101906114fa9190614465565b435f9081526009602052604090208054601090611528908490600160801b90046001600160801b031661468b565b92506101000a8154816001600160801b0302191690836001600160801b031602179055507f000000000000000000000000d0580192e98ea6ceb9c7b6191ed2e275609116976001600160a01b03166379cc679088602001602081019061158e919061415e565b61159e60c08b0160a08c01614465565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160801b031660248201526044015f604051808303815f87803b1580156115ea575f5ffd5b505af11580156115fc573d5f5f3e3d5ffd5b5061164e92506116159150506060890160408a0161415e565b61162560a08a0160808b01614465565b6001600160801b031661163e60808b0160608c0161415e565b6001600160a01b03169190613468565b61165e608088016060890161415e565b6001600160a01b03166116776060890160408a0161415e565b6001600160a01b031661169060408a0160208b0161415e565b6001600160a01b03167f3037fcfc598f14760ada165fef340d12541c6c6cd2aba9e93ee0012d689b63766116ca60c08c0160a08d01614465565b6116da60a08d0160808e01614465565b6116e86101008e018e6146c5565b6040516116f8949392919061472f565b60405180910390a45050505050610d776001600455565b5f516020614a625f395f51905f526117268161325f565b6117507f44ac9762eec3a11893fefb11d028bb3102560094137c3ed4518712475b2577cc836134c7565b505050565b5f516020614a625f395f51905f5261176c8161325f565b6117507f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6836134c7565b6001600160a01b0382165f9081526006602052604081206117b79083613275565b9392505050565b5f6117c88161325f565b610d7782613503565b5f6117db8161325f565b610d7782613575565b5f516020614a625f395f51905f526117fb8161325f565b6117507f85e8f2d6819d6b24108062d87ea08f54651bcb8960d98062d3faf96e7873b8b9836134c7565b5f61182f8161325f565b6001600160801b03838116600160801b91841691820281176008556040805191825260208201929092527f59a7de62a3858f345ff23f8eb0f13db6c8fdf6044d557cbe68adc8c3fa4c88d4910160405180910390a1505050565b5f516020614aa25f395f51905f526118a08161325f565b6001600160a01b0382166118c75760405163d92e233d60e01b815260040160405180910390fd5b336118df5f516020614aa25f395f51905f52826134c7565b506118f75f516020614aa25f395f51905f52846132be565b50826001600160a01b0316816001600160a01b03167f6478bc9986cba0e8495ad193362a383cddc9142aa7f9bec227ade7bd95052cb760405160405180910390a3505050565b5f6119478161325f565b610ab66135e4565b5f516020614a825f395f51905f526119668161325f565b6001600160a01b0382165f81815260056020526040808220805460ff19169055517fe285bb51ee9ef78b36fb9eca52aede9c9f4234d2bb72917200f87005edb25a559190a25050565b5f610e3a6002546001600160a01b031690565b5f516020614aa25f395f51905f526119d98161325f565b6001600160a01b0383161580611a2057507f000000000000000000000000d0580192e98ea6ceb9c7b6191ed2e275609116976001600160a01b0316836001600160a01b0316145b80611a3357506001600160a01b0383163b155b15611a5157604051630f58058360e11b815260040160405180910390fd5b60408201516001600160801b03161580611a76575060608201516001600160801b0316155b15611a945760405163162908e360e11b815260040160405180910390fd5b6040805160808101909152825181908015611ab157611ab16145ca565b8152600160208083018290526040868101516001600160801b03908116828601526060808901519091169401939093526001600160a01b0387165f9081526007909152919091208251815491929091839160ff1990911690838015611b1857611b186145ca565b02179055506020820151815460408085015171ffffffffffffffffffffffffffffffffff00199092166101009315159390930262010000600160901b03191692909217620100006001600160801b0392831602178355606090930151600190920180546001600160801b0319169290931691909117909155516001600160a01b038416907f784c8f4dbf0ffedd6e72c76501c545a70f8b203b30a26ce542bf92ba87c248a4905f90a2505050565b5f611bd08161325f565b6001600160a01b038216611bf75760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382165f908152600760205260409020546201000090046001600160801b0316158015611c4c57506001600160a01b0382165f908152600760205260409020600101546001600160801b0316155b15611c755760405163094403b760e41b81526001600160a01b0383166004820152602401610b07565b6001600160a01b0382165f81815260076020526040808220805471ffffffffffffffffffffffffffffffffffff1916815560010180546001600160801b0319169055517f4c910b69fe65a61f7531b9c5042b2329ca7179c77290aa7e2eb3afa3c8511fd39190a25050565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b5f5f611d337f000000000000000000000000d0580192e98ea6ceb9c7b6191ed2e27560911697613621565b90505f611d3f85613621565b90505f5f826001600160801b0316846001600160801b031611611d7657611d66848461476a565b611d7190600a61486c565b611d8b565b611d80838561476a565b611d8b90600a61486c565b9050826001600160801b0316846001600160801b031611611db557611db0818a614894565b611dbf565b611dbf818a6148c1565b91505f886001600160801b0316836001600160801b031611611dea57611de5838a61476a565b611df4565b611df4898461476a565b90505f89611e04612710846148c1565b611e0e9190614894565b90505f886001811115611e2357611e236145ca565b03611e6957836001600160801b03168a6001600160801b031611611e48576001611e5c565b600c546001600160801b0390811690821611155b9650505050505050611e89565b896001600160801b0316846001600160801b031611611e48576001611e5c565b949350505050565b6002545f90600160d01b900465ffffffffffff168015158015611ebc57504265ffffffffffff821610155b611ec7575f5f611edb565b600254600160a01b900465ffffffffffff16815b915091509091565b5f516020614a825f395f51905f52611efa8161325f565b5f5b82811015611ff2575f848483818110611f1757611f17614663565b9050602002016020810190611f2c919061415e565b6001600160a01b031614611fea57600160055f868685818110611f5157611f51614663565b9050602002016020810190611f66919061415e565b6001600160a01b0316815260208101919091526040015f20805460ff1916911515919091179055838382818110611f9f57611f9f614663565b9050602002016020810190611fb4919061415e565b6001600160a01b03167f7409cb8e690bcd1487fd4fd27dad3fa92388d201ba6f953631d6d6b26299f84960405160405180910390a25b600101611efc565b50505050565b5f516020614aa25f395f51905f5261200f8161325f565b50600c80546001600160801b0319166001600160801b0392909216919091179055565b60607fabd63c7ab81f552392db9516aca5d44bfcf14c264d8ad35283366a90f02d311761206260208401846146aa565b612072604085016020860161415e565b612082606086016040870161415e565b612092608087016060880161415e565b6120a260a0880160808901614465565b6120b260c0890160a08a01614465565b6120c260e08a0160c08b01614465565b60e08a01356120d56101008c018c6146c5565b6040516120e39291906148e3565b6040519081900381206121019a9998979695949392916020016148f2565b6040516020818303038152906040529050919050565b5f5f61212284611047565b90505f61213260208501856146aa565b6001811115612143576121436145ca565b036121dc575f6121938261215a60208701876146c5565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061368d92505050565b90506121a5604086016020870161415e565b6001600160a01b0316816001600160a01b0316146121d65760405163b81d58e760e01b815260040160405180910390fd5b506122d8565b60016121eb60208501856146aa565b60018111156121fc576121fc6145ca565b036122bf57630b135d3f60e11b612219604086016020870161415e565b6001600160a01b0316631626ba7e8361223560208801886146c5565b6040518463ffffffff1660e01b815260040161225393929190614964565b602060405180830381865afa15801561226e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122929190614986565b6001600160e01b031916146122ba57604051635d52cbe360e01b815260040160405180910390fd5b6122d8565b6040516306b46e4d60e41b815260040160405180910390fd5b6122e8606085016040860161415e565b6001600160a01b0316612301604086016020870161415e565b6001600160a01b03161461237057612353612322606086016040870161415e565b60065f6123356040890160208a0161415e565b6001600160a01b0316815260208101919091526040015f2090613275565b61237057604051633bef22cb60e01b815260040160405180910390fd5b5f612381606086016040870161415e565b6001600160a01b0316036123a85760405163e6c4247b60e01b815260040160405180910390fd5b60075f6123bb608087016060880161415e565b6001600160a01b0316815260208101919091526040015f2054610100900460ff16612415576123f0608085016060860161415e565b60405163094403b760e41b81526001600160a01b039091166004820152602401610b07565b61242560a0850160808601614465565b6001600160801b03161580612450575061244560c0850160a08601614465565b6001600160801b0316155b1561246e5760405163162908e360e11b815260040160405180910390fd5b5f60075f612482608088016060890161415e565b6001600160a01b0316815260208101919091526040015f205460ff1680156124ac576124ac6145ca565b146124ca57604051630928045160e21b815260040160405180910390fd5b61250a6124dd60a0860160808701614465565b6124ed60c0870160a08801614465565b6124fd608088016060890161415e565b6107c260208901896146aa565b61252757604051630c32239d60e41b815260040160405180910390fd5b61253760e0850160c08601614465565b6001600160801b03164211156117b757604051630819bdcd60e01b815260040160405180910390fd5b5f516020614a625f395f51905f526125778161325f565b505f600855565b6125866133dd565b7f85e8f2d6819d6b24108062d87ea08f54651bcb8960d98062d3faf96e7873b8b96125b08161325f565b5f80806125c06020860186614617565b90506125cc8680614617565b90501415806125e457506125e08580614617565b1590505b156126025760405163427282e960e11b815260040160405180910390fd5b5f5b61260e8680614617565b90508110156126a0576126346126248780614617565b83818110610c1b57610c1b614663565b6126515760405163565c062f60e11b815260040160405180910390fd5b61265e6020870187614617565b8281811061266e5761266e614663565b90506020020160208101906126839190614465565b612696906001600160801b0316856149a1565b9350600101612604565b5082612710146126c35760405163427282e960e11b815260040160405180910390fd5b5f5b6126cf8680614617565b905081101561278a576127106126e86020880188614617565b838181106126f8576126f8614663565b905060200201602081019061270d9190614465565b612720906001600160801b0316896149b4565b61272a91906149cb565b925082156127825761277561273f8780614617565b8381811061274f5761274f614663565b9050602002016020810190612764919061415e565b6001600160a01b038a169085613468565b61277f83836149a1565b91505b6001016126c5565b505f61279682886149de565b905080156127f7576127f76127ab8780614617565b60016127b78a80614617565b6127c29291506149de565b8181106127d1576127d1614663565b90506020020160208101906127e6919061415e565b6001600160a01b038a169083613468565b50505050506117506001600455565b6002545f90600160d01b900465ffffffffffff16801515801561283057504265ffffffffffff8216105b61284b57600154600160d01b900465ffffffffffff1661285e565b600254600160a01b900465ffffffffffff165b91505090565b5f61286d6128a3565b509050336001600160a01b0382161461289b57604051636116401160e11b8152336004820152602401610b07565b610ab66136b5565b6001546001600160a01b03811691600160a01b90910465ffffffffffff1690565b5f516020614aa25f395f51905f5282036128f15760405163043a0fe160e41b815260040160405180910390fd5b610d77828261374b565b6129036133dd565b61290b613407565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a66129358161325f565b61294560c0850160a08601614465565b612955608086016060870161415e565b6001600160a01b0381165f908152600760205260408082208151608081019092528054829060ff16801561298b5761298b6145ca565b8015612999576129996145ca565b8152815460ff61010082041615156020808401919091526001600160801b036201000090920482166040840152600190930154166060909101528101519091506129f657604051630928045160e21b815260040160405180910390fd5b604080820151435f908152600a60209081528382206001600160a01b0387168352905291909120546001600160801b0391821691612a369186911661468b565b6001600160801b03161115612a5e57604051630fbf0bc960e01b815260040160405180910390fd5b612a6e60c0880160a08901614465565b600854435f908152600960205260409020546001600160801b0391821691612a989184911661468b565b6001600160801b03161115612ac057604051630783069f60e21b815260040160405180910390fd5b5f612ace60208a018a6146aa565b6001811115612adf57612adf6145ca565b14612afd5760405163af61069360e01b815260040160405180910390fd5b60055f612b1060408b0160208c0161415e565b6001600160a01b0316815260208101919091526040015f205460ff16612b405761140f6040890160208a0161415e565b612b4a8888612117565b50612b5486610b93565b612b715760405163427282e960e11b815260040160405180910390fd5b612b8e612b8460408a0160208b0161415e565b8960e0013561342b565b612b9e60c0890160a08a01614465565b435f908152600a6020526040812090612bbd60808c0160608d0161415e565b6001600160a01b0316815260208101919091526040015f9081208054909190612bf09084906001600160801b031661468b565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508760a0016020810190612c279190614465565b435f9081526009602052604081208054909190612c4e9084906001600160801b031661468b565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550612cc4886080016020810190612c889190614465565b612c9860808b0160608c0161415e565b612ca860408c0160208d0161415e565b612cb28a80614617565b612cbf60208d018d614617565b613773565b6001600160a01b037f000000000000000000000000d0580192e98ea6ceb9c7b6191ed2e27560911697166340c10f19612d0360608b0160408c0161415e565b612d1360c08c0160a08d01614465565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160801b031660248201526044015f604051808303815f87803b158015612d5f575f5ffd5b505af1158015612d71573d5f5f3e3d5ffd5b50612d86925050506080890160608a0161415e565b6001600160a01b0316612d9f60608a0160408b0161415e565b6001600160a01b0316612db860408b0160208c0161415e565b6001600160a01b03167fb55810952b04eb8aedf037fe0ccec9d04d852f06753eb52085118329252ae9b9612df260a08d0160808e01614465565b612e0260c08e0160a08f01614465565b612e106101008f018f6146c5565b604051612e20949392919061472f565b60405180910390a450505050506117506001600455565b5f612e418161325f565b610ab66138ec565b6001600160a01b038216612e705760405163e6c4247b60e01b815260040160405180910390fd5b8015612ee457335f908152600660205260409020612e8e90836133c9565b612eab5760405163e6c4247b60e01b815260040160405180910390fd5b6040516001600160a01b0383169033907f0d21c62c0c678e2d47ebd0409bf53131e0a431cdfe1f780cc88d4d94f43eb3ff905f90a35050565b335f908152600660205260409020612efc90836133b5565b612f195760405163e6c4247b60e01b815260040160405180910390fd5b6040516001600160a01b0383169033907f6e63003c7a0ad5718ea27734884d2c2221e14cd1b4e6d559b00734dd34c8af9c905f90a35050565b5f612f5c8161325f565b6001600160a01b0382165f90815260076020526040902054610100900460ff16612fa45760405163094403b760e41b81526001600160a01b0383166004820152602401610b07565b6001600160a01b0382165f8181526007602090815260409182902060010180546001600160801b031981166001600160801b03898116918217909355845192909116808352928201529092917f96b246e163c6e0477f8d777b6e5f3492233ef888481c386ef27e527df21d7f6b9101610b85565b5f516020614a825f395f51905f5261302f8161325f565b6001600160a01b0382166130565760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382165f81815260056020526040808220805460ff19166001179055517f7409cb8e690bcd1487fd4fd27dad3fa92388d201ba6f953631d6d6b26299f8499190a25050565b5f7f000000000000000000000000000000000000000000000000000000000000000146036130ef57507f33caa0d423907546c9da3f65b832df8193f9b8f562400707df8b4dfae2124b6690565b610e3a604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f924057aed08648f274927e52243890092250b6a10bb03cb421f423165ac417d8918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b5f5f5f835f036131b957604051633ab3447f60e11b815260040160405180910390fd5b6001600160a01b0385165f908152600b602090815260408083206effffffffffffffffffffffffffffff600889901c16808552925290912054600160ff87161b908082161561321b57604051633ab3447f60e11b815260040160405180910390fd5b91945090925090505b9250925092565b5f6001600160e01b03198216637965db0b60e01b1480610a9e57506301ffc9a760e01b6001600160e01b0319831614610a9e565b610ab681336138f6565b6132735f5f61392f565b565b6001600160a01b0381165f90815260018301602052604081205415156117b7565b816132b457604051631fe1e13d60e11b815260040160405180910390fd5b610d7782826139ee565b5f8261331a575f6132d76002546001600160a01b031690565b6001600160a01b0316146132fe57604051631fe1e13d60e11b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0384161790555b6117b78383613a12565b60605f6117b783613aa1565b6001600160a01b03811633146133595760405163334bd91960e11b815260040160405180910390fd5b61175082826134c7565b61336b613afa565b6003805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b5f6117b7836001600160a01b038416613b1d565b5f6117b7836001600160a01b038416613c07565b60026004540361340057604051633ee5aeb560e01b815260040160405180910390fd5b6002600455565b60035460ff16156132735760405163d93c066560e01b815260040160405180910390fd5b5f5f5f6134388585613196565b6001600160a01b039097165f908152600b6020908152604080832094835293905291909120951790945550505050565b6040516001600160a01b0383811660248301526044820183905261175091859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050613c4c565b5f821580156134e357506002546001600160a01b038381169116145b156134f957600280546001600160a01b03191690555b6117b78383613cb8565b5f61350c612806565b61351542613d21565b61351f91906149f1565b905061352b8282613d57565b60405165ffffffffffff821681526001600160a01b038316907f3377dc44241e779dd06afab5b788a35ca5f3b778836e2990bdb26a2a4b2e5ed69060200160405180910390a25050565b5f61357f82613dd4565b61358842613d21565b61359291906149f1565b905061359e828261392f565b6040805165ffffffffffff8085168252831660208201527ff1038c18cf84a56e432fdbfaf746924b7ea511dfe03a6506a0ceba4888788d9b910160405180910390a15050565b6135ec613407565b6003805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586133983390565b5f5f826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561365f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136839190614a0f565b60ff169392505050565b5f5f5f5f61369b8686613e1b565b9250925092506136ab8282613e61565b5090949350505050565b5f5f6136bf6128a3565b915091506136d48165ffffffffffff16151590565b15806136e857504265ffffffffffff821610155b15613710576040516319ca5ebb60e01b815265ffffffffffff82166004820152602401610b07565b61372b5f6137266002546001600160a01b031690565b6134c7565b506137365f836132be565b5050600180546001600160d01b031916905550565b8161376957604051631fe1e13d60e11b815260040160405180910390fd5b610d778282613f19565b6001600160a01b0386165f90815260076020526040902054610100900460ff166137b057604051630928045160e21b815260040160405180910390fd5b855f805b6001600160801b038116861115613873575f6127108686846001600160801b03168181106137e4576137e4614663565b90506020020160208101906137f99190614465565b613803908d6148c1565b61380d9190614894565b905061385e898989856001600160801b031681811061382e5761382e614663565b9050602002016020810190613843919061415e565b6001600160a01b03871691906001600160801b038516613f3d565b613868818461468b565b9250506001016137b4565b505f61387f828b61476a565b90506001600160801b038116156138e0576138e08888886138a16001826149de565b8181106138b0576138b0614663565b90506020020160208101906138c5919061415e565b6001600160a01b03861691906001600160801b038516613f3d565b50505050505050505050565b6132735f5f613d57565b6139008282611ce0565b610d775760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610b07565b600254600160d01b900465ffffffffffff1680156139b1574265ffffffffffff8216101561398857600254600180546001600160d01b0316600160a01b90920465ffffffffffff16600160d01b029190911790556139b1565b6040517f2b1fa2edafe6f7b9e97c1a9e0c3660e645beb2dcaa2d45bdbf9beaf5472e1ec5905f90a15b50600280546001600160a01b0316600160a01b65ffffffffffff948516026001600160d01b031617600160d01b9290931691909102919091179055565b5f82815260208190526040902060010154613a088161325f565b611ff283836132be565b5f613a1d8383611ce0565b613a9a575f838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055613a523390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610a9e565b505f610a9e565b6060815f01805480602002602001604051908101604052809291908181526020018280548015613aee57602002820191905f5260205f20905b815481526020019060010190808311613ada575b50505050509050919050565b60035460ff1661327357604051638dfc202b60e01b815260040160405180910390fd5b5f8181526001830160205260408120548015613bf7575f613b3f6001836149de565b85549091505f90613b52906001906149de565b9050808214613bb1575f865f018281548110613b7057613b70614663565b905f5260205f200154905080875f018481548110613b9057613b90614663565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080613bc257613bc2614a2f565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610a9e565b5f915050610a9e565b5092915050565b5f818152600183016020526040812054613a9a57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610a9e565b5f5f60205f8451602086015f885af180613c6b576040513d5f823e3d81fd5b50505f513d91508115613c82578060011415613c8f565b6001600160a01b0384163b155b15611ff257604051635274afe760e01b81526001600160a01b0385166004820152602401610b07565b5f613cc38383611ce0565b15613a9a575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610a9e565b5f65ffffffffffff821115613d53576040516306dfcc6560e41b81526030600482015260248101839052604401610b07565b5090565b5f613d606128a3565b6001805465ffffffffffff8616600160a01b026001600160d01b03199091166001600160a01b038816171790559150613da290508165ffffffffffff16151590565b15611750576040517f8886ebfc4259abdbc16601dd8fb5678e54878f47b3c34836cfc51154a9605109905f90a1505050565b5f5f613dde612806565b90508065ffffffffffff168365ffffffffffff1611613e0657613e018382614a43565b6117b7565b6117b765ffffffffffff841662069780613f76565b5f5f5f8351604103613e52576020840151604085015160608601515f1a613e4488828585613f85565b955095509550505050613224565b505081515f9150600290613224565b5f826003811115613e7457613e746145ca565b03613e7d575050565b6001826003811115613e9157613e916145ca565b03613eaf5760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115613ec357613ec36145ca565b03613ee45760405163fce698f760e01b815260048101829052602401610b07565b6003826003811115613ef857613ef86145ca565b03610d77576040516335e2f38360e21b815260048101829052602401610b07565b5f82815260208190526040902060010154613f338161325f565b611ff283836134c7565b6040516001600160a01b038481166024830152838116604483015260648201839052611ff29186918216906323b872dd90608401613495565b5f8282188284100282186117b7565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115613fbe57505f91506003905082614043565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa15801561400f573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b03811661403a57505f925060019150829050614043565b92505f91508190505b9450945094915050565b6001600160e01b031981168114610ab6575f5ffd5b5f60208284031215614072575f5ffd5b81356117b78161404d565b80356001600160801b0381168114614093575f5ffd5b919050565b80356001600160a01b0381168114614093575f5ffd5b5f5f604083850312156140bf575f5ffd5b6140c88361407d565b91506140d660208401614098565b90509250929050565b5f604082840312156140ef575f5ffd5b50919050565b5f60208284031215614105575f5ffd5b81356001600160401b0381111561411a575f5ffd5b611e89848285016140df565b5f60208284031215614136575f5ffd5b5035919050565b5f5f6040838503121561414e575f5ffd5b823591506140d660208401614098565b5f6020828403121561416e575f5ffd5b6117b782614098565b602080825282518282018190525f918401906040840190835b818110156141b75783516001600160a01b0316835260209384019390920191600101614190565b509095945050505050565b5f61012082840312156140ef575f5ffd5b5f602082840312156141e3575f5ffd5b81356001600160401b038111156141f8575f5ffd5b611e89848285016141c2565b5f5f60408385031215614215575f5ffd5b82356001600160401b0381111561422a575f5ffd5b614236858286016141c2565b92505060208301356001600160401b03811115614251575f5ffd5b61425d858286016140df565b9150509250929050565b5f5f60408385031215614278575f5ffd5b6140c883614098565b5f60208284031215614291575f5ffd5b813565ffffffffffff811681146117b7575f5ffd5b5f5f604083850312156142b7575f5ffd5b6142c08361407d565b91506140d66020840161407d565b803560018110614093575f5ffd5b80358015158114614093575f5ffd5b5f5f82840360a08112156142fd575f5ffd5b61430684614098565b92506080601f1982011215614319575f5ffd5b50604051608081018181106001600160401b038211171561434857634e487b7160e01b5f52604160045260245ffd5b604052614357602085016142ce565b8152614365604085016142dc565b60208201526143766060850161407d565b60408201526143876080850161407d565b6060820152809150509250929050565b60028110610ab6575f5ffd5b5f5f5f5f608085870312156143b6575f5ffd5b6143bf8561407d565b93506143cd6020860161407d565b92506143db60408601614098565b915060608501356143eb81614397565b939692955090935050565b5f5f60208385031215614407575f5ffd5b82356001600160401b0381111561441c575f5ffd5b8301601f8101851361442c575f5ffd5b80356001600160401b03811115614441575f5ffd5b8560208260051b8401011115614455575f5ffd5b6020919091019590945092505050565b5f60208284031215614475575f5ffd5b6117b78261407d565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f5f606084860312156144c5575f5ffd5b6144ce84614098565b92506020840135915060408401356001600160401b038111156144ef575f5ffd5b6144fb868287016140df565b9150509250925092565b5f5f5f60608486031215614517575f5ffd5b83356001600160401b0381111561452c575f5ffd5b614538868287016141c2565b93505060208401356001600160401b03811115614553575f5ffd5b61455f868287016140df565b92505060408401356001600160401b038111156144ef575f5ffd5b5f5f6040838503121561458b575f5ffd5b61459483614098565b91506140d6602084016142dc565b5f5f604083850312156145b3575f5ffd5b6145bc83614098565b946020939093013593505050565b634e487b7160e01b5f52602160045260245ffd5b60808101600186106145f2576145f26145ca565b94815292151560208401526001600160801b0391821660408401521660609091015290565b5f5f8335601e1984360301811261462c575f5ffd5b8301803591506001600160401b03821115614645575f5ffd5b6020019150600581901b360382131561465c575f5ffd5b9250929050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b6001600160801b038181168382160190811115610a9e57610a9e614677565b5f602082840312156146ba575f5ffd5b81356117b781614397565b5f5f8335601e198436030181126146da575f5ffd5b8301803591506001600160401b038211156146f3575f5ffd5b60200191503681900382131561465c575f5ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b6001600160801b03851681526001600160801b0384166020820152606060408201525f614760606083018486614707565b9695505050505050565b6001600160801b038281168282160390811115610a9e57610a9e614677565b6001815b60018411156147c4578085048111156147a8576147a8614677565b60018416156147b657908102905b60019390931c92800261478d565b935093915050565b5f826147da57506001610a9e565b816147e657505f610a9e565b81600181146147fc576002811461480657614822565b6001915050610a9e565b60ff84111561481757614817614677565b50506001821b610a9e565b5060208310610133831016604e8410600b8410161715614845575081810a610a9e565b6148515f198484614789565b805f190482111561486457614864614677565b029392505050565b5f6117b76001600160801b038416836147cc565b634e487b7160e01b5f52601260045260245ffd5b5f6001600160801b038316806148ac576148ac614880565b806001600160801b0384160491505092915050565b6001600160801b038181168382160290811690818114613c0057613c00614677565b818382375f9101908152919050565b8a8152610140810160028b1061490a5761490a6145ca565b602082019a909a526001600160a01b03988916604082015296881660608801529490961660808601526001600160801b0392831660a086015290821660c08501521660e08301526101008201929092526101200152919050565b838152604060208201525f61497d604083018486614707565b95945050505050565b5f60208284031215614996575f5ffd5b81516117b78161404d565b80820180821115610a9e57610a9e614677565b8082028115828204841417610a9e57610a9e614677565b5f826149d9576149d9614880565b500490565b81810381811115610a9e57610a9e614677565b65ffffffffffff8181168382160190811115610a9e57610a9e614677565b5f60208284031215614a1f575f5ffd5b815160ff811681146117b7575f5ffd5b634e487b7160e01b5f52603160045260245ffd5b65ffffffffffff8281168282160390811115610a9e57610a9e61467756fe3c63e605be3290ab6b04cfc46c6e1516e626d43236b034f09d7ede1d017beb0c8619cecd8b9e095ab43867f5b69d492180450fe862e6b50bfbfb24b75dd84c8a5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5a26469706673582212206d80c2aa71d2d6989f6cebd49d64427f2eee5c0a917ea2cd6a05c86c87b6a66064736f6c634300081c0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"cancun","libraries":{},"optimizer":{"enabled":true,"runs":200},"outputSelection":{"*":{"":["*"],"*":["*"]}}},"optimization_runs":200,"sourcify_repo_url":null,"decoded_constructor_args":[["0xd0580192E98eA6CEB9c7b6191Ed2E27560911697",{"internalType":"address","name":"_trUSDAddress","type":"address"}],[["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48","0xdAC17F958D2ee523a2206206994597C13D831ec7"],{"internalType":"address[]","name":"_allowedTokens","type":"address[]"}],[[["0","true","50000000000000000000","5000000000000000000"],["0","true","50000000000000000000","5000000000000000000"]],{"components":[{"internalType":"enum ToriMinting.TokenType","name":"tokenType","type":"uint8"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint128","name":"maxMintPerBlock","type":"uint128"},{"internalType":"uint128","name":"maxRedeemPerBlock","type":"uint128"}],"internalType":"struct ToriMinting.TokenConfig[]","name":"_tokenConfigs","type":"tuple[]"}],["50000000000000000000",{"internalType":"uint128","name":"_globalMaxMintPerBlock","type":"uint128"}],["5000000000000000000",{"internalType":"uint128","name":"_globalMaxRedeemPerBlock","type":"uint128"}],["0x0C6Bbfd2d5666d44bf28580eDEec0263692C8316",{"internalType":"address","name":"_admin","type":"address"}]],"compiler_version":"v0.8.28+commit.7893614a","is_verified_via_verifier_alliance":false,"verified_at":"2026-06-11T13:05:24.820247Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x60e060405234801561000f575f5ffd5b5060405161531538038061531583398101604081905261002e916106ad565b62015180816001600160a01b03811661006057604051636116401160e11b81525f600482015260240160405180910390fd5b600180546001600160d01b0316600160d01b65ffffffffffff8516021790556100895f8261040e565b50506001600455506001600160a01b0381166100b85760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0386166100df5760405163d92e233d60e01b815260040160405180910390fd5b83518551146101015760405163162908e360e11b815260040160405180910390fd5b84515f036101225760405163162908e360e11b815260040160405180910390fd5b6001600160a01b0386166080526001600160801b03828116600160801b02908416176008555f5b855181101561035e575f868281518110610165576101656107b0565b602002602001015190505f868381518110610182576101826107b0565b602002602001015190505f6001600160a01b0316826001600160a01b031614806101bd5750886001600160a01b0316826001600160a01b0316145b806101d057506001600160a01b0382163b155b156101ee57604051630f58058360e11b815260040160405180910390fd5b60408101516001600160801b03161580610213575060608101516001600160801b0316155b156102315760405163162908e360e11b815260040160405180910390fd5b604080516080810190915281518190801561024e5761024e6107c4565b8152600160208083018290526040858101516001600160801b03908116828601526060808801519091169401939093526001600160a01b0386165f9081526007909152919091208251815491929091839160ff19909116908380156102b5576102b56107c4565b021790555060208201518154604080850151610100600160901b03199092166101009315159390930262010000600160901b03191692909217620100006001600160801b0392831602178355606090930151600190920180546001600160801b0319169290931691909117909155516001600160a01b038316907f784c8f4dbf0ffedd6e72c76501c545a70f8b203b30a26ce542bf92ba87c248a4905f90a25050600101610149565b504660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f924057aed08648f274927e52243890092250b6a10bb03cb421f423165ac417d8828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060830152608082019490945230818401528151808203909301835260c0019052805191012060c052506107d8945050505050565b5f8261046a575f6104276002546001600160a01b031690565b6001600160a01b03161461044e57604051631fe1e13d60e11b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0384161790555b610474838361047d565b90505b92915050565b5f828152602081815260408083206001600160a01b038516845290915281205460ff1661051d575f838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556104d53390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610477565b505f610477565b80516001600160a01b038116811461053a575f5ffd5b919050565b634e487b7160e01b5f52604160045260245ffd5b604051608081016001600160401b03811182821017156105755761057561053f565b60405290565b604051601f8201601f191681016001600160401b03811182821017156105a3576105a361053f565b604052919050565b5f6001600160401b038211156105c3576105c361053f565b5060051b60200190565b80516001600160801b038116811461053a575f5ffd5b5f82601f8301126105f2575f5ffd5b8151610605610600826105ab565b61057b565b8082825260208201915060208360071b860101925085831115610626575f5ffd5b602085015b838110156106a35760808188031215610642575f5ffd5b61064a610553565b815160018110610658575f5ffd5b81526020820151801515811461066c575f5ffd5b602082015261067d604083016105cd565b604082015261068e606083016105cd565b6060820152835260209092019160800161062b565b5095945050505050565b5f5f5f5f5f5f60c087890312156106c2575f5ffd5b6106cb87610524565b60208801519096506001600160401b038111156106e6575f5ffd5b8701601f810189136106f6575f5ffd5b8051610704610600826105ab565b8082825260208201915060208360051b85010192508b831115610725575f5ffd5b6020840193505b8284101561074e5761073d84610524565b82526020938401939091019061072c565b60408b0151909850925050506001600160401b0381111561076d575f5ffd5b61077989828a016105e3565b945050610788606088016105cd565b9250610796608088016105cd565b91506107a460a08801610524565b90509295509295509295565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b60805160a05160c051614af761081e5f395f6130cd01525f6130a501525f81816106eb0152818161154e015281816119ec01528181611d0f0152612cce0152614af75ff3fe608060405234801561000f575f5ffd5b50600436106103eb575f3560e01c806389b66fe01161020b578063c5ff38bd1161011f578063d602b9fd116100b4578063e077020211610084578063e0770202146109c6578063e43252d7146109d9578063ed24911d146109ec578063f4ee2a8b146109f4578063fe136c4e14610a22575f5ffd5b8063d602b9fd14610975578063d6fd31751461097d578063d7d0a09414610991578063d936547e146109a4575f5ffd5b8063cf6eefb7116100ef578063cf6eefb7146108fa578063d539139314610928578063d547741f1461094f578063d58c2dee14610962575f5ffd5b8063c5ff38bd146108cf578063c7f2f0bf146108d7578063cc8463c8146108ea578063cefc1429146108f2575f5ffd5b80639be918e6116101a0578063a693635e11610170578063a693635e14610838578063af4eca3514610876578063afa774b314610889578063b3be507b146108a9578063be4088ee146108bc575f5ffd5b80639be918e6146107c7578063a1eda53c146107f7578063a217fddf1461081e578063a617713914610825575f5ffd5b806390469a9d116101db57806390469a9d1461073b57806391d148541461074e57806392408dc71461076157806392a3c04f146107b4575f5ffd5b806389b66fe0146106e65780638ab1d6811461070d5780638da5cb5b146107205780638dfd87e214610728575f5ffd5b80634ba87af9116103025780635c975abb1161029757806372c117981161026757806372c117981461066c5780637ac5f2d81461067f5780637fa46ab4146106925780638456cb59146106b957806384ef8ffc146106c1575f5ffd5b80635c975abb14610628578063634e93da14610633578063649a5ec7146106465780637274c25c14610659575f5ffd5b8063532c3f82116102d2578063532c3f82146105db57806354f1e126146105ee578063570618e114610601578063591c354414610615575f5ffd5b80634ba87af9146105885780634be7a64b1461059b5780634d9f73f2146105ae5780634e128fe0146105c1575f5ffd5b80632f2ff15d116103835780633bb935b4116103535780633bb935b41461051c5780633f1fda50146105475780633f4ba83a1461055a578063435a3ca914610562578063488e966b14610575575f5ffd5b80632f2ff15d146104ce57806331998fac146104e1578063334cfda4146104f457806336568abe14610509575f5ffd5b806312a4a10e116103be57806312a4a10e1461045f5780631f6c7da214610472578063248a9ca3146104855780632e718ab7146104a7575f5ffd5b806301ffc9a7146103ef578063022d63fb146104175780630aa6220b146104335780630d3cf6fc1461043d575b5f5ffd5b6104026103fd366004614062565b610a7a565b60405190151581526020015b60405180910390f35b620697805b60405165ffffffffffff909116815260200161040e565b61043b610aa4565b005b6104515f516020614aa25f395f51905f5281565b60405190815260200161040e565b61043b61046d3660046140ae565b610ab9565b6104026104803660046140f5565b610b93565b610451610493366004614126565b5f9081526020819052604090206001015490565b6104517f85e8f2d6819d6b24108062d87ea08f54651bcb8960d98062d3faf96e7873b8b981565b61043b6104dc36600461413d565b610d40565b61043b6104ef36600461415e565b610d7b565b6104fc610e2e565b60405161040e9190614177565b61043b61051736600461413d565b610e3f565b60085461052f906001600160801b031681565b6040516001600160801b03909116815260200161040e565b61043b61055536600461415e565b610ee5565b61043b610f9a565b61043b61057036600461415e565b610fac565b6104516105833660046141d3565b611047565b61043b61059636600461415e565b611082565b61043b6105a936600461415e565b6110f7565b61043b6105bc366004614204565b6111b6565b60085461052f90600160801b90046001600160801b031681565b61043b6105e936600461415e565b61170f565b61043b6105fc36600461415e565b611755565b6104515f516020614a825f395f51905f5281565b610402610623366004614267565b611796565b60035460ff16610402565b61043b61064136600461415e565b6117be565b61043b610654366004614281565b6117d1565b61043b61066736600461415e565b6117e4565b61043b61067a3660046142a6565b611825565b61043b61068d36600461415e565b611889565b6104517f44ac9762eec3a11893fefb11d028bb3102560094137c3ed4518712475b2577cc81565b61043b61193d565b6002546001600160a01b03165b6040516001600160a01b03909116815260200161040e565b6106ce7f000000000000000000000000000000000000000000000000000000000000000081565b61043b61071b36600461415e565b61194f565b6106ce6119af565b61043b6107363660046142eb565b6119c2565b61043b61074936600461415e565b611bc6565b61040261075c36600461413d565b611ce0565b61079461076f366004614126565b60096020525f90815260409020546001600160801b0380821691600160801b90041682565b604080516001600160801b0393841681529290911660208301520161040e565b6104026107c23660046143a3565b611d08565b6104026107d536600461415e565b6001600160a01b03165f90815260076020526040902054610100900460ff1690565b6107ff611e91565b6040805165ffffffffffff93841681529290911660208301520161040e565b6104515f81565b61043b6108333660046143f6565b611ee3565b61079461084636600461413d565b600a60209081525f92835260408084209091529082529020546001600160801b0380821691600160801b90041682565b61043b610884366004614465565b611ff8565b61089c6108973660046141d3565b612032565b60405161040e919061447e565b6104516108b7366004614204565b612117565b600c5461052f906001600160801b031681565b61043b612560565b61043b6108e53660046144b3565b61257e565b61041c612806565b61043b612864565b6109026128a3565b604080516001600160a01b03909316835265ffffffffffff90911660208301520161040e565b6104517f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b61043b61095d36600461413d565b6128c4565b61043b610970366004614505565b6128fb565b61043b612e37565b6104515f516020614a625f395f51905f5281565b61043b61099f36600461457a565b612e49565b6104026109b236600461415e565b60056020525f908152604090205460ff1681565b61043b6109d43660046140ae565b612f52565b61043b6109e736600461415e565b613018565b6104516130a2565b610a07610a023660046145a2565b613196565b6040805193845260208401929092529082015260600161040e565b610a6a610a3036600461415e565b60076020525f90815260409020805460019091015460ff808316926101008104909116916001600160801b03620100009092048216911684565b60405161040e94939291906145de565b5f6001600160e01b031982166318a4c3c360e11b1480610a9e5750610a9e8261322b565b92915050565b5f610aae8161325f565b610ab6613269565b50565b5f610ac38161325f565b6001600160a01b0382165f90815260076020526040902054610100900460ff16610b105760405163094403b760e41b81526001600160a01b03831660048201526024015b60405180910390fd5b6001600160a01b0382165f8181526007602090815260409182902080546001600160801b038881166201000081810262010000600160901b031985161790945585519390920416808352928201529092917f78de14853e0ae0bbd014f1441c426f26b2b0f9e90ff56a2d70ed4e368674f11291015b60405180910390a250505050565b5f80610ba26020840184614617565b9050610bae8480614617565b905014610bbd57505f92915050565b610bc78380614617565b90505f03610bd757505f92915050565b5f5b610be38480614617565b9050816001600160801b03161015610d2c57610c38610c028580614617565b836001600160801b0316818110610c1b57610c1b614663565b9050602002016020810190610c30919061415e565b600d90613275565b1580610c8357505f610c4a8580614617565b836001600160801b0316818110610c6357610c63614663565b9050602002016020810190610c78919061415e565b6001600160a01b0316145b80610ccf5750610c966020850185614617565b826001600160801b0316818110610caf57610caf614663565b9050602002016020810190610cc49190614465565b6001600160801b0316155b15610cdd57505f9392505050565b610cea6020850185614617565b826001600160801b0316818110610d0357610d03614663565b9050602002016020810190610d189190614465565b610d22908361468b565b9150600101610bd9565b506001600160801b03166127101492915050565b5f516020614aa25f395f51905f528203610d6d5760405163043a0fe160e41b815260040160405180910390fd5b610d778282613296565b5050565b5f610d858161325f565b6001600160a01b038216610dac5760405163d92e233d60e01b815260040160405180910390fd5b600f5460ff1615610dd057604051631b6d030f60e11b815260040160405180910390fd5b600f805460ff19166001179055610df45f516020614aa25f395f51905f52836132be565b506040516001600160a01b038316905f907f6478bc9986cba0e8495ad193362a383cddc9142aa7f9bec227ade7bd95052cb7908290a35050565b6060610e3a600d613324565b905090565b81158015610e5a57506002546001600160a01b038281169116145b15610edb575f5f610e696128a3565b90925090506001600160a01b038216151580610e8b575065ffffffffffff8116155b80610e9e57504265ffffffffffff821610155b15610ec6576040516319ca5ebb60e01b815265ffffffffffff82166004820152602401610b07565b50506001805465ffffffffffff60a01b191690555b610d778282613330565b5f516020614aa25f395f51905f52610efc8161325f565b6001600160a01b038216610f235760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382165f908152600760205260408120546201000090046001600160801b03169003610f745760405163094403b760e41b81526001600160a01b0383166004820152602401610b07565b506001600160a01b03165f908152600760205260409020805461ff001916610100179055565b5f610fa48161325f565b610ab6613363565b5f610fb68161325f565b6001600160a01b038216610fdd5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382165f90815260076020526040902054610100900460ff166110255760405163094403b760e41b81526001600160a01b0383166004820152602401610b07565b506001600160a01b03165f908152600760205260409020805461ff0019169055565b5f610a9e6110536130a2565b61105c84612032565b8051906020012060405161190160f01b8152600281019290925260228201526042902090565b5f61108c8161325f565b611097600d83613275565b6110b45760405163565c062f60e11b815260040160405180910390fd5b6110bf600d836133b5565b506040516001600160a01b038316907f75567811df62a6b68bd5ee394d5808ad7282e19541858be466bc789cad9d4dfb905f90a25050565b5f516020614aa25f395f51905f5261110e8161325f565b6001600160a01b038216158061112c57506001600160a01b03821630145b1561114a5760405163e6c4247b60e01b815260040160405180910390fd5b611155600d83613275565b156111735760405163565c062f60e11b815260040160405180910390fd5b61117e600d836133c9565b506040516001600160a01b038316907ffbd30b5bdd51f5de989170dc23d65aac2de0a6099f5d9d200bc5779d883abcd4905f90a25050565b6111be6133dd565b6111c6613407565b7f44ac9762eec3a11893fefb11d028bb3102560094137c3ed4518712475b2577cc6111f08161325f565b61120060c0840160a08501614465565b611210608085016060860161415e565b6001600160a01b0381165f908152600760205260408082208151608081019092528054829060ff168015611246576112466145ca565b8015611254576112546145ca565b8152815460ff61010082041615156020808401919091526001600160801b036201000090920482166040840152600190930154166060909101528101519091506112b157604051630928045160e21b815260040160405180910390fd5b6060810151435f908152600a602090815260408083206001600160a01b03871684529091529020546001600160801b03918216916112f9918691600160801b9091041661468b565b6001600160801b03161115611321576040516326a753e760e11b815260040160405180910390fd5b61133160c0870160a08801614465565b600854435f908152600960205260409020546001600160801b03600160801b928390048116926113669285929190041661468b565b6001600160801b0316111561138e57604051637d11424760e01b815260040160405180910390fd5b600161139d60208901896146aa565b60018111156113ae576113ae6145ca565b146113cc5760405163af61069360e01b815260040160405180910390fd5b60055f6113df60408a0160208b0161415e565b6001600160a01b0316815260208101919091526040015f205460ff166114345761140f604088016020890161415e565b604051636f8bf18b60e11b81526001600160a01b039091166004820152602401610b07565b61143e8787612117565b5061145c6114526040890160208a0161415e565b8860e0013561342b565b61146c60c0880160a08901614465565b435f908152600a602052604081209061148b60808b0160608c0161415e565b6001600160a01b0316815260208101919091526040015f2080546010906114c3908490600160801b90046001600160801b031661468b565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508660a00160208101906114fa9190614465565b435f9081526009602052604090208054601090611528908490600160801b90046001600160801b031661468b565b92506101000a8154816001600160801b0302191690836001600160801b031602179055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166379cc679088602001602081019061158e919061415e565b61159e60c08b0160a08c01614465565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160801b031660248201526044015f604051808303815f87803b1580156115ea575f5ffd5b505af11580156115fc573d5f5f3e3d5ffd5b5061164e92506116159150506060890160408a0161415e565b61162560a08a0160808b01614465565b6001600160801b031661163e60808b0160608c0161415e565b6001600160a01b03169190613468565b61165e608088016060890161415e565b6001600160a01b03166116776060890160408a0161415e565b6001600160a01b031661169060408a0160208b0161415e565b6001600160a01b03167f3037fcfc598f14760ada165fef340d12541c6c6cd2aba9e93ee0012d689b63766116ca60c08c0160a08d01614465565b6116da60a08d0160808e01614465565b6116e86101008e018e6146c5565b6040516116f8949392919061472f565b60405180910390a45050505050610d776001600455565b5f516020614a625f395f51905f526117268161325f565b6117507f44ac9762eec3a11893fefb11d028bb3102560094137c3ed4518712475b2577cc836134c7565b505050565b5f516020614a625f395f51905f5261176c8161325f565b6117507f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6836134c7565b6001600160a01b0382165f9081526006602052604081206117b79083613275565b9392505050565b5f6117c88161325f565b610d7782613503565b5f6117db8161325f565b610d7782613575565b5f516020614a625f395f51905f526117fb8161325f565b6117507f85e8f2d6819d6b24108062d87ea08f54651bcb8960d98062d3faf96e7873b8b9836134c7565b5f61182f8161325f565b6001600160801b03838116600160801b91841691820281176008556040805191825260208201929092527f59a7de62a3858f345ff23f8eb0f13db6c8fdf6044d557cbe68adc8c3fa4c88d4910160405180910390a1505050565b5f516020614aa25f395f51905f526118a08161325f565b6001600160a01b0382166118c75760405163d92e233d60e01b815260040160405180910390fd5b336118df5f516020614aa25f395f51905f52826134c7565b506118f75f516020614aa25f395f51905f52846132be565b50826001600160a01b0316816001600160a01b03167f6478bc9986cba0e8495ad193362a383cddc9142aa7f9bec227ade7bd95052cb760405160405180910390a3505050565b5f6119478161325f565b610ab66135e4565b5f516020614a825f395f51905f526119668161325f565b6001600160a01b0382165f81815260056020526040808220805460ff19169055517fe285bb51ee9ef78b36fb9eca52aede9c9f4234d2bb72917200f87005edb25a559190a25050565b5f610e3a6002546001600160a01b031690565b5f516020614aa25f395f51905f526119d98161325f565b6001600160a01b0383161580611a2057507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316145b80611a3357506001600160a01b0383163b155b15611a5157604051630f58058360e11b815260040160405180910390fd5b60408201516001600160801b03161580611a76575060608201516001600160801b0316155b15611a945760405163162908e360e11b815260040160405180910390fd5b6040805160808101909152825181908015611ab157611ab16145ca565b8152600160208083018290526040868101516001600160801b03908116828601526060808901519091169401939093526001600160a01b0387165f9081526007909152919091208251815491929091839160ff1990911690838015611b1857611b186145ca565b02179055506020820151815460408085015171ffffffffffffffffffffffffffffffffff00199092166101009315159390930262010000600160901b03191692909217620100006001600160801b0392831602178355606090930151600190920180546001600160801b0319169290931691909117909155516001600160a01b038416907f784c8f4dbf0ffedd6e72c76501c545a70f8b203b30a26ce542bf92ba87c248a4905f90a2505050565b5f611bd08161325f565b6001600160a01b038216611bf75760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382165f908152600760205260409020546201000090046001600160801b0316158015611c4c57506001600160a01b0382165f908152600760205260409020600101546001600160801b0316155b15611c755760405163094403b760e41b81526001600160a01b0383166004820152602401610b07565b6001600160a01b0382165f81815260076020526040808220805471ffffffffffffffffffffffffffffffffffff1916815560010180546001600160801b0319169055517f4c910b69fe65a61f7531b9c5042b2329ca7179c77290aa7e2eb3afa3c8511fd39190a25050565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b5f5f611d337f0000000000000000000000000000000000000000000000000000000000000000613621565b90505f611d3f85613621565b90505f5f826001600160801b0316846001600160801b031611611d7657611d66848461476a565b611d7190600a61486c565b611d8b565b611d80838561476a565b611d8b90600a61486c565b9050826001600160801b0316846001600160801b031611611db557611db0818a614894565b611dbf565b611dbf818a6148c1565b91505f886001600160801b0316836001600160801b031611611dea57611de5838a61476a565b611df4565b611df4898461476a565b90505f89611e04612710846148c1565b611e0e9190614894565b90505f886001811115611e2357611e236145ca565b03611e6957836001600160801b03168a6001600160801b031611611e48576001611e5c565b600c546001600160801b0390811690821611155b9650505050505050611e89565b896001600160801b0316846001600160801b031611611e48576001611e5c565b949350505050565b6002545f90600160d01b900465ffffffffffff168015158015611ebc57504265ffffffffffff821610155b611ec7575f5f611edb565b600254600160a01b900465ffffffffffff16815b915091509091565b5f516020614a825f395f51905f52611efa8161325f565b5f5b82811015611ff2575f848483818110611f1757611f17614663565b9050602002016020810190611f2c919061415e565b6001600160a01b031614611fea57600160055f868685818110611f5157611f51614663565b9050602002016020810190611f66919061415e565b6001600160a01b0316815260208101919091526040015f20805460ff1916911515919091179055838382818110611f9f57611f9f614663565b9050602002016020810190611fb4919061415e565b6001600160a01b03167f7409cb8e690bcd1487fd4fd27dad3fa92388d201ba6f953631d6d6b26299f84960405160405180910390a25b600101611efc565b50505050565b5f516020614aa25f395f51905f5261200f8161325f565b50600c80546001600160801b0319166001600160801b0392909216919091179055565b60607fabd63c7ab81f552392db9516aca5d44bfcf14c264d8ad35283366a90f02d311761206260208401846146aa565b612072604085016020860161415e565b612082606086016040870161415e565b612092608087016060880161415e565b6120a260a0880160808901614465565b6120b260c0890160a08a01614465565b6120c260e08a0160c08b01614465565b60e08a01356120d56101008c018c6146c5565b6040516120e39291906148e3565b6040519081900381206121019a9998979695949392916020016148f2565b6040516020818303038152906040529050919050565b5f5f61212284611047565b90505f61213260208501856146aa565b6001811115612143576121436145ca565b036121dc575f6121938261215a60208701876146c5565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061368d92505050565b90506121a5604086016020870161415e565b6001600160a01b0316816001600160a01b0316146121d65760405163b81d58e760e01b815260040160405180910390fd5b506122d8565b60016121eb60208501856146aa565b60018111156121fc576121fc6145ca565b036122bf57630b135d3f60e11b612219604086016020870161415e565b6001600160a01b0316631626ba7e8361223560208801886146c5565b6040518463ffffffff1660e01b815260040161225393929190614964565b602060405180830381865afa15801561226e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122929190614986565b6001600160e01b031916146122ba57604051635d52cbe360e01b815260040160405180910390fd5b6122d8565b6040516306b46e4d60e41b815260040160405180910390fd5b6122e8606085016040860161415e565b6001600160a01b0316612301604086016020870161415e565b6001600160a01b03161461237057612353612322606086016040870161415e565b60065f6123356040890160208a0161415e565b6001600160a01b0316815260208101919091526040015f2090613275565b61237057604051633bef22cb60e01b815260040160405180910390fd5b5f612381606086016040870161415e565b6001600160a01b0316036123a85760405163e6c4247b60e01b815260040160405180910390fd5b60075f6123bb608087016060880161415e565b6001600160a01b0316815260208101919091526040015f2054610100900460ff16612415576123f0608085016060860161415e565b60405163094403b760e41b81526001600160a01b039091166004820152602401610b07565b61242560a0850160808601614465565b6001600160801b03161580612450575061244560c0850160a08601614465565b6001600160801b0316155b1561246e5760405163162908e360e11b815260040160405180910390fd5b5f60075f612482608088016060890161415e565b6001600160a01b0316815260208101919091526040015f205460ff1680156124ac576124ac6145ca565b146124ca57604051630928045160e21b815260040160405180910390fd5b61250a6124dd60a0860160808701614465565b6124ed60c0870160a08801614465565b6124fd608088016060890161415e565b6107c260208901896146aa565b61252757604051630c32239d60e41b815260040160405180910390fd5b61253760e0850160c08601614465565b6001600160801b03164211156117b757604051630819bdcd60e01b815260040160405180910390fd5b5f516020614a625f395f51905f526125778161325f565b505f600855565b6125866133dd565b7f85e8f2d6819d6b24108062d87ea08f54651bcb8960d98062d3faf96e7873b8b96125b08161325f565b5f80806125c06020860186614617565b90506125cc8680614617565b90501415806125e457506125e08580614617565b1590505b156126025760405163427282e960e11b815260040160405180910390fd5b5f5b61260e8680614617565b90508110156126a0576126346126248780614617565b83818110610c1b57610c1b614663565b6126515760405163565c062f60e11b815260040160405180910390fd5b61265e6020870187614617565b8281811061266e5761266e614663565b90506020020160208101906126839190614465565b612696906001600160801b0316856149a1565b9350600101612604565b5082612710146126c35760405163427282e960e11b815260040160405180910390fd5b5f5b6126cf8680614617565b905081101561278a576127106126e86020880188614617565b838181106126f8576126f8614663565b905060200201602081019061270d9190614465565b612720906001600160801b0316896149b4565b61272a91906149cb565b925082156127825761277561273f8780614617565b8381811061274f5761274f614663565b9050602002016020810190612764919061415e565b6001600160a01b038a169085613468565b61277f83836149a1565b91505b6001016126c5565b505f61279682886149de565b905080156127f7576127f76127ab8780614617565b60016127b78a80614617565b6127c29291506149de565b8181106127d1576127d1614663565b90506020020160208101906127e6919061415e565b6001600160a01b038a169083613468565b50505050506117506001600455565b6002545f90600160d01b900465ffffffffffff16801515801561283057504265ffffffffffff8216105b61284b57600154600160d01b900465ffffffffffff1661285e565b600254600160a01b900465ffffffffffff165b91505090565b5f61286d6128a3565b509050336001600160a01b0382161461289b57604051636116401160e11b8152336004820152602401610b07565b610ab66136b5565b6001546001600160a01b03811691600160a01b90910465ffffffffffff1690565b5f516020614aa25f395f51905f5282036128f15760405163043a0fe160e41b815260040160405180910390fd5b610d77828261374b565b6129036133dd565b61290b613407565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a66129358161325f565b61294560c0850160a08601614465565b612955608086016060870161415e565b6001600160a01b0381165f908152600760205260408082208151608081019092528054829060ff16801561298b5761298b6145ca565b8015612999576129996145ca565b8152815460ff61010082041615156020808401919091526001600160801b036201000090920482166040840152600190930154166060909101528101519091506129f657604051630928045160e21b815260040160405180910390fd5b604080820151435f908152600a60209081528382206001600160a01b0387168352905291909120546001600160801b0391821691612a369186911661468b565b6001600160801b03161115612a5e57604051630fbf0bc960e01b815260040160405180910390fd5b612a6e60c0880160a08901614465565b600854435f908152600960205260409020546001600160801b0391821691612a989184911661468b565b6001600160801b03161115612ac057604051630783069f60e21b815260040160405180910390fd5b5f612ace60208a018a6146aa565b6001811115612adf57612adf6145ca565b14612afd5760405163af61069360e01b815260040160405180910390fd5b60055f612b1060408b0160208c0161415e565b6001600160a01b0316815260208101919091526040015f205460ff16612b405761140f6040890160208a0161415e565b612b4a8888612117565b50612b5486610b93565b612b715760405163427282e960e11b815260040160405180910390fd5b612b8e612b8460408a0160208b0161415e565b8960e0013561342b565b612b9e60c0890160a08a01614465565b435f908152600a6020526040812090612bbd60808c0160608d0161415e565b6001600160a01b0316815260208101919091526040015f9081208054909190612bf09084906001600160801b031661468b565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508760a0016020810190612c279190614465565b435f9081526009602052604081208054909190612c4e9084906001600160801b031661468b565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550612cc4886080016020810190612c889190614465565b612c9860808b0160608c0161415e565b612ca860408c0160208d0161415e565b612cb28a80614617565b612cbf60208d018d614617565b613773565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f19612d0360608b0160408c0161415e565b612d1360c08c0160a08d01614465565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160801b031660248201526044015f604051808303815f87803b158015612d5f575f5ffd5b505af1158015612d71573d5f5f3e3d5ffd5b50612d86925050506080890160608a0161415e565b6001600160a01b0316612d9f60608a0160408b0161415e565b6001600160a01b0316612db860408b0160208c0161415e565b6001600160a01b03167fb55810952b04eb8aedf037fe0ccec9d04d852f06753eb52085118329252ae9b9612df260a08d0160808e01614465565b612e0260c08e0160a08f01614465565b612e106101008f018f6146c5565b604051612e20949392919061472f565b60405180910390a450505050506117506001600455565b5f612e418161325f565b610ab66138ec565b6001600160a01b038216612e705760405163e6c4247b60e01b815260040160405180910390fd5b8015612ee457335f908152600660205260409020612e8e90836133c9565b612eab5760405163e6c4247b60e01b815260040160405180910390fd5b6040516001600160a01b0383169033907f0d21c62c0c678e2d47ebd0409bf53131e0a431cdfe1f780cc88d4d94f43eb3ff905f90a35050565b335f908152600660205260409020612efc90836133b5565b612f195760405163e6c4247b60e01b815260040160405180910390fd5b6040516001600160a01b0383169033907f6e63003c7a0ad5718ea27734884d2c2221e14cd1b4e6d559b00734dd34c8af9c905f90a35050565b5f612f5c8161325f565b6001600160a01b0382165f90815260076020526040902054610100900460ff16612fa45760405163094403b760e41b81526001600160a01b0383166004820152602401610b07565b6001600160a01b0382165f8181526007602090815260409182902060010180546001600160801b031981166001600160801b03898116918217909355845192909116808352928201529092917f96b246e163c6e0477f8d777b6e5f3492233ef888481c386ef27e527df21d7f6b9101610b85565b5f516020614a825f395f51905f5261302f8161325f565b6001600160a01b0382166130565760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0382165f81815260056020526040808220805460ff19166001179055517f7409cb8e690bcd1487fd4fd27dad3fa92388d201ba6f953631d6d6b26299f8499190a25050565b5f7f000000000000000000000000000000000000000000000000000000000000000046036130ef57507f000000000000000000000000000000000000000000000000000000000000000090565b610e3a604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f924057aed08648f274927e52243890092250b6a10bb03cb421f423165ac417d8918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b5f5f5f835f036131b957604051633ab3447f60e11b815260040160405180910390fd5b6001600160a01b0385165f908152600b602090815260408083206effffffffffffffffffffffffffffff600889901c16808552925290912054600160ff87161b908082161561321b57604051633ab3447f60e11b815260040160405180910390fd5b91945090925090505b9250925092565b5f6001600160e01b03198216637965db0b60e01b1480610a9e57506301ffc9a760e01b6001600160e01b0319831614610a9e565b610ab681336138f6565b6132735f5f61392f565b565b6001600160a01b0381165f90815260018301602052604081205415156117b7565b816132b457604051631fe1e13d60e11b815260040160405180910390fd5b610d7782826139ee565b5f8261331a575f6132d76002546001600160a01b031690565b6001600160a01b0316146132fe57604051631fe1e13d60e11b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0384161790555b6117b78383613a12565b60605f6117b783613aa1565b6001600160a01b03811633146133595760405163334bd91960e11b815260040160405180910390fd5b61175082826134c7565b61336b613afa565b6003805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b5f6117b7836001600160a01b038416613b1d565b5f6117b7836001600160a01b038416613c07565b60026004540361340057604051633ee5aeb560e01b815260040160405180910390fd5b6002600455565b60035460ff16156132735760405163d93c066560e01b815260040160405180910390fd5b5f5f5f6134388585613196565b6001600160a01b039097165f908152600b6020908152604080832094835293905291909120951790945550505050565b6040516001600160a01b0383811660248301526044820183905261175091859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050613c4c565b5f821580156134e357506002546001600160a01b038381169116145b156134f957600280546001600160a01b03191690555b6117b78383613cb8565b5f61350c612806565b61351542613d21565b61351f91906149f1565b905061352b8282613d57565b60405165ffffffffffff821681526001600160a01b038316907f3377dc44241e779dd06afab5b788a35ca5f3b778836e2990bdb26a2a4b2e5ed69060200160405180910390a25050565b5f61357f82613dd4565b61358842613d21565b61359291906149f1565b905061359e828261392f565b6040805165ffffffffffff8085168252831660208201527ff1038c18cf84a56e432fdbfaf746924b7ea511dfe03a6506a0ceba4888788d9b910160405180910390a15050565b6135ec613407565b6003805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586133983390565b5f5f826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561365f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136839190614a0f565b60ff169392505050565b5f5f5f5f61369b8686613e1b565b9250925092506136ab8282613e61565b5090949350505050565b5f5f6136bf6128a3565b915091506136d48165ffffffffffff16151590565b15806136e857504265ffffffffffff821610155b15613710576040516319ca5ebb60e01b815265ffffffffffff82166004820152602401610b07565b61372b5f6137266002546001600160a01b031690565b6134c7565b506137365f836132be565b5050600180546001600160d01b031916905550565b8161376957604051631fe1e13d60e11b815260040160405180910390fd5b610d778282613f19565b6001600160a01b0386165f90815260076020526040902054610100900460ff166137b057604051630928045160e21b815260040160405180910390fd5b855f805b6001600160801b038116861115613873575f6127108686846001600160801b03168181106137e4576137e4614663565b90506020020160208101906137f99190614465565b613803908d6148c1565b61380d9190614894565b905061385e898989856001600160801b031681811061382e5761382e614663565b9050602002016020810190613843919061415e565b6001600160a01b03871691906001600160801b038516613f3d565b613868818461468b565b9250506001016137b4565b505f61387f828b61476a565b90506001600160801b038116156138e0576138e08888886138a16001826149de565b8181106138b0576138b0614663565b90506020020160208101906138c5919061415e565b6001600160a01b03861691906001600160801b038516613f3d565b50505050505050505050565b6132735f5f613d57565b6139008282611ce0565b610d775760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610b07565b600254600160d01b900465ffffffffffff1680156139b1574265ffffffffffff8216101561398857600254600180546001600160d01b0316600160a01b90920465ffffffffffff16600160d01b029190911790556139b1565b6040517f2b1fa2edafe6f7b9e97c1a9e0c3660e645beb2dcaa2d45bdbf9beaf5472e1ec5905f90a15b50600280546001600160a01b0316600160a01b65ffffffffffff948516026001600160d01b031617600160d01b9290931691909102919091179055565b5f82815260208190526040902060010154613a088161325f565b611ff283836132be565b5f613a1d8383611ce0565b613a9a575f838152602081815260408083206001600160a01b03861684529091529020805460ff19166001179055613a523390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610a9e565b505f610a9e565b6060815f01805480602002602001604051908101604052809291908181526020018280548015613aee57602002820191905f5260205f20905b815481526020019060010190808311613ada575b50505050509050919050565b60035460ff1661327357604051638dfc202b60e01b815260040160405180910390fd5b5f8181526001830160205260408120548015613bf7575f613b3f6001836149de565b85549091505f90613b52906001906149de565b9050808214613bb1575f865f018281548110613b7057613b70614663565b905f5260205f200154905080875f018481548110613b9057613b90614663565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080613bc257613bc2614a2f565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610a9e565b5f915050610a9e565b5092915050565b5f818152600183016020526040812054613a9a57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610a9e565b5f5f60205f8451602086015f885af180613c6b576040513d5f823e3d81fd5b50505f513d91508115613c82578060011415613c8f565b6001600160a01b0384163b155b15611ff257604051635274afe760e01b81526001600160a01b0385166004820152602401610b07565b5f613cc38383611ce0565b15613a9a575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610a9e565b5f65ffffffffffff821115613d53576040516306dfcc6560e41b81526030600482015260248101839052604401610b07565b5090565b5f613d606128a3565b6001805465ffffffffffff8616600160a01b026001600160d01b03199091166001600160a01b038816171790559150613da290508165ffffffffffff16151590565b15611750576040517f8886ebfc4259abdbc16601dd8fb5678e54878f47b3c34836cfc51154a9605109905f90a1505050565b5f5f613dde612806565b90508065ffffffffffff168365ffffffffffff1611613e0657613e018382614a43565b6117b7565b6117b765ffffffffffff841662069780613f76565b5f5f5f8351604103613e52576020840151604085015160608601515f1a613e4488828585613f85565b955095509550505050613224565b505081515f9150600290613224565b5f826003811115613e7457613e746145ca565b03613e7d575050565b6001826003811115613e9157613e916145ca565b03613eaf5760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115613ec357613ec36145ca565b03613ee45760405163fce698f760e01b815260048101829052602401610b07565b6003826003811115613ef857613ef86145ca565b03610d77576040516335e2f38360e21b815260048101829052602401610b07565b5f82815260208190526040902060010154613f338161325f565b611ff283836134c7565b6040516001600160a01b038481166024830152838116604483015260648201839052611ff29186918216906323b872dd90608401613495565b5f8282188284100282186117b7565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115613fbe57505f91506003905082614043565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa15801561400f573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b03811661403a57505f925060019150829050614043565b92505f91508190505b9450945094915050565b6001600160e01b031981168114610ab6575f5ffd5b5f60208284031215614072575f5ffd5b81356117b78161404d565b80356001600160801b0381168114614093575f5ffd5b919050565b80356001600160a01b0381168114614093575f5ffd5b5f5f604083850312156140bf575f5ffd5b6140c88361407d565b91506140d660208401614098565b90509250929050565b5f604082840312156140ef575f5ffd5b50919050565b5f60208284031215614105575f5ffd5b81356001600160401b0381111561411a575f5ffd5b611e89848285016140df565b5f60208284031215614136575f5ffd5b5035919050565b5f5f6040838503121561414e575f5ffd5b823591506140d660208401614098565b5f6020828403121561416e575f5ffd5b6117b782614098565b602080825282518282018190525f918401906040840190835b818110156141b75783516001600160a01b0316835260209384019390920191600101614190565b509095945050505050565b5f61012082840312156140ef575f5ffd5b5f602082840312156141e3575f5ffd5b81356001600160401b038111156141f8575f5ffd5b611e89848285016141c2565b5f5f60408385031215614215575f5ffd5b82356001600160401b0381111561422a575f5ffd5b614236858286016141c2565b92505060208301356001600160401b03811115614251575f5ffd5b61425d858286016140df565b9150509250929050565b5f5f60408385031215614278575f5ffd5b6140c883614098565b5f60208284031215614291575f5ffd5b813565ffffffffffff811681146117b7575f5ffd5b5f5f604083850312156142b7575f5ffd5b6142c08361407d565b91506140d66020840161407d565b803560018110614093575f5ffd5b80358015158114614093575f5ffd5b5f5f82840360a08112156142fd575f5ffd5b61430684614098565b92506080601f1982011215614319575f5ffd5b50604051608081018181106001600160401b038211171561434857634e487b7160e01b5f52604160045260245ffd5b604052614357602085016142ce565b8152614365604085016142dc565b60208201526143766060850161407d565b60408201526143876080850161407d565b6060820152809150509250929050565b60028110610ab6575f5ffd5b5f5f5f5f608085870312156143b6575f5ffd5b6143bf8561407d565b93506143cd6020860161407d565b92506143db60408601614098565b915060608501356143eb81614397565b939692955090935050565b5f5f60208385031215614407575f5ffd5b82356001600160401b0381111561441c575f5ffd5b8301601f8101851361442c575f5ffd5b80356001600160401b03811115614441575f5ffd5b8560208260051b8401011115614455575f5ffd5b6020919091019590945092505050565b5f60208284031215614475575f5ffd5b6117b78261407d565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f5f606084860312156144c5575f5ffd5b6144ce84614098565b92506020840135915060408401356001600160401b038111156144ef575f5ffd5b6144fb868287016140df565b9150509250925092565b5f5f5f60608486031215614517575f5ffd5b83356001600160401b0381111561452c575f5ffd5b614538868287016141c2565b93505060208401356001600160401b03811115614553575f5ffd5b61455f868287016140df565b92505060408401356001600160401b038111156144ef575f5ffd5b5f5f6040838503121561458b575f5ffd5b61459483614098565b91506140d6602084016142dc565b5f5f604083850312156145b3575f5ffd5b6145bc83614098565b946020939093013593505050565b634e487b7160e01b5f52602160045260245ffd5b60808101600186106145f2576145f26145ca565b94815292151560208401526001600160801b0391821660408401521660609091015290565b5f5f8335601e1984360301811261462c575f5ffd5b8301803591506001600160401b03821115614645575f5ffd5b6020019150600581901b360382131561465c575f5ffd5b9250929050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b6001600160801b038181168382160190811115610a9e57610a9e614677565b5f602082840312156146ba575f5ffd5b81356117b781614397565b5f5f8335601e198436030181126146da575f5ffd5b8301803591506001600160401b038211156146f3575f5ffd5b60200191503681900382131561465c575f5ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b6001600160801b03851681526001600160801b0384166020820152606060408201525f614760606083018486614707565b9695505050505050565b6001600160801b038281168282160390811115610a9e57610a9e614677565b6001815b60018411156147c4578085048111156147a8576147a8614677565b60018416156147b657908102905b60019390931c92800261478d565b935093915050565b5f826147da57506001610a9e565b816147e657505f610a9e565b81600181146147fc576002811461480657614822565b6001915050610a9e565b60ff84111561481757614817614677565b50506001821b610a9e565b5060208310610133831016604e8410600b8410161715614845575081810a610a9e565b6148515f198484614789565b805f190482111561486457614864614677565b029392505050565b5f6117b76001600160801b038416836147cc565b634e487b7160e01b5f52601260045260245ffd5b5f6001600160801b038316806148ac576148ac614880565b806001600160801b0384160491505092915050565b6001600160801b038181168382160290811690818114613c0057613c00614677565b818382375f9101908152919050565b8a8152610140810160028b1061490a5761490a6145ca565b602082019a909a526001600160a01b03988916604082015296881660608801529490961660808601526001600160801b0392831660a086015290821660c08501521660e08301526101008201929092526101200152919050565b838152604060208201525f61497d604083018486614707565b95945050505050565b5f60208284031215614996575f5ffd5b81516117b78161404d565b80820180821115610a9e57610a9e614677565b8082028115828204841417610a9e57610a9e614677565b5f826149d9576149d9614880565b500490565b81810381811115610a9e57610a9e614677565b65ffffffffffff8181168382160190811115610a9e57610a9e614677565b5f60208284031215614a1f575f5ffd5b815160ff811681146117b7575f5ffd5b634e487b7160e01b5f52603160045260245ffd5b65ffffffffffff8281168282160390811115610a9e57610a9e61467756fe3c63e605be3290ab6b04cfc46c6e1516e626d43236b034f09d7ede1d017beb0c8619cecd8b9e095ab43867f5b69d492180450fe862e6b50bfbfb24b75dd84c8a5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5a26469706673582212206d80c2aa71d2d6989f6cebd49d64427f2eee5c0a917ea2cd6a05c86c87b6a66064736f6c634300081c0033000000000000000000000000d0580192e98ea6ceb9c7b6191ed2e2756091169700000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000002b5e3af16b18800000000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000c6bbfd2d5666d44bf28580edeec0263692c83160000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000002b5e3af16b18800000000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000002b5e3af16b18800000000000000000000000000000000000000000000000000004563918244f40000","name":"ToriMinting","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":false,"language":"solidity","evm_version":"cancun","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"@openzeppelin/contracts/access/AccessControl.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.20;\n\nimport {IAccessControl} from \"./IAccessControl.sol\";\nimport {Context} from \"../utils/Context.sol\";\nimport {IERC165, ERC165} from \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n *     require(hasRole(MY_ROLE, msg.sender));\n *     ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n    struct RoleData {\n        mapping(address account => bool) hasRole;\n        bytes32 adminRole;\n    }\n\n    mapping(bytes32 role => RoleData) private _roles;\n\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n    /**\n     * @dev Modifier that checks that an account has a specific role. Reverts\n     * with an {AccessControlUnauthorizedAccount} error including the required role.\n     */\n    modifier onlyRole(bytes32 role) {\n        _checkRole(role);\n        _;\n    }\n\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n        return _roles[role].hasRole[account];\n    }\n\n    /**\n     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n     */\n    function _checkRole(bytes32 role) internal view virtual {\n        _checkRole(role, _msgSender());\n    }\n\n    /**\n     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n     * is missing `role`.\n     */\n    function _checkRole(bytes32 role, address account) internal view virtual {\n        if (!hasRole(role, account)) {\n            revert AccessControlUnauthorizedAccount(account, role);\n        }\n    }\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n        return _roles[role].adminRole;\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been revoked `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `callerConfirmation`.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n        if (callerConfirmation != _msgSender()) {\n            revert AccessControlBadConfirmation();\n        }\n\n        _revokeRole(role, callerConfirmation);\n    }\n\n    /**\n     * @dev Sets `adminRole` as ``role``'s admin role.\n     *\n     * Emits a {RoleAdminChanged} event.\n     */\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n        bytes32 previousAdminRole = getRoleAdmin(role);\n        _roles[role].adminRole = adminRole;\n        emit RoleAdminChanged(role, previousAdminRole, adminRole);\n    }\n\n    /**\n     * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n        if (!hasRole(role, account)) {\n            _roles[role].hasRole[account] = true;\n            emit RoleGranted(role, account, _msgSender());\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n        if (hasRole(role, account)) {\n            _roles[role].hasRole[account] = false;\n            emit RoleRevoked(role, account, _msgSender());\n            return true;\n        } else {\n            return false;\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Context.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/introspection/ERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/introspection/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},{"file_path":"@openzeppelin/contracts/utils/math/Math.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\nimport {Panic} from \"../Panic.sol\";\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Return the 512-bit addition of two uint256.\n     *\n     * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.\n     */\n    function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n        assembly (\"memory-safe\") {\n            low := add(a, b)\n            high := lt(low, a)\n        }\n    }\n\n    /**\n     * @dev Return the 512-bit multiplication of two uint256.\n     *\n     * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.\n     */\n    function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n        // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use\n        // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n        // variables such that product = high * 2²⁵⁶ + low.\n        assembly (\"memory-safe\") {\n            let mm := mulmod(a, b, not(0))\n            low := mul(a, b)\n            high := sub(sub(mm, low), lt(mm, low))\n        }\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a + b;\n            success = c >= a;\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a - b;\n            success = c <= a;\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a * b;\n            assembly (\"memory-safe\") {\n                // Only true when the multiplication doesn't overflow\n                // (c / a == b) || (a == 0)\n                success := or(eq(div(c, a), b), iszero(a))\n            }\n            // equivalent to: success ? c : 0\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            success = b > 0;\n            assembly (\"memory-safe\") {\n                // The `DIV` opcode returns zero when the denominator is 0.\n                result := div(a, b)\n            }\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            success = b > 0;\n            assembly (\"memory-safe\") {\n                // The `MOD` opcode returns zero when the denominator is 0.\n                result := mod(a, b)\n            }\n        }\n    }\n\n    /**\n     * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.\n     */\n    function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\n        (bool success, uint256 result) = tryAdd(a, b);\n        return ternary(success, result, type(uint256).max);\n    }\n\n    /**\n     * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\n     */\n    function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\n        (, uint256 result) = trySub(a, b);\n        return result;\n    }\n\n    /**\n     * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.\n     */\n    function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\n        (bool success, uint256 result) = tryMul(a, b);\n        return ternary(success, result, type(uint256).max);\n    }\n\n    /**\n     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\n     *\n     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\n     * one branch when needed, making this function more expensive.\n     */\n    function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\n        unchecked {\n            // branchless ternary works because:\n            // b ^ (a ^ b) == a\n            // b ^ 0 == b\n            return b ^ ((a ^ b) * SafeCast.toUint(condition));\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return ternary(a > b, a, b);\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return ternary(a < b, a, b);\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n\n        // The following calculation ensures accurate ceiling division without overflow.\n        // Since a is non-zero, (a - 1) / b will not overflow.\n        // The largest possible result occurs when (a - 1) / b is type(uint256).max,\n        // but the largest value we can obtain is type(uint256).max - 1, which happens\n        // when a = type(uint256).max and b = 1.\n        unchecked {\n            return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\n        }\n    }\n\n    /**\n     * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n     * denominator == 0.\n     *\n     * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            (uint256 high, uint256 low) = mul512(x, y);\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (high == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return low / denominator;\n            }\n\n            // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.\n            if (denominator <= high) {\n                Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\n            }\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [high low].\n            uint256 remainder;\n            assembly (\"memory-safe\") {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                high := sub(high, gt(remainder, low))\n                low := sub(low, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\n            assembly (\"memory-safe\") {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [high low] by twos.\n                low := div(low, twos)\n\n                // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from high into low.\n            low |= high * twos;\n\n            // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such\n            // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv ≡ 1 mod 2⁴.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n            // works in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶\n            inverse *= 2 - denominator * inverse; // inverse mod 2³²\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is\n            // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high\n            // is no longer required.\n            result = low * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\n    }\n\n    /**\n     * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\n     */\n    function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\n        unchecked {\n            (uint256 high, uint256 low) = mul512(x, y);\n            if (high >= 1 << n) {\n                Panic.panic(Panic.UNDER_OVERFLOW);\n            }\n            return (high << (256 - n)) | (low >> n);\n        }\n    }\n\n    /**\n     * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\n     */\n    function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\n        return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\n    }\n\n    /**\n     * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\n     *\n     * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\n     * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\n     *\n     * If the input value is not inversible, 0 is returned.\n     *\n     * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\n     * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\n     */\n    function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\n        unchecked {\n            if (n == 0) return 0;\n\n            // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\n            // Used to compute integers x and y such that: ax + ny = gcd(a, n).\n            // When the gcd is 1, then the inverse of a modulo n exists and it's x.\n            // ax + ny = 1\n            // ax = 1 + (-y)n\n            // ax ≡ 1 (mod n) # x is the inverse of a modulo n\n\n            // If the remainder is 0 the gcd is n right away.\n            uint256 remainder = a % n;\n            uint256 gcd = n;\n\n            // Therefore the initial coefficients are:\n            // ax + ny = gcd(a, n) = n\n            // 0a + 1n = n\n            int256 x = 0;\n            int256 y = 1;\n\n            while (remainder != 0) {\n                uint256 quotient = gcd / remainder;\n\n                (gcd, remainder) = (\n                    // The old remainder is the next gcd to try.\n                    remainder,\n                    // Compute the next remainder.\n                    // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\n                    // where gcd is at most n (capped to type(uint256).max)\n                    gcd - remainder * quotient\n                );\n\n                (x, y) = (\n                    // Increment the coefficient of a.\n                    y,\n                    // Decrement the coefficient of n.\n                    // Can overflow, but the result is casted to uint256 so that the\n                    // next value of y is \"wrapped around\" to a value between 0 and n - 1.\n                    x - y * int256(quotient)\n                );\n            }\n\n            if (gcd != 1) return 0; // No inverse exists.\n            return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\n        }\n    }\n\n    /**\n     * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\n     *\n     * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\n     * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that\n     * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\n     *\n     * NOTE: this function does NOT check that `p` is a prime greater than `2`.\n     */\n    function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\n        unchecked {\n            return Math.modExp(a, p - 2, p);\n        }\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\n     *\n     * Requirements:\n     * - modulus can't be zero\n     * - underlying staticcall to precompile must succeed\n     *\n     * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\n     * sure the chain you're using it on supports the precompiled contract for modular exponentiation\n     * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\n     * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\n     * interpreted as 0.\n     */\n    function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\n        (bool success, uint256 result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\n     * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\n     * to operate modulo 0 or if the underlying precompile reverted.\n     *\n     * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\n     * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\n     * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\n     * of a revert, but the result may be incorrectly interpreted as 0.\n     */\n    function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\n        if (m == 0) return (false, 0);\n        assembly (\"memory-safe\") {\n            let ptr := mload(0x40)\n            // | Offset    | Content    | Content (Hex)                                                      |\n            // |-----------|------------|--------------------------------------------------------------------|\n            // | 0x00:0x1f | size of b  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x20:0x3f | size of e  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x40:0x5f | size of m  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x60:0x7f | value of b | 0x<.............................................................b> |\n            // | 0x80:0x9f | value of e | 0x<.............................................................e> |\n            // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\n            mstore(ptr, 0x20)\n            mstore(add(ptr, 0x20), 0x20)\n            mstore(add(ptr, 0x40), 0x20)\n            mstore(add(ptr, 0x60), b)\n            mstore(add(ptr, 0x80), e)\n            mstore(add(ptr, 0xa0), m)\n\n            // Given the result < m, it's guaranteed to fit in 32 bytes,\n            // so we can use the memory scratch space located at offset 0.\n            success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\n            result := mload(0x00)\n        }\n    }\n\n    /**\n     * @dev Variant of {modExp} that supports inputs of arbitrary length.\n     */\n    function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\n        (bool success, bytes memory result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\n     */\n    function tryModExp(\n        bytes memory b,\n        bytes memory e,\n        bytes memory m\n    ) internal view returns (bool success, bytes memory result) {\n        if (_zeroBytes(m)) return (false, new bytes(0));\n\n        uint256 mLen = m.length;\n\n        // Encode call args in result and move the free memory pointer\n        result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\n\n        assembly (\"memory-safe\") {\n            let dataPtr := add(result, 0x20)\n            // Write result on top of args to avoid allocating extra memory.\n            success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\n            // Overwrite the length.\n            // result.length > returndatasize() is guaranteed because returndatasize() == m.length\n            mstore(result, mLen)\n            // Set the memory pointer after the returned data.\n            mstore(0x40, add(dataPtr, mLen))\n        }\n    }\n\n    /**\n     * @dev Returns whether the provided byte array is zero.\n     */\n    function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\n        for (uint256 i = 0; i < byteArray.length; ++i) {\n            if (byteArray[i] != 0) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n     * towards zero.\n     *\n     * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\n     * using integer operations.\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        unchecked {\n            // Take care of easy edge cases when a == 0 or a == 1\n            if (a <= 1) {\n                return a;\n            }\n\n            // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a\n            // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\n            // the current value as `ε_n = | x_n - sqrt(a) |`.\n            //\n            // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\n            // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is\n            // bigger than any uint256.\n            //\n            // By noticing that\n            // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`\n            // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\n            // to the msb function.\n            uint256 aa = a;\n            uint256 xn = 1;\n\n            if (aa >= (1 << 128)) {\n                aa >>= 128;\n                xn <<= 64;\n            }\n            if (aa >= (1 << 64)) {\n                aa >>= 64;\n                xn <<= 32;\n            }\n            if (aa >= (1 << 32)) {\n                aa >>= 32;\n                xn <<= 16;\n            }\n            if (aa >= (1 << 16)) {\n                aa >>= 16;\n                xn <<= 8;\n            }\n            if (aa >= (1 << 8)) {\n                aa >>= 8;\n                xn <<= 4;\n            }\n            if (aa >= (1 << 4)) {\n                aa >>= 4;\n                xn <<= 2;\n            }\n            if (aa >= (1 << 2)) {\n                xn <<= 1;\n            }\n\n            // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).\n            //\n            // We can refine our estimation by noticing that the middle of that interval minimizes the error.\n            // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).\n            // This is going to be our x_0 (and ε_0)\n            xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)\n\n            // From here, Newton's method give us:\n            // x_{n+1} = (x_n + a / x_n) / 2\n            //\n            // One should note that:\n            // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a\n            //              = ((x_n² + a) / (2 * x_n))² - a\n            //              = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a\n            //              = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)\n            //              = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)\n            //              = (x_n² - a)² / (2 * x_n)²\n            //              = ((x_n² - a) / (2 * x_n))²\n            //              ≥ 0\n            // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n\n            //\n            // This gives us the proof of quadratic convergence of the sequence:\n            // ε_{n+1} = | x_{n+1} - sqrt(a) |\n            //         = | (x_n + a / x_n) / 2 - sqrt(a) |\n            //         = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |\n            //         = | (x_n - sqrt(a))² / (2 * x_n) |\n            //         = | ε_n² / (2 * x_n) |\n            //         = ε_n² / | (2 * x_n) |\n            //\n            // For the first iteration, we have a special case where x_0 is known:\n            // ε_1 = ε_0² / | (2 * x_0) |\n            //     ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))\n            //     ≤ 2**(2*e-4) / (3 * 2**(e-1))\n            //     ≤ 2**(e-3) / 3\n            //     ≤ 2**(e-3-log2(3))\n            //     ≤ 2**(e-4.5)\n            //\n            // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:\n            // ε_{n+1} = ε_n² / | (2 * x_n) |\n            //         ≤ (2**(e-k))² / (2 * 2**(e-1))\n            //         ≤ 2**(2*e-2*k) / 2**e\n            //         ≤ 2**(e-2*k)\n            xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5)  -- special case, see above\n            xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9)    -- general case with k = 4.5\n            xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18)   -- general case with k = 9\n            xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36)   -- general case with k = 18\n            xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72)   -- general case with k = 36\n            xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144)  -- general case with k = 72\n\n            // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision\n            // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\n            // sqrt(a) or sqrt(a) + 1.\n            return xn - SafeCast.toUint(xn > a / xn);\n        }\n    }\n\n    /**\n     * @dev Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 x) internal pure returns (uint256 r) {\n        // If value has upper 128 bits set, log2 result is at least 128\n        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n        // If upper 64 bits of 128-bit half set, add 64 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n        // If upper 32 bits of 64-bit half set, add 32 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n        // If upper 16 bits of 32-bit half set, add 16 to result\n        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n        // If upper 8 bits of 16-bit half set, add 8 to result\n        r |= SafeCast.toUint((x >> r) > 0xff) << 3;\n        // If upper 4 bits of 8-bit half set, add 4 to result\n        r |= SafeCast.toUint((x >> r) > 0xf) << 2;\n\n        // Shifts value right by the current result and use it as an index into this lookup table:\n        //\n        // | x (4 bits) |  index  | table[index] = MSB position |\n        // |------------|---------|-----------------------------|\n        // |    0000    |    0    |        table[0] = 0         |\n        // |    0001    |    1    |        table[1] = 0         |\n        // |    0010    |    2    |        table[2] = 1         |\n        // |    0011    |    3    |        table[3] = 1         |\n        // |    0100    |    4    |        table[4] = 2         |\n        // |    0101    |    5    |        table[5] = 2         |\n        // |    0110    |    6    |        table[6] = 2         |\n        // |    0111    |    7    |        table[7] = 2         |\n        // |    1000    |    8    |        table[8] = 3         |\n        // |    1001    |    9    |        table[9] = 3         |\n        // |    1010    |   10    |        table[10] = 3        |\n        // |    1011    |   11    |        table[11] = 3        |\n        // |    1100    |   12    |        table[12] = 3        |\n        // |    1101    |   13    |        table[13] = 3        |\n        // |    1110    |   14    |        table[14] = 3        |\n        // |    1111    |   15    |        table[15] = 3        |\n        //\n        // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\n        assembly (\"memory-safe\") {\n            r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 x) internal pure returns (uint256 r) {\n        // If value has upper 128 bits set, log2 result is at least 128\n        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n        // If upper 64 bits of 128-bit half set, add 64 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n        // If upper 32 bits of 64-bit half set, add 32 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n        // If upper 16 bits of 32-bit half set, add 16 to result\n        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n        // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\n        return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/math/SafeCast.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeCast {\n    /**\n     * @dev Value doesn't fit in an uint of `bits` size.\n     */\n    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\n\n    /**\n     * @dev An int value doesn't fit in an uint of `bits` size.\n     */\n    error SafeCastOverflowedIntToUint(int256 value);\n\n    /**\n     * @dev Value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\n\n    /**\n     * @dev An uint value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedUintToInt(uint256 value);\n\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        if (value > type(uint248).max) {\n            revert SafeCastOverflowedUintDowncast(248, value);\n        }\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        if (value > type(uint240).max) {\n            revert SafeCastOverflowedUintDowncast(240, value);\n        }\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        if (value > type(uint232).max) {\n            revert SafeCastOverflowedUintDowncast(232, value);\n        }\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        if (value > type(uint224).max) {\n            revert SafeCastOverflowedUintDowncast(224, value);\n        }\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        if (value > type(uint216).max) {\n            revert SafeCastOverflowedUintDowncast(216, value);\n        }\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        if (value > type(uint208).max) {\n            revert SafeCastOverflowedUintDowncast(208, value);\n        }\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        if (value > type(uint200).max) {\n            revert SafeCastOverflowedUintDowncast(200, value);\n        }\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        if (value > type(uint192).max) {\n            revert SafeCastOverflowedUintDowncast(192, value);\n        }\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        if (value > type(uint184).max) {\n            revert SafeCastOverflowedUintDowncast(184, value);\n        }\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        if (value > type(uint176).max) {\n            revert SafeCastOverflowedUintDowncast(176, value);\n        }\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        if (value > type(uint168).max) {\n            revert SafeCastOverflowedUintDowncast(168, value);\n        }\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        if (value > type(uint160).max) {\n            revert SafeCastOverflowedUintDowncast(160, value);\n        }\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        if (value > type(uint152).max) {\n            revert SafeCastOverflowedUintDowncast(152, value);\n        }\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        if (value > type(uint144).max) {\n            revert SafeCastOverflowedUintDowncast(144, value);\n        }\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        if (value > type(uint136).max) {\n            revert SafeCastOverflowedUintDowncast(136, value);\n        }\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        if (value > type(uint128).max) {\n            revert SafeCastOverflowedUintDowncast(128, value);\n        }\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        if (value > type(uint120).max) {\n            revert SafeCastOverflowedUintDowncast(120, value);\n        }\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        if (value > type(uint112).max) {\n            revert SafeCastOverflowedUintDowncast(112, value);\n        }\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        if (value > type(uint104).max) {\n            revert SafeCastOverflowedUintDowncast(104, value);\n        }\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        if (value > type(uint96).max) {\n            revert SafeCastOverflowedUintDowncast(96, value);\n        }\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        if (value > type(uint88).max) {\n            revert SafeCastOverflowedUintDowncast(88, value);\n        }\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        if (value > type(uint80).max) {\n            revert SafeCastOverflowedUintDowncast(80, value);\n        }\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        if (value > type(uint72).max) {\n            revert SafeCastOverflowedUintDowncast(72, value);\n        }\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        if (value > type(uint64).max) {\n            revert SafeCastOverflowedUintDowncast(64, value);\n        }\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        if (value > type(uint56).max) {\n            revert SafeCastOverflowedUintDowncast(56, value);\n        }\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        if (value > type(uint48).max) {\n            revert SafeCastOverflowedUintDowncast(48, value);\n        }\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        if (value > type(uint40).max) {\n            revert SafeCastOverflowedUintDowncast(40, value);\n        }\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        if (value > type(uint32).max) {\n            revert SafeCastOverflowedUintDowncast(32, value);\n        }\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        if (value > type(uint24).max) {\n            revert SafeCastOverflowedUintDowncast(24, value);\n        }\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        if (value > type(uint16).max) {\n            revert SafeCastOverflowedUintDowncast(16, value);\n        }\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        if (value > type(uint8).max) {\n            revert SafeCastOverflowedUintDowncast(8, value);\n        }\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        if (value < 0) {\n            revert SafeCastOverflowedIntToUint(value);\n        }\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(248, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(240, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(232, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(224, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(216, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(208, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(200, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(192, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(184, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(176, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(168, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(160, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(152, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(144, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(136, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(128, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(120, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(112, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(104, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(96, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(88, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(80, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(72, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(64, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(56, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(48, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(40, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(32, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(24, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(16, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(8, value);\n        }\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        if (value > uint256(type(int256).max)) {\n            revert SafeCastOverflowedUintToInt(value);\n        }\n        return int256(value);\n    }\n\n    /**\n     * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\n     */\n    function toUint(bool b) internal pure returns (uint256 u) {\n        assembly (\"memory-safe\") {\n            u := iszero(iszero(b))\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Comparators.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Comparators.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides a set of functions to compare values.\n *\n * _Available since v5.1._\n */\nlibrary Comparators {\n    function lt(uint256 a, uint256 b) internal pure returns (bool) {\n        return a < b;\n    }\n\n    function gt(uint256 a, uint256 b) internal pure returns (bool) {\n        return a > b;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/access/IAccessControl.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/IAccessControl.sol)\n\npragma solidity >=0.8.4;\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n    /**\n     * @dev The `account` is missing a role.\n     */\n    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n    /**\n     * @dev The caller of a function is not the expected one.\n     *\n     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n     */\n    error AccessControlBadConfirmation();\n\n    /**\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n     *\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n     * {RoleAdminChanged} not being emitted to signal this.\n     */\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n    /**\n     * @dev Emitted when `account` is granted `role`.\n     *\n     * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).\n     * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.\n     */\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Emitted when `account` is revoked `role`.\n     *\n     * `sender` is the account that originated the contract call:\n     *   - if using `revokeRole`, it is the admin role bearer\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\n     */\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) external view returns (bool);\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `callerConfirmation`.\n     */\n    function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n"},{"file_path":"@openzeppelin/contracts/access/extensions/AccessControlDefaultAdminRules.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/extensions/AccessControlDefaultAdminRules.sol)\n\npragma solidity ^0.8.20;\n\nimport {IAccessControlDefaultAdminRules} from \"./IAccessControlDefaultAdminRules.sol\";\nimport {AccessControl, IAccessControl} from \"../AccessControl.sol\";\nimport {SafeCast} from \"../../utils/math/SafeCast.sol\";\nimport {Math} from \"../../utils/math/Math.sol\";\nimport {IERC5313} from \"../../interfaces/IERC5313.sol\";\nimport {IERC165} from \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Extension of {AccessControl} that allows specifying special rules to manage\n * the `DEFAULT_ADMIN_ROLE` holder, which is a sensitive role with special permissions\n * over other roles that may potentially have privileged rights in the system.\n *\n * If a specific role doesn't have an admin role assigned, the holder of the\n * `DEFAULT_ADMIN_ROLE` will have the ability to grant it and revoke it.\n *\n * This contract implements the following risk mitigations on top of {AccessControl}:\n *\n * * Only one account holds the `DEFAULT_ADMIN_ROLE` since deployment until it's potentially renounced.\n * * Enforces a 2-step process to transfer the `DEFAULT_ADMIN_ROLE` to another account.\n * * Enforces a configurable delay between the two steps, with the ability to cancel before the transfer is accepted.\n * * The delay can be changed by scheduling, see {changeDefaultAdminDelay}.\n * * Role transfers must wait at least one block after scheduling before it can be accepted.\n * * It is not possible to use another role to manage the `DEFAULT_ADMIN_ROLE`.\n *\n * Example usage:\n *\n * ```solidity\n * contract MyToken is AccessControlDefaultAdminRules {\n *   constructor() AccessControlDefaultAdminRules(\n *     3 days,\n *     msg.sender // Explicit initial `DEFAULT_ADMIN_ROLE` holder\n *    ) {}\n * }\n * ```\n */\nabstract contract AccessControlDefaultAdminRules is IAccessControlDefaultAdminRules, IERC5313, AccessControl {\n    // pending admin pair read/written together frequently\n    address private _pendingDefaultAdmin;\n    uint48 private _pendingDefaultAdminSchedule; // 0 == unset\n\n    uint48 private _currentDelay;\n    address private _currentDefaultAdmin;\n\n    // pending delay pair read/written together frequently\n    uint48 private _pendingDelay;\n    uint48 private _pendingDelaySchedule; // 0 == unset\n\n    /**\n     * @dev Sets the initial values for {defaultAdminDelay} and {defaultAdmin} address.\n     */\n    constructor(uint48 initialDelay, address initialDefaultAdmin) {\n        if (initialDefaultAdmin == address(0)) {\n            revert AccessControlInvalidDefaultAdmin(address(0));\n        }\n        _currentDelay = initialDelay;\n        _grantRole(DEFAULT_ADMIN_ROLE, initialDefaultAdmin);\n    }\n\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IAccessControlDefaultAdminRules).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /// @inheritdoc IERC5313\n    function owner() public view virtual returns (address) {\n        return defaultAdmin();\n    }\n\n    ///\n    /// Override AccessControl role management\n    ///\n\n    /**\n     * @dev See {AccessControl-grantRole}. Reverts for `DEFAULT_ADMIN_ROLE`.\n     */\n    function grantRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) {\n        if (role == DEFAULT_ADMIN_ROLE) {\n            revert AccessControlEnforcedDefaultAdminRules();\n        }\n        super.grantRole(role, account);\n    }\n\n    /**\n     * @dev See {AccessControl-revokeRole}. Reverts for `DEFAULT_ADMIN_ROLE`.\n     */\n    function revokeRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) {\n        if (role == DEFAULT_ADMIN_ROLE) {\n            revert AccessControlEnforcedDefaultAdminRules();\n        }\n        super.revokeRole(role, account);\n    }\n\n    /**\n     * @dev See {AccessControl-renounceRole}.\n     *\n     * For the `DEFAULT_ADMIN_ROLE`, it only allows renouncing in two steps by first calling\n     * {beginDefaultAdminTransfer} to the `address(0)`, so it's required that the {pendingDefaultAdmin} schedule\n     * has also passed when calling this function.\n     *\n     * After its execution, it will not be possible to call `onlyRole(DEFAULT_ADMIN_ROLE)` functions.\n     *\n     * NOTE: Renouncing `DEFAULT_ADMIN_ROLE` will leave the contract without a {defaultAdmin},\n     * thereby disabling any functionality that is only available for it, and the possibility of reassigning a\n     * non-administrated role.\n     */\n    function renounceRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) {\n        if (role == DEFAULT_ADMIN_ROLE && account == defaultAdmin()) {\n            (address newDefaultAdmin, uint48 schedule) = pendingDefaultAdmin();\n            if (newDefaultAdmin != address(0) || !_isScheduleSet(schedule) || !_hasSchedulePassed(schedule)) {\n                revert AccessControlEnforcedDefaultAdminDelay(schedule);\n            }\n            delete _pendingDefaultAdminSchedule;\n        }\n        super.renounceRole(role, account);\n    }\n\n    /**\n     * @dev See {AccessControl-_grantRole}.\n     *\n     * For `DEFAULT_ADMIN_ROLE`, it only allows granting if there isn't already a {defaultAdmin} or if the\n     * role has been previously renounced.\n     *\n     * NOTE: Exposing this function through another mechanism may make the `DEFAULT_ADMIN_ROLE`\n     * assignable again. Make sure to guarantee this is the expected behavior in your implementation.\n     */\n    function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {\n        if (role == DEFAULT_ADMIN_ROLE) {\n            if (defaultAdmin() != address(0)) {\n                revert AccessControlEnforcedDefaultAdminRules();\n            }\n            _currentDefaultAdmin = account;\n        }\n        return super._grantRole(role, account);\n    }\n\n    /// @inheritdoc AccessControl\n    function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {\n        if (role == DEFAULT_ADMIN_ROLE && account == defaultAdmin()) {\n            delete _currentDefaultAdmin;\n        }\n        return super._revokeRole(role, account);\n    }\n\n    /**\n     * @dev See {AccessControl-_setRoleAdmin}. Reverts for `DEFAULT_ADMIN_ROLE`.\n     */\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual override {\n        if (role == DEFAULT_ADMIN_ROLE) {\n            revert AccessControlEnforcedDefaultAdminRules();\n        }\n        super._setRoleAdmin(role, adminRole);\n    }\n\n    ///\n    /// AccessControlDefaultAdminRules accessors\n    ///\n\n    /// @inheritdoc IAccessControlDefaultAdminRules\n    function defaultAdmin() public view virtual returns (address) {\n        return _currentDefaultAdmin;\n    }\n\n    /// @inheritdoc IAccessControlDefaultAdminRules\n    function pendingDefaultAdmin() public view virtual returns (address newAdmin, uint48 schedule) {\n        return (_pendingDefaultAdmin, _pendingDefaultAdminSchedule);\n    }\n\n    /// @inheritdoc IAccessControlDefaultAdminRules\n    function defaultAdminDelay() public view virtual returns (uint48) {\n        uint48 schedule = _pendingDelaySchedule;\n        return (_isScheduleSet(schedule) && _hasSchedulePassed(schedule)) ? _pendingDelay : _currentDelay;\n    }\n\n    /// @inheritdoc IAccessControlDefaultAdminRules\n    function pendingDefaultAdminDelay() public view virtual returns (uint48 newDelay, uint48 schedule) {\n        schedule = _pendingDelaySchedule;\n        return (_isScheduleSet(schedule) && !_hasSchedulePassed(schedule)) ? (_pendingDelay, schedule) : (0, 0);\n    }\n\n    /// @inheritdoc IAccessControlDefaultAdminRules\n    function defaultAdminDelayIncreaseWait() public view virtual returns (uint48) {\n        return 5 days;\n    }\n\n    ///\n    /// AccessControlDefaultAdminRules public and internal setters for defaultAdmin/pendingDefaultAdmin\n    ///\n\n    /// @inheritdoc IAccessControlDefaultAdminRules\n    function beginDefaultAdminTransfer(address newAdmin) public virtual onlyRole(DEFAULT_ADMIN_ROLE) {\n        _beginDefaultAdminTransfer(newAdmin);\n    }\n\n    /**\n     * @dev See {beginDefaultAdminTransfer}.\n     *\n     * Internal function without access restriction.\n     */\n    function _beginDefaultAdminTransfer(address newAdmin) internal virtual {\n        uint48 newSchedule = SafeCast.toUint48(block.timestamp) + defaultAdminDelay();\n        _setPendingDefaultAdmin(newAdmin, newSchedule);\n        emit DefaultAdminTransferScheduled(newAdmin, newSchedule);\n    }\n\n    /// @inheritdoc IAccessControlDefaultAdminRules\n    function cancelDefaultAdminTransfer() public virtual onlyRole(DEFAULT_ADMIN_ROLE) {\n        _cancelDefaultAdminTransfer();\n    }\n\n    /**\n     * @dev See {cancelDefaultAdminTransfer}.\n     *\n     * Internal function without access restriction.\n     */\n    function _cancelDefaultAdminTransfer() internal virtual {\n        _setPendingDefaultAdmin(address(0), 0);\n    }\n\n    /// @inheritdoc IAccessControlDefaultAdminRules\n    function acceptDefaultAdminTransfer() public virtual {\n        (address newDefaultAdmin, ) = pendingDefaultAdmin();\n        if (_msgSender() != newDefaultAdmin) {\n            // Enforce newDefaultAdmin explicit acceptance.\n            revert AccessControlInvalidDefaultAdmin(_msgSender());\n        }\n        _acceptDefaultAdminTransfer();\n    }\n\n    /**\n     * @dev See {acceptDefaultAdminTransfer}.\n     *\n     * Internal function without access restriction.\n     */\n    function _acceptDefaultAdminTransfer() internal virtual {\n        (address newAdmin, uint48 schedule) = pendingDefaultAdmin();\n        if (!_isScheduleSet(schedule) || !_hasSchedulePassed(schedule)) {\n            revert AccessControlEnforcedDefaultAdminDelay(schedule);\n        }\n        _revokeRole(DEFAULT_ADMIN_ROLE, defaultAdmin());\n        _grantRole(DEFAULT_ADMIN_ROLE, newAdmin);\n        delete _pendingDefaultAdmin;\n        delete _pendingDefaultAdminSchedule;\n    }\n\n    ///\n    /// AccessControlDefaultAdminRules public and internal setters for defaultAdminDelay/pendingDefaultAdminDelay\n    ///\n\n    /// @inheritdoc IAccessControlDefaultAdminRules\n    function changeDefaultAdminDelay(uint48 newDelay) public virtual onlyRole(DEFAULT_ADMIN_ROLE) {\n        _changeDefaultAdminDelay(newDelay);\n    }\n\n    /**\n     * @dev See {changeDefaultAdminDelay}.\n     *\n     * Internal function without access restriction.\n     */\n    function _changeDefaultAdminDelay(uint48 newDelay) internal virtual {\n        uint48 newSchedule = SafeCast.toUint48(block.timestamp) + _delayChangeWait(newDelay);\n        _setPendingDelay(newDelay, newSchedule);\n        emit DefaultAdminDelayChangeScheduled(newDelay, newSchedule);\n    }\n\n    /// @inheritdoc IAccessControlDefaultAdminRules\n    function rollbackDefaultAdminDelay() public virtual onlyRole(DEFAULT_ADMIN_ROLE) {\n        _rollbackDefaultAdminDelay();\n    }\n\n    /**\n     * @dev See {rollbackDefaultAdminDelay}.\n     *\n     * Internal function without access restriction.\n     */\n    function _rollbackDefaultAdminDelay() internal virtual {\n        _setPendingDelay(0, 0);\n    }\n\n    /**\n     * @dev Returns the amount of seconds to wait after the `newDelay` will\n     * become the new {defaultAdminDelay}.\n     *\n     * The value returned guarantees that if the delay is reduced, it will go into effect\n     * after a wait that honors the previously set delay.\n     *\n     * See {defaultAdminDelayIncreaseWait}.\n     */\n    function _delayChangeWait(uint48 newDelay) internal view virtual returns (uint48) {\n        uint48 currentDelay = defaultAdminDelay();\n\n        // When increasing the delay, we schedule the delay change to occur after a period of \"new delay\" has passed, up\n        // to a maximum given by defaultAdminDelayIncreaseWait, by default 5 days. For example, if increasing from 1 day\n        // to 3 days, the new delay will come into effect after 3 days. If increasing from 1 day to 10 days, the new\n        // delay will come into effect after 5 days. The 5 day wait period is intended to be able to fix an error like\n        // using milliseconds instead of seconds.\n        //\n        // When decreasing the delay, we wait the difference between \"current delay\" and \"new delay\". This guarantees\n        // that an admin transfer cannot be made faster than \"current delay\" at the time the delay change is scheduled.\n        // For example, if decreasing from 10 days to 3 days, the new delay will come into effect after 7 days.\n        return\n            newDelay > currentDelay\n                ? uint48(Math.min(newDelay, defaultAdminDelayIncreaseWait())) // no need to safecast, both inputs are uint48\n                : currentDelay - newDelay;\n    }\n\n    ///\n    /// Private setters\n    ///\n\n    /**\n     * @dev Setter of the tuple for pending admin and its schedule.\n     *\n     * May emit a DefaultAdminTransferCanceled event.\n     */\n    function _setPendingDefaultAdmin(address newAdmin, uint48 newSchedule) private {\n        (, uint48 oldSchedule) = pendingDefaultAdmin();\n\n        _pendingDefaultAdmin = newAdmin;\n        _pendingDefaultAdminSchedule = newSchedule;\n\n        // An `oldSchedule` from `pendingDefaultAdmin()` is only set if it hasn't been accepted.\n        if (_isScheduleSet(oldSchedule)) {\n            // Emit for implicit cancellations when another default admin was scheduled.\n            emit DefaultAdminTransferCanceled();\n        }\n    }\n\n    /**\n     * @dev Setter of the tuple for pending delay and its schedule.\n     *\n     * May emit a DefaultAdminDelayChangeCanceled event.\n     */\n    function _setPendingDelay(uint48 newDelay, uint48 newSchedule) private {\n        uint48 oldSchedule = _pendingDelaySchedule;\n\n        if (_isScheduleSet(oldSchedule)) {\n            if (_hasSchedulePassed(oldSchedule)) {\n                // Materialize a virtual delay\n                _currentDelay = _pendingDelay;\n            } else {\n                // Emit for implicit cancellations when another delay was scheduled.\n                emit DefaultAdminDelayChangeCanceled();\n            }\n        }\n\n        _pendingDelay = newDelay;\n        _pendingDelaySchedule = newSchedule;\n    }\n\n    ///\n    /// Private helpers\n    ///\n\n    /**\n     * @dev Defines if an `schedule` is considered set. For consistency purposes.\n     */\n    function _isScheduleSet(uint48 schedule) private pure returns (bool) {\n        return schedule != 0;\n    }\n\n    /**\n     * @dev Defines if an `schedule` is considered passed. For consistency purposes.\n     */\n    function _hasSchedulePassed(uint48 schedule) private view returns (bool) {\n        return schedule < block.timestamp;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/access/extensions/IAccessControlDefaultAdminRules.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/extensions/IAccessControlDefaultAdminRules.sol)\n\npragma solidity >=0.8.4;\n\nimport {IAccessControl} from \"../IAccessControl.sol\";\n\n/**\n * @dev External interface of AccessControlDefaultAdminRules declared to support ERC-165 detection.\n */\ninterface IAccessControlDefaultAdminRules is IAccessControl {\n    /**\n     * @dev The new default admin is not a valid default admin.\n     */\n    error AccessControlInvalidDefaultAdmin(address defaultAdmin);\n\n    /**\n     * @dev At least one of the following rules was violated:\n     *\n     * - The `DEFAULT_ADMIN_ROLE` must only be managed by itself.\n     * - The `DEFAULT_ADMIN_ROLE` must only be held by one account at the time.\n     * - Any `DEFAULT_ADMIN_ROLE` transfer must be in two delayed steps.\n     */\n    error AccessControlEnforcedDefaultAdminRules();\n\n    /**\n     * @dev The delay for transferring the default admin delay is enforced and\n     * the operation must wait until `schedule`.\n     *\n     * NOTE: `schedule` can be 0 indicating there's no transfer scheduled.\n     */\n    error AccessControlEnforcedDefaultAdminDelay(uint48 schedule);\n\n    /**\n     * @dev Emitted when a {defaultAdmin} transfer is started, setting `newAdmin` as the next\n     * address to become the {defaultAdmin} by calling {acceptDefaultAdminTransfer} only after `acceptSchedule`\n     * passes.\n     */\n    event DefaultAdminTransferScheduled(address indexed newAdmin, uint48 acceptSchedule);\n\n    /**\n     * @dev Emitted when a {pendingDefaultAdmin} is reset if it was never accepted, regardless of its schedule.\n     */\n    event DefaultAdminTransferCanceled();\n\n    /**\n     * @dev Emitted when a {defaultAdminDelay} change is started, setting `newDelay` as the next\n     * delay to be applied between default admin transfer after `effectSchedule` has passed.\n     */\n    event DefaultAdminDelayChangeScheduled(uint48 newDelay, uint48 effectSchedule);\n\n    /**\n     * @dev Emitted when a {pendingDefaultAdminDelay} is reset if its schedule didn't pass.\n     */\n    event DefaultAdminDelayChangeCanceled();\n\n    /**\n     * @dev Returns the address of the current `DEFAULT_ADMIN_ROLE` holder.\n     */\n    function defaultAdmin() external view returns (address);\n\n    /**\n     * @dev Returns a tuple of a `newAdmin` and an accept schedule.\n     *\n     * After the `schedule` passes, the `newAdmin` will be able to accept the {defaultAdmin} role\n     * by calling {acceptDefaultAdminTransfer}, completing the role transfer.\n     *\n     * A zero value only in `acceptSchedule` indicates no pending admin transfer.\n     *\n     * NOTE: A zero address `newAdmin` means that {defaultAdmin} is being renounced.\n     */\n    function pendingDefaultAdmin() external view returns (address newAdmin, uint48 acceptSchedule);\n\n    /**\n     * @dev Returns the delay required to schedule the acceptance of a {defaultAdmin} transfer started.\n     *\n     * This delay will be added to the current timestamp when calling {beginDefaultAdminTransfer} to set\n     * the acceptance schedule.\n     *\n     * NOTE: If a delay change has been scheduled, it will take effect as soon as the schedule passes, making this\n     * function returns the new delay. See {changeDefaultAdminDelay}.\n     */\n    function defaultAdminDelay() external view returns (uint48);\n\n    /**\n     * @dev Returns a tuple of `newDelay` and an effect schedule.\n     *\n     * After the `schedule` passes, the `newDelay` will get into effect immediately for every\n     * new {defaultAdmin} transfer started with {beginDefaultAdminTransfer}.\n     *\n     * A zero value only in `effectSchedule` indicates no pending delay change.\n     *\n     * NOTE: A zero value only for `newDelay` means that the next {defaultAdminDelay}\n     * will be zero after the effect schedule.\n     */\n    function pendingDefaultAdminDelay() external view returns (uint48 newDelay, uint48 effectSchedule);\n\n    /**\n     * @dev Starts a {defaultAdmin} transfer by setting a {pendingDefaultAdmin} scheduled for acceptance\n     * after the current timestamp plus a {defaultAdminDelay}.\n     *\n     * Requirements:\n     *\n     * - Only can be called by the current {defaultAdmin}.\n     *\n     * Emits a DefaultAdminRoleChangeStarted event.\n     */\n    function beginDefaultAdminTransfer(address newAdmin) external;\n\n    /**\n     * @dev Cancels a {defaultAdmin} transfer previously started with {beginDefaultAdminTransfer}.\n     *\n     * A {pendingDefaultAdmin} not yet accepted can also be cancelled with this function.\n     *\n     * Requirements:\n     *\n     * - Only can be called by the current {defaultAdmin}.\n     *\n     * May emit a DefaultAdminTransferCanceled event.\n     */\n    function cancelDefaultAdminTransfer() external;\n\n    /**\n     * @dev Completes a {defaultAdmin} transfer previously started with {beginDefaultAdminTransfer}.\n     *\n     * After calling the function:\n     *\n     * - `DEFAULT_ADMIN_ROLE` should be granted to the caller.\n     * - `DEFAULT_ADMIN_ROLE` should be revoked from the previous holder.\n     * - {pendingDefaultAdmin} should be reset to zero values.\n     *\n     * Requirements:\n     *\n     * - Only can be called by the {pendingDefaultAdmin}'s `newAdmin`.\n     * - The {pendingDefaultAdmin}'s `acceptSchedule` should've passed.\n     */\n    function acceptDefaultAdminTransfer() external;\n\n    /**\n     * @dev Initiates a {defaultAdminDelay} update by setting a {pendingDefaultAdminDelay} scheduled for getting\n     * into effect after the current timestamp plus a {defaultAdminDelay}.\n     *\n     * This function guarantees that any call to {beginDefaultAdminTransfer} done between the timestamp this\n     * method is called and the {pendingDefaultAdminDelay} effect schedule will use the current {defaultAdminDelay}\n     * set before calling.\n     *\n     * The {pendingDefaultAdminDelay}'s effect schedule is defined in a way that waiting until the schedule and then\n     * calling {beginDefaultAdminTransfer} with the new delay will take at least the same as another {defaultAdmin}\n     * complete transfer (including acceptance).\n     *\n     * The schedule is designed for two scenarios:\n     *\n     * - When the delay is changed for a larger one the schedule is `block.timestamp + newDelay` capped by\n     * {defaultAdminDelayIncreaseWait}.\n     * - When the delay is changed for a shorter one, the schedule is `block.timestamp + (current delay - new delay)`.\n     *\n     * A {pendingDefaultAdminDelay} that never got into effect will be canceled in favor of a new scheduled change.\n     *\n     * Requirements:\n     *\n     * - Only can be called by the current {defaultAdmin}.\n     *\n     * Emits a DefaultAdminDelayChangeScheduled event and may emit a DefaultAdminDelayChangeCanceled event.\n     */\n    function changeDefaultAdminDelay(uint48 newDelay) external;\n\n    /**\n     * @dev Cancels a scheduled {defaultAdminDelay} change.\n     *\n     * Requirements:\n     *\n     * - Only can be called by the current {defaultAdmin}.\n     *\n     * May emit a DefaultAdminDelayChangeCanceled event.\n     */\n    function rollbackDefaultAdminDelay() external;\n\n    /**\n     * @dev Maximum time in seconds for an increase to {defaultAdminDelay} (that is scheduled using {changeDefaultAdminDelay})\n     * to take effect. Default to 5 days.\n     *\n     * When the {defaultAdminDelay} is scheduled to be increased, it goes into effect after the new delay has passed with\n     * the purpose of giving enough time for reverting any accidental change (i.e. using milliseconds instead of seconds)\n     * that may lock the contract. However, to avoid excessive schedules, the wait is capped by this function and it can\n     * be overrode for a custom {defaultAdminDelay} increase scheduling.\n     *\n     * IMPORTANT: Make sure to add a reasonable amount of time while overriding this value, otherwise,\n     * there's a risk of setting a high new delay that goes into effect almost immediately without the\n     * possibility of human intervention in the case of an input error (eg. set milliseconds instead of seconds).\n     */\n    function defaultAdminDelayIncreaseWait() external view returns (uint48);\n}\n"},{"file_path":"@openzeppelin/contracts/interfaces/IERC1271.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1271.sol)\n\npragma solidity >=0.5.0;\n\n/**\n * @dev Interface of the ERC-1271 standard signature validation method for\n * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].\n */\ninterface IERC1271 {\n    /**\n     * @dev Should return whether the signature provided is valid for the provided data\n     * @param hash      Hash of the data to be signed\n     * @param signature Signature byte array associated with `hash`\n     */\n    function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4 magicValue);\n}\n"},{"file_path":"@openzeppelin/contracts/interfaces/IERC1363.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @title IERC1363\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\n *\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\n */\ninterface IERC1363 is IERC20, IERC165 {\n    /*\n     * Note: the ERC-165 identifier for this interface is 0xb0202a11.\n     * 0xb0202a11 ===\n     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\n     */\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @param data Additional data with no specified format, sent in call to `spender`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\n}\n"},{"file_path":"@openzeppelin/contracts/interfaces/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC165} from \"../utils/introspection/IERC165.sol\";\n"},{"file_path":"@openzeppelin/contracts/interfaces/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\n"},{"file_path":"@openzeppelin/contracts/interfaces/IERC5313.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC5313.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface for the Light Contract Ownership Standard.\n *\n * A standardized minimal interface required to identify an account that controls a contract\n */\ninterface IERC5313 {\n    /**\n     * @dev Gets the address of the owner.\n     */\n    function owner() external view returns (address);\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC1363} from \"../../../interfaces/IERC1363.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    /**\n     * @dev An operation with an ERC-20 token failed.\n     */\n    error SafeERC20FailedOperation(address token);\n\n    /**\n     * @dev Indicates a failed `decreaseAllowance` request.\n     */\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n    }\n\n    /**\n     * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\n     */\n    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\n        return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));\n    }\n\n    /**\n     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\n     */\n    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\n        return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     *\n     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n     * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        forceApprove(token, spender, oldAllowance + value);\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n     * value, non-reverting calls are assumed to be successful.\n     *\n     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n     * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n        unchecked {\n            uint256 currentAllowance = token.allowance(address(this), spender);\n            if (currentAllowance < requestedDecrease) {\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n            }\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     *\n     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\n     * only sets the \"standard\" allowance. Any temporary allowance will remain active, in addition to the value being\n     * set here.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            safeTransfer(token, to, value);\n        } else if (!token.transferAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\n     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferFromAndCallRelaxed(\n        IERC1363 token,\n        address from,\n        address to,\n        uint256 value,\n        bytes memory data\n    ) internal {\n        if (to.code.length == 0) {\n            safeTransferFrom(token, from, to, value);\n        } else if (!token.transferFromAndCall(from, to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\n     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\n     * once without retrying, and relies on the returned value to be true.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            forceApprove(token, to, value);\n        } else if (!token.approveAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        uint256 returnSize;\n        uint256 returnValue;\n        assembly (\"memory-safe\") {\n            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\n            // bubble errors\n            if iszero(success) {\n                let ptr := mload(0x40)\n                returndatacopy(ptr, 0, returndatasize())\n                revert(ptr, returndatasize())\n            }\n            returnSize := returndatasize()\n            returnValue := mload(0)\n        }\n\n        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        bool success;\n        uint256 returnSize;\n        uint256 returnValue;\n        assembly (\"memory-safe\") {\n            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\n            returnSize := returndatasize()\n            returnValue := mload(0)\n        }\n        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Arrays.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/Arrays.sol)\n// This file was procedurally generated from scripts/generate/templates/Arrays.js.\n\npragma solidity ^0.8.20;\n\nimport {Comparators} from \"./Comparators.sol\";\nimport {SlotDerivation} from \"./SlotDerivation.sol\";\nimport {StorageSlot} from \"./StorageSlot.sol\";\nimport {Math} from \"./math/Math.sol\";\n\n/**\n * @dev Collection of functions related to array types.\n */\nlibrary Arrays {\n    using SlotDerivation for bytes32;\n    using StorageSlot for bytes32;\n\n    /**\n     * @dev Sort an array of uint256 (in memory) following the provided comparator function.\n     *\n     * This function does the sorting \"in place\", meaning that it overrides the input. The object is returned for\n     * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\n     *\n     * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the\n     * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\n     * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\n     * consume more gas than is available in a block, leading to potential DoS.\n     *\n     * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\n     */\n    function sort(\n        uint256[] memory array,\n        function(uint256, uint256) pure returns (bool) comp\n    ) internal pure returns (uint256[] memory) {\n        _quickSort(_begin(array), _end(array), comp);\n        return array;\n    }\n\n    /**\n     * @dev Variant of {sort} that sorts an array of uint256 in increasing order.\n     */\n    function sort(uint256[] memory array) internal pure returns (uint256[] memory) {\n        sort(array, Comparators.lt);\n        return array;\n    }\n\n    /**\n     * @dev Sort an array of address (in memory) following the provided comparator function.\n     *\n     * This function does the sorting \"in place\", meaning that it overrides the input. The object is returned for\n     * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\n     *\n     * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the\n     * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\n     * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\n     * consume more gas than is available in a block, leading to potential DoS.\n     *\n     * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\n     */\n    function sort(\n        address[] memory array,\n        function(address, address) pure returns (bool) comp\n    ) internal pure returns (address[] memory) {\n        sort(_castToUint256Array(array), _castToUint256Comp(comp));\n        return array;\n    }\n\n    /**\n     * @dev Variant of {sort} that sorts an array of address in increasing order.\n     */\n    function sort(address[] memory array) internal pure returns (address[] memory) {\n        sort(_castToUint256Array(array), Comparators.lt);\n        return array;\n    }\n\n    /**\n     * @dev Sort an array of bytes32 (in memory) following the provided comparator function.\n     *\n     * This function does the sorting \"in place\", meaning that it overrides the input. The object is returned for\n     * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\n     *\n     * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the\n     * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\n     * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\n     * consume more gas than is available in a block, leading to potential DoS.\n     *\n     * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\n     */\n    function sort(\n        bytes32[] memory array,\n        function(bytes32, bytes32) pure returns (bool) comp\n    ) internal pure returns (bytes32[] memory) {\n        sort(_castToUint256Array(array), _castToUint256Comp(comp));\n        return array;\n    }\n\n    /**\n     * @dev Variant of {sort} that sorts an array of bytes32 in increasing order.\n     */\n    function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) {\n        sort(_castToUint256Array(array), Comparators.lt);\n        return array;\n    }\n\n    /**\n     * @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops\n     * at end (exclusive). Sorting follows the `comp` comparator.\n     *\n     * Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls.\n     *\n     * IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should\n     * be used only if the limits are within a memory array.\n     */\n    function _quickSort(uint256 begin, uint256 end, function(uint256, uint256) pure returns (bool) comp) private pure {\n        unchecked {\n            if (end - begin < 0x40) return;\n\n            // Use first element as pivot\n            uint256 pivot = _mload(begin);\n            // Position where the pivot should be at the end of the loop\n            uint256 pos = begin;\n\n            for (uint256 it = begin + 0x20; it < end; it += 0x20) {\n                if (comp(_mload(it), pivot)) {\n                    // If the value stored at the iterator's position comes before the pivot, we increment the\n                    // position of the pivot and move the value there.\n                    pos += 0x20;\n                    _swap(pos, it);\n                }\n            }\n\n            _swap(begin, pos); // Swap pivot into place\n            _quickSort(begin, pos, comp); // Sort the left side of the pivot\n            _quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot\n        }\n    }\n\n    /**\n     * @dev Pointer to the memory location of the first element of `array`.\n     */\n    function _begin(uint256[] memory array) private pure returns (uint256 ptr) {\n        assembly (\"memory-safe\") {\n            ptr := add(array, 0x20)\n        }\n    }\n\n    /**\n     * @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word\n     * that comes just after the last element of the array.\n     */\n    function _end(uint256[] memory array) private pure returns (uint256 ptr) {\n        unchecked {\n            return _begin(array) + array.length * 0x20;\n        }\n    }\n\n    /**\n     * @dev Load memory word (as a uint256) at location `ptr`.\n     */\n    function _mload(uint256 ptr) private pure returns (uint256 value) {\n        assembly {\n            value := mload(ptr)\n        }\n    }\n\n    /**\n     * @dev Swaps the elements memory location `ptr1` and `ptr2`.\n     */\n    function _swap(uint256 ptr1, uint256 ptr2) private pure {\n        assembly {\n            let value1 := mload(ptr1)\n            let value2 := mload(ptr2)\n            mstore(ptr1, value2)\n            mstore(ptr2, value1)\n        }\n    }\n\n    /// @dev Helper: low level cast address memory array to uint256 memory array\n    function _castToUint256Array(address[] memory input) private pure returns (uint256[] memory output) {\n        assembly {\n            output := input\n        }\n    }\n\n    /// @dev Helper: low level cast bytes32 memory array to uint256 memory array\n    function _castToUint256Array(bytes32[] memory input) private pure returns (uint256[] memory output) {\n        assembly {\n            output := input\n        }\n    }\n\n    /// @dev Helper: low level cast address comp function to uint256 comp function\n    function _castToUint256Comp(\n        function(address, address) pure returns (bool) input\n    ) private pure returns (function(uint256, uint256) pure returns (bool) output) {\n        assembly {\n            output := input\n        }\n    }\n\n    /// @dev Helper: low level cast bytes32 comp function to uint256 comp function\n    function _castToUint256Comp(\n        function(bytes32, bytes32) pure returns (bool) input\n    ) private pure returns (function(uint256, uint256) pure returns (bool) output) {\n        assembly {\n            output := input\n        }\n    }\n\n    /**\n     * @dev Searches a sorted `array` and returns the first index that contains\n     * a value greater or equal to `element`. If no such index exists (i.e. all\n     * values in the array are strictly less than `element`), the array length is\n     * returned. Time complexity O(log n).\n     *\n     * NOTE: The `array` is expected to be sorted in ascending order, and to\n     * contain no repeated elements.\n     *\n     * IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks\n     * support for repeated elements in the array. The {lowerBound} function should\n     * be used instead.\n     */\n    function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\n        uint256 low = 0;\n        uint256 high = array.length;\n\n        if (high == 0) {\n            return 0;\n        }\n\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n\n            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\n            // because Math.average rounds towards zero (it does integer division with truncation).\n            if (unsafeAccess(array, mid).value > element) {\n                high = mid;\n            } else {\n                low = mid + 1;\n            }\n        }\n\n        // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.\n        if (low > 0 && unsafeAccess(array, low - 1).value == element) {\n            return low - 1;\n        } else {\n            return low;\n        }\n    }\n\n    /**\n     * @dev Searches an `array` sorted in ascending order and returns the first\n     * index that contains a value greater or equal than `element`. If no such index\n     * exists (i.e. all values in the array are strictly less than `element`), the array\n     * length is returned. Time complexity O(log n).\n     *\n     * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound].\n     */\n    function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\n        uint256 low = 0;\n        uint256 high = array.length;\n\n        if (high == 0) {\n            return 0;\n        }\n\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n\n            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\n            // because Math.average rounds towards zero (it does integer division with truncation).\n            if (unsafeAccess(array, mid).value < element) {\n                // this cannot overflow because mid < high\n                unchecked {\n                    low = mid + 1;\n                }\n            } else {\n                high = mid;\n            }\n        }\n\n        return low;\n    }\n\n    /**\n     * @dev Searches an `array` sorted in ascending order and returns the first\n     * index that contains a value strictly greater than `element`. If no such index\n     * exists (i.e. all values in the array are strictly less than `element`), the array\n     * length is returned. Time complexity O(log n).\n     *\n     * See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound].\n     */\n    function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\n        uint256 low = 0;\n        uint256 high = array.length;\n\n        if (high == 0) {\n            return 0;\n        }\n\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n\n            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\n            // because Math.average rounds towards zero (it does integer division with truncation).\n            if (unsafeAccess(array, mid).value > element) {\n                high = mid;\n            } else {\n                // this cannot overflow because mid < high\n                unchecked {\n                    low = mid + 1;\n                }\n            }\n        }\n\n        return low;\n    }\n\n    /**\n     * @dev Same as {lowerBound}, but with an array in memory.\n     */\n    function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {\n        uint256 low = 0;\n        uint256 high = array.length;\n\n        if (high == 0) {\n            return 0;\n        }\n\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n\n            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\n            // because Math.average rounds towards zero (it does integer division with truncation).\n            if (unsafeMemoryAccess(array, mid) < element) {\n                // this cannot overflow because mid < high\n                unchecked {\n                    low = mid + 1;\n                }\n            } else {\n                high = mid;\n            }\n        }\n\n        return low;\n    }\n\n    /**\n     * @dev Same as {upperBound}, but with an array in memory.\n     */\n    function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {\n        uint256 low = 0;\n        uint256 high = array.length;\n\n        if (high == 0) {\n            return 0;\n        }\n\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n\n            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\n            // because Math.average rounds towards zero (it does integer division with truncation).\n            if (unsafeMemoryAccess(array, mid) > element) {\n                high = mid;\n            } else {\n                // this cannot overflow because mid < high\n                unchecked {\n                    low = mid + 1;\n                }\n            }\n        }\n\n        return low;\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {\n        bytes32 slot;\n        assembly (\"memory-safe\") {\n            slot := arr.slot\n        }\n        return slot.deriveArray().offset(pos).getAddressSlot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {\n        bytes32 slot;\n        assembly (\"memory-safe\") {\n            slot := arr.slot\n        }\n        return slot.deriveArray().offset(pos).getBytes32Slot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {\n        bytes32 slot;\n        assembly (\"memory-safe\") {\n            slot := arr.slot\n        }\n        return slot.deriveArray().offset(pos).getUint256Slot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(bytes[] storage arr, uint256 pos) internal pure returns (StorageSlot.BytesSlot storage) {\n        bytes32 slot;\n        assembly (\"memory-safe\") {\n            slot := arr.slot\n        }\n        return slot.deriveArray().offset(pos).getBytesSlot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(string[] storage arr, uint256 pos) internal pure returns (StorageSlot.StringSlot storage) {\n        bytes32 slot;\n        assembly (\"memory-safe\") {\n            slot := arr.slot\n        }\n        return slot.deriveArray().offset(pos).getStringSlot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {\n        assembly {\n            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\n        }\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) {\n        assembly {\n            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\n        }\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {\n        assembly {\n            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\n        }\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeMemoryAccess(bytes[] memory arr, uint256 pos) internal pure returns (bytes memory res) {\n        assembly {\n            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\n        }\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeMemoryAccess(string[] memory arr, uint256 pos) internal pure returns (string memory res) {\n        assembly {\n            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\n        }\n    }\n\n    /**\n     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\n     *\n     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\n     */\n    function unsafeSetLength(address[] storage array, uint256 len) internal {\n        assembly (\"memory-safe\") {\n            sstore(array.slot, len)\n        }\n    }\n\n    /**\n     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\n     *\n     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\n     */\n    function unsafeSetLength(bytes32[] storage array, uint256 len) internal {\n        assembly (\"memory-safe\") {\n            sstore(array.slot, len)\n        }\n    }\n\n    /**\n     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\n     *\n     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\n     */\n    function unsafeSetLength(uint256[] storage array, uint256 len) internal {\n        assembly (\"memory-safe\") {\n            sstore(array.slot, len)\n        }\n    }\n\n    /**\n     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\n     *\n     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\n     */\n    function unsafeSetLength(bytes[] storage array, uint256 len) internal {\n        assembly (\"memory-safe\") {\n            sstore(array.slot, len)\n        }\n    }\n\n    /**\n     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\n     *\n     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\n     */\n    function unsafeSetLength(string[] storage array, uint256 len) internal {\n        assembly (\"memory-safe\") {\n            sstore(array.slot, len)\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Panic.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Helper library for emitting standardized panic codes.\n *\n * ```solidity\n * contract Example {\n *      using Panic for uint256;\n *\n *      // Use any of the declared internal constants\n *      function foo() { Panic.GENERIC.panic(); }\n *\n *      // Alternatively\n *      function foo() { Panic.panic(Panic.GENERIC); }\n * }\n * ```\n *\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\n *\n * _Available since v5.1._\n */\n// slither-disable-next-line unused-state\nlibrary Panic {\n    /// @dev generic / unspecified error\n    uint256 internal constant GENERIC = 0x00;\n    /// @dev used by the assert() builtin\n    uint256 internal constant ASSERT = 0x01;\n    /// @dev arithmetic underflow or overflow\n    uint256 internal constant UNDER_OVERFLOW = 0x11;\n    /// @dev division or modulo by zero\n    uint256 internal constant DIVISION_BY_ZERO = 0x12;\n    /// @dev enum conversion error\n    uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\n    /// @dev invalid encoding in storage\n    uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\n    /// @dev empty array pop\n    uint256 internal constant EMPTY_ARRAY_POP = 0x31;\n    /// @dev array out of bounds access\n    uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\n    /// @dev resource error (too large allocation or too large array)\n    uint256 internal constant RESOURCE_ERROR = 0x41;\n    /// @dev calling invalid internal function\n    uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\n\n    /// @dev Reverts with a panic code. Recommended to use with\n    /// the internal constants with predefined codes.\n    function panic(uint256 code) internal pure {\n        assembly (\"memory-safe\") {\n            mstore(0x00, 0x4e487b71)\n            mstore(0x20, code)\n            revert(0x1c, 0x24)\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Pausable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n    bool private _paused;\n\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    /**\n     * @dev The operation failed because the contract is paused.\n     */\n    error EnforcedPause();\n\n    /**\n     * @dev The operation failed because the contract is not paused.\n     */\n    error ExpectedPause();\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        if (paused()) {\n            revert EnforcedPause();\n        }\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        if (!paused()) {\n            revert ExpectedPause();\n        }\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/ReentrancyGuard.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,\n * consider using {ReentrancyGuardTransient} instead.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant NOT_ENTERED = 1;\n    uint256 private constant ENTERED = 2;\n\n    uint256 private _status;\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    constructor() {\n        _status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        if (_status == ENTERED) {\n            revert ReentrancyGuardReentrantCall();\n        }\n\n        // Any calls to nonReentrant after this point will fail\n        _status = ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == ENTERED;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/SlotDerivation.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/SlotDerivation.sol)\n// This file was procedurally generated from scripts/generate/templates/SlotDerivation.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots\n * corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by\n * the solidity language / compiler.\n *\n * See https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays[Solidity docs for mappings and dynamic arrays.].\n *\n * Example usage:\n * ```solidity\n * contract Example {\n *     // Add the library methods\n *     using StorageSlot for bytes32;\n *     using SlotDerivation for bytes32;\n *\n *     // Declare a namespace\n *     string private constant _NAMESPACE = \"<namespace>\"; // eg. OpenZeppelin.Slot\n *\n *     function setValueInNamespace(uint256 key, address newValue) internal {\n *         _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;\n *     }\n *\n *     function getValueInNamespace(uint256 key) internal view returns (address) {\n *         return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value;\n *     }\n * }\n * ```\n *\n * TIP: Consider using this library along with {StorageSlot}.\n *\n * NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking\n * upgrade safety will ignore the slots accessed through this library.\n *\n * _Available since v5.1._\n */\nlibrary SlotDerivation {\n    /**\n     * @dev Derive an ERC-7201 slot from a string (namespace).\n     */\n    function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1))\n            slot := and(keccak256(0x00, 0x20), not(0xff))\n        }\n    }\n\n    /**\n     * @dev Add an offset to a slot to get the n-th element of a structure or an array.\n     */\n    function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) {\n        unchecked {\n            return bytes32(uint256(slot) + pos);\n        }\n    }\n\n    /**\n     * @dev Derive the location of the first element in an array from the slot where the length is stored.\n     */\n    function deriveArray(bytes32 slot) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, slot)\n            result := keccak256(0x00, 0x20)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, and(key, shr(96, not(0))))\n            mstore(0x20, slot)\n            result := keccak256(0x00, 0x40)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, iszero(iszero(key)))\n            mstore(0x20, slot)\n            result := keccak256(0x00, 0x40)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, key)\n            mstore(0x20, slot)\n            result := keccak256(0x00, 0x40)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, key)\n            mstore(0x20, slot)\n            result := keccak256(0x00, 0x40)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, key)\n            mstore(0x20, slot)\n            result := keccak256(0x00, 0x40)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            let length := mload(key)\n            let begin := add(key, 0x20)\n            let end := add(begin, length)\n            let cache := mload(end)\n            mstore(end, slot)\n            result := keccak256(begin, add(length, 0x20))\n            mstore(end, cache)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            let length := mload(key)\n            let begin := add(key, 0x20)\n            let end := add(begin, length)\n            let cache := mload(end)\n            mstore(end, slot)\n            result := keccak256(begin, add(length, 0x20))\n            mstore(end, cache)\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/StorageSlot.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC-1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n *     function _getImplementation() internal view returns (address) {\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n *     }\n *\n *     function _setImplementation(address newImplementation) internal {\n *         require(newImplementation.code.length > 0);\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary StorageSlot {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct BooleanSlot {\n        bool value;\n    }\n\n    struct Bytes32Slot {\n        bytes32 value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    struct Int256Slot {\n        int256 value;\n    }\n\n    struct StringSlot {\n        string value;\n    }\n\n    struct BytesSlot {\n        bytes value;\n    }\n\n    /**\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n     */\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Int256Slot` with member `value` located at `slot`.\n     */\n    function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `StringSlot` with member `value` located at `slot`.\n     */\n    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n     */\n    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BytesSlot` with member `value` located at `slot`.\n     */\n    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n     */\n    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Strings.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/Strings.sol)\n\npragma solidity ^0.8.20;\n\nimport {Math} from \"./math/Math.sol\";\nimport {SafeCast} from \"./math/SafeCast.sol\";\nimport {SignedMath} from \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    using SafeCast for *;\n\n    bytes16 private constant HEX_DIGITS = \"0123456789abcdef\";\n    uint8 private constant ADDRESS_LENGTH = 20;\n    uint256 private constant SPECIAL_CHARS_LOOKUP =\n        (1 << 0x08) | // backspace\n            (1 << 0x09) | // tab\n            (1 << 0x0a) | // newline\n            (1 << 0x0c) | // form feed\n            (1 << 0x0d) | // carriage return\n            (1 << 0x22) | // double quote\n            (1 << 0x5c); // backslash\n\n    /**\n     * @dev The `value` string doesn't fit in the specified `length`.\n     */\n    error StringsInsufficientHexLength(uint256 value, uint256 length);\n\n    /**\n     * @dev The string being parsed contains characters that are not in scope of the given base.\n     */\n    error StringsInvalidChar();\n\n    /**\n     * @dev The string being parsed is not a properly formatted address.\n     */\n    error StringsInvalidAddressFormat();\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            assembly (\"memory-safe\") {\n                ptr := add(add(buffer, 0x20), length)\n            }\n            while (true) {\n                ptr--;\n                assembly (\"memory-safe\") {\n                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\n     */\n    function toStringSigned(int256 value) internal pure returns (string memory) {\n        return string.concat(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value)));\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        uint256 localValue = value;\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = HEX_DIGITS[localValue & 0xf];\n            localValue >>= 4;\n        }\n        if (localValue != 0) {\n            revert StringsInsufficientHexLength(value, length);\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal\n     * representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal\n     * representation, according to EIP-55.\n     */\n    function toChecksumHexString(address addr) internal pure returns (string memory) {\n        bytes memory buffer = bytes(toHexString(addr));\n\n        // hash the hex part of buffer (skip length + 2 bytes, length 40)\n        uint256 hashValue;\n        assembly (\"memory-safe\") {\n            hashValue := shr(96, keccak256(add(buffer, 0x22), 40))\n        }\n\n        for (uint256 i = 41; i > 1; --i) {\n            // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)\n            if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {\n                // case shift by xoring with 0x20\n                buffer[i] ^= 0x20;\n            }\n            hashValue >>= 4;\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Returns true if the two strings are equal.\n     */\n    function equal(string memory a, string memory b) internal pure returns (bool) {\n        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n\n    /**\n     * @dev Parse a decimal string and returns the value as a `uint256`.\n     *\n     * Requirements:\n     * - The string must be formatted as `[0-9]*`\n     * - The result must fit into an `uint256` type\n     */\n    function parseUint(string memory input) internal pure returns (uint256) {\n        return parseUint(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseUint-string} that parses a substring of `input` located between position `begin` (included) and\n     * `end` (excluded).\n     *\n     * Requirements:\n     * - The substring must be formatted as `[0-9]*`\n     * - The result must fit into an `uint256` type\n     */\n    function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {\n        (bool success, uint256 value) = tryParseUint(input, begin, end);\n        if (!success) revert StringsInvalidChar();\n        return value;\n    }\n\n    /**\n     * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.\n     *\n     * NOTE: This function will revert if the result does not fit in a `uint256`.\n     */\n    function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {\n        return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid\n     * character.\n     *\n     * NOTE: This function will revert if the result does not fit in a `uint256`.\n     */\n    function tryParseUint(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) internal pure returns (bool success, uint256 value) {\n        if (end > bytes(input).length || begin > end) return (false, 0);\n        return _tryParseUintUncheckedBounds(input, begin, end);\n    }\n\n    /**\n     * @dev Implementation of {tryParseUint-string-uint256-uint256} that does not check bounds. Caller should make sure that\n     * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\n     */\n    function _tryParseUintUncheckedBounds(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) private pure returns (bool success, uint256 value) {\n        bytes memory buffer = bytes(input);\n\n        uint256 result = 0;\n        for (uint256 i = begin; i < end; ++i) {\n            uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));\n            if (chr > 9) return (false, 0);\n            result *= 10;\n            result += chr;\n        }\n        return (true, result);\n    }\n\n    /**\n     * @dev Parse a decimal string and returns the value as a `int256`.\n     *\n     * Requirements:\n     * - The string must be formatted as `[-+]?[0-9]*`\n     * - The result must fit in an `int256` type.\n     */\n    function parseInt(string memory input) internal pure returns (int256) {\n        return parseInt(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and\n     * `end` (excluded).\n     *\n     * Requirements:\n     * - The substring must be formatted as `[-+]?[0-9]*`\n     * - The result must fit in an `int256` type.\n     */\n    function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {\n        (bool success, int256 value) = tryParseInt(input, begin, end);\n        if (!success) revert StringsInvalidChar();\n        return value;\n    }\n\n    /**\n     * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if\n     * the result does not fit in a `int256`.\n     *\n     * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.\n     */\n    function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {\n        return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);\n    }\n\n    uint256 private constant ABS_MIN_INT256 = 2 ** 255;\n\n    /**\n     * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid\n     * character or if the result does not fit in a `int256`.\n     *\n     * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.\n     */\n    function tryParseInt(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) internal pure returns (bool success, int256 value) {\n        if (end > bytes(input).length || begin > end) return (false, 0);\n        return _tryParseIntUncheckedBounds(input, begin, end);\n    }\n\n    /**\n     * @dev Implementation of {tryParseInt-string-uint256-uint256} that does not check bounds. Caller should make sure that\n     * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\n     */\n    function _tryParseIntUncheckedBounds(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) private pure returns (bool success, int256 value) {\n        bytes memory buffer = bytes(input);\n\n        // Check presence of a negative sign.\n        bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\n        bool positiveSign = sign == bytes1(\"+\");\n        bool negativeSign = sign == bytes1(\"-\");\n        uint256 offset = (positiveSign || negativeSign).toUint();\n\n        (bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);\n\n        if (absSuccess && absValue < ABS_MIN_INT256) {\n            return (true, negativeSign ? -int256(absValue) : int256(absValue));\n        } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {\n            return (true, type(int256).min);\n        } else return (false, 0);\n    }\n\n    /**\n     * @dev Parse a hexadecimal string (with or without \"0x\" prefix), and returns the value as a `uint256`.\n     *\n     * Requirements:\n     * - The string must be formatted as `(0x)?[0-9a-fA-F]*`\n     * - The result must fit in an `uint256` type.\n     */\n    function parseHexUint(string memory input) internal pure returns (uint256) {\n        return parseHexUint(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseHexUint-string} that parses a substring of `input` located between position `begin` (included) and\n     * `end` (excluded).\n     *\n     * Requirements:\n     * - The substring must be formatted as `(0x)?[0-9a-fA-F]*`\n     * - The result must fit in an `uint256` type.\n     */\n    function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {\n        (bool success, uint256 value) = tryParseHexUint(input, begin, end);\n        if (!success) revert StringsInvalidChar();\n        return value;\n    }\n\n    /**\n     * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.\n     *\n     * NOTE: This function will revert if the result does not fit in a `uint256`.\n     */\n    function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {\n        return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an\n     * invalid character.\n     *\n     * NOTE: This function will revert if the result does not fit in a `uint256`.\n     */\n    function tryParseHexUint(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) internal pure returns (bool success, uint256 value) {\n        if (end > bytes(input).length || begin > end) return (false, 0);\n        return _tryParseHexUintUncheckedBounds(input, begin, end);\n    }\n\n    /**\n     * @dev Implementation of {tryParseHexUint-string-uint256-uint256} that does not check bounds. Caller should make sure that\n     * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\n     */\n    function _tryParseHexUintUncheckedBounds(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) private pure returns (bool success, uint256 value) {\n        bytes memory buffer = bytes(input);\n\n        // skip 0x prefix if present\n        bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2(\"0x\"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\n        uint256 offset = hasPrefix.toUint() * 2;\n\n        uint256 result = 0;\n        for (uint256 i = begin + offset; i < end; ++i) {\n            uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));\n            if (chr > 15) return (false, 0);\n            result *= 16;\n            unchecked {\n                // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).\n                // This guarantees that adding a value < 16 will not cause an overflow, hence the unchecked.\n                result += chr;\n            }\n        }\n        return (true, result);\n    }\n\n    /**\n     * @dev Parse a hexadecimal string (with or without \"0x\" prefix), and returns the value as an `address`.\n     *\n     * Requirements:\n     * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`\n     */\n    function parseAddress(string memory input) internal pure returns (address) {\n        return parseAddress(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseAddress-string} that parses a substring of `input` located between position `begin` (included) and\n     * `end` (excluded).\n     *\n     * Requirements:\n     * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`\n     */\n    function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {\n        (bool success, address value) = tryParseAddress(input, begin, end);\n        if (!success) revert StringsInvalidAddressFormat();\n        return value;\n    }\n\n    /**\n     * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly\n     * formatted address. See {parseAddress-string} requirements.\n     */\n    function tryParseAddress(string memory input) internal pure returns (bool success, address value) {\n        return tryParseAddress(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly\n     * formatted address. See {parseAddress-string-uint256-uint256} requirements.\n     */\n    function tryParseAddress(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) internal pure returns (bool success, address value) {\n        if (end > bytes(input).length || begin > end) return (false, address(0));\n\n        bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2(\"0x\"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\n        uint256 expectedLength = 40 + hasPrefix.toUint() * 2;\n\n        // check that input is the correct length\n        if (end - begin == expectedLength) {\n            // length guarantees that this does not overflow, and value is at most type(uint160).max\n            (bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);\n            return (s, address(uint160(v)));\n        } else {\n            return (false, address(0));\n        }\n    }\n\n    function _tryParseChr(bytes1 chr) private pure returns (uint8) {\n        uint8 value = uint8(chr);\n\n        // Try to parse `chr`:\n        // - Case 1: [0-9]\n        // - Case 2: [a-f]\n        // - Case 3: [A-F]\n        // - otherwise not supported\n        unchecked {\n            if (value > 47 && value < 58) value -= 48;\n            else if (value > 96 && value < 103) value -= 87;\n            else if (value > 64 && value < 71) value -= 55;\n            else return type(uint8).max;\n        }\n\n        return value;\n    }\n\n    /**\n     * @dev Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata.\n     *\n     * WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped.\n     *\n     * NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of\n     * RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode\n     * characters that are not in this range, but other tooling may provide different results.\n     */\n    function escapeJSON(string memory input) internal pure returns (string memory) {\n        bytes memory buffer = bytes(input);\n        bytes memory output = new bytes(2 * buffer.length); // worst case scenario\n        uint256 outputLength = 0;\n\n        for (uint256 i; i < buffer.length; ++i) {\n            bytes1 char = bytes1(_unsafeReadBytesOffset(buffer, i));\n            if (((SPECIAL_CHARS_LOOKUP & (1 << uint8(char))) != 0)) {\n                output[outputLength++] = \"\\\\\";\n                if (char == 0x08) output[outputLength++] = \"b\";\n                else if (char == 0x09) output[outputLength++] = \"t\";\n                else if (char == 0x0a) output[outputLength++] = \"n\";\n                else if (char == 0x0c) output[outputLength++] = \"f\";\n                else if (char == 0x0d) output[outputLength++] = \"r\";\n                else if (char == 0x5c) output[outputLength++] = \"\\\\\";\n                else if (char == 0x22) {\n                    // solhint-disable-next-line quotes\n                    output[outputLength++] = '\"';\n                }\n            } else {\n                output[outputLength++] = char;\n            }\n        }\n        // write the actual length and deallocate unused memory\n        assembly (\"memory-safe\") {\n            mstore(output, outputLength)\n            mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63)))))\n        }\n\n        return string(output);\n    }\n\n    /**\n     * @dev Reads a bytes32 from a bytes array without bounds checking.\n     *\n     * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the\n     * assembly block as such would prevent some optimizations.\n     */\n    function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {\n        // This is not memory safe in the general case, but all calls to this private function are within bounds.\n        assembly (\"memory-safe\") {\n            value := mload(add(add(buffer, 0x20), offset))\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/cryptography/ECDSA.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n    enum RecoverError {\n        NoError,\n        InvalidSignature,\n        InvalidSignatureLength,\n        InvalidSignatureS\n    }\n\n    /**\n     * @dev The signature derives the `address(0)`.\n     */\n    error ECDSAInvalidSignature();\n\n    /**\n     * @dev The signature has an invalid length.\n     */\n    error ECDSAInvalidSignatureLength(uint256 length);\n\n    /**\n     * @dev The signature has an S value that is in the upper half order.\n     */\n    error ECDSAInvalidSignatureS(bytes32 s);\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not\n     * return address(0) without also returning an error description. Errors are documented using an enum (error type)\n     * and a bytes32 providing additional information about the error.\n     *\n     * If no error is returned, then the address can be used for verification purposes.\n     *\n     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.\n     *\n     * Documentation for signature generation:\n     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n     */\n    function tryRecover(\n        bytes32 hash,\n        bytes memory signature\n    ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\n        if (signature.length == 65) {\n            bytes32 r;\n            bytes32 s;\n            uint8 v;\n            // ecrecover takes the signature parameters, and the only way to get them\n            // currently is to use assembly.\n            assembly (\"memory-safe\") {\n                r := mload(add(signature, 0x20))\n                s := mload(add(signature, 0x40))\n                v := byte(0, mload(add(signature, 0x60)))\n            }\n            return tryRecover(hash, v, r, s);\n        } else {\n            return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature`. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.\n     */\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);\n        _throwError(error, errorArg);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n     *\n     * See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures]\n     */\n    function tryRecover(\n        bytes32 hash,\n        bytes32 r,\n        bytes32 vs\n    ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\n        unchecked {\n            bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n            // We do not check for an overflow here since the shift operation results in 0 or 1.\n            uint8 v = uint8((uint256(vs) >> 255) + 27);\n            return tryRecover(hash, v, r, s);\n        }\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n     */\n    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);\n        _throwError(error, errorArg);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     */\n    function tryRecover(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n        //\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n        // these malleable signatures as well.\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n            return (address(0), RecoverError.InvalidSignatureS, s);\n        }\n\n        // If the signature is valid (and not malleable), return the signer address\n        address signer = ecrecover(hash, v, r, s);\n        if (signer == address(0)) {\n            return (address(0), RecoverError.InvalidSignature, bytes32(0));\n        }\n\n        return (signer, RecoverError.NoError, bytes32(0));\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     */\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);\n        _throwError(error, errorArg);\n        return recovered;\n    }\n\n    /**\n     * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.\n     */\n    function _throwError(RecoverError error, bytes32 errorArg) private pure {\n        if (error == RecoverError.NoError) {\n            return; // no error: do nothing\n        } else if (error == RecoverError.InvalidSignature) {\n            revert ECDSAInvalidSignature();\n        } else if (error == RecoverError.InvalidSignatureLength) {\n            revert ECDSAInvalidSignatureLength(uint256(errorArg));\n        } else if (error == RecoverError.InvalidSignatureS) {\n            revert ECDSAInvalidSignatureS(errorArg);\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/MessageHashUtils.sol)\n\npragma solidity ^0.8.20;\n\nimport {Strings} from \"../Strings.sol\";\n\n/**\n * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.\n *\n * The library provides methods for generating a hash of a message that conforms to the\n * https://eips.ethereum.org/EIPS/eip-191[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]\n * specifications.\n */\nlibrary MessageHashUtils {\n    /**\n     * @dev Returns the keccak256 digest of an ERC-191 signed data with version\n     * `0x45` (`personal_sign` messages).\n     *\n     * The digest is calculated by prefixing a bytes32 `messageHash` with\n     * `\"\\x19Ethereum Signed Message:\\n32\"` and hashing the result. It corresponds with the\n     * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.\n     *\n     * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with\n     * keccak256, although any bytes32 value can be safely used because the final digest will\n     * be re-hashed.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\") // 32 is the bytes-length of messageHash\n            mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix\n            digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)\n        }\n    }\n\n    /**\n     * @dev Returns the keccak256 digest of an ERC-191 signed data with version\n     * `0x45` (`personal_sign` messages).\n     *\n     * The digest is calculated by prefixing an arbitrary `message` with\n     * `\"\\x19Ethereum Signed Message:\\n\" + len(message)` and hashing the result. It corresponds with the\n     * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {\n        return\n            keccak256(bytes.concat(\"\\x19Ethereum Signed Message:\\n\", bytes(Strings.toString(message.length)), message));\n    }\n\n    /**\n     * @dev Returns the keccak256 digest of an ERC-191 signed data with version\n     * `0x00` (data with intended validator).\n     *\n     * The digest is calculated by prefixing an arbitrary `data` with `\"\\x19\\x00\"` and the intended\n     * `validator` address. Then hashing the result.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(hex\"19_00\", validator, data));\n    }\n\n    /**\n     * @dev Variant of {toDataWithIntendedValidatorHash-address-bytes} optimized for cases where `data` is a bytes32.\n     */\n    function toDataWithIntendedValidatorHash(\n        address validator,\n        bytes32 messageHash\n    ) internal pure returns (bytes32 digest) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, hex\"19_00\")\n            mstore(0x02, shl(96, validator))\n            mstore(0x16, messageHash)\n            digest := keccak256(0x00, 0x36)\n        }\n    }\n\n    /**\n     * @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`).\n     *\n     * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with\n     * `\\x19\\x01` and hashing the result. It corresponds to the hash signed by the\n     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {\n        assembly (\"memory-safe\") {\n            let ptr := mload(0x40)\n            mstore(ptr, hex\"19_01\")\n            mstore(add(ptr, 0x02), domainSeparator)\n            mstore(add(ptr, 0x22), structHash)\n            digest := keccak256(ptr, 0x42)\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/math/SignedMath.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.20;\n\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n    /**\n     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\n     *\n     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\n     * one branch when needed, making this function more expensive.\n     */\n    function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {\n        unchecked {\n            // branchless ternary works because:\n            // b ^ (a ^ b) == a\n            // b ^ 0 == b\n            return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two signed numbers.\n     */\n    function max(int256 a, int256 b) internal pure returns (int256) {\n        return ternary(a > b, a, b);\n    }\n\n    /**\n     * @dev Returns the smallest of two signed numbers.\n     */\n    function min(int256 a, int256 b) internal pure returns (int256) {\n        return ternary(a < b, a, b);\n    }\n\n    /**\n     * @dev Returns the average of two signed numbers without overflow.\n     * The result is rounded towards zero.\n     */\n    function average(int256 a, int256 b) internal pure returns (int256) {\n        // Formula from the book \"Hacker's Delight\"\n        int256 x = (a & b) + ((a ^ b) >> 1);\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\n    }\n\n    /**\n     * @dev Returns the absolute unsigned value of a signed value.\n     */\n    function abs(int256 n) internal pure returns (uint256) {\n        unchecked {\n            // Formula from the \"Bit Twiddling Hacks\" by Sean Eron Anderson.\n            // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,\n            // taking advantage of the most significant (or \"sign\" bit) in two's complement representation.\n            // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,\n            // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).\n            int256 mask = n >> 255;\n\n            // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.\n            return uint256((n + mask) ^ mask);\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/structs/EnumerableSet.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.20;\n\nimport {Arrays} from \"../Arrays.sol\";\nimport {Math} from \"../math/Math.sol\";\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n * - Set can be cleared (all elements removed) in O(n).\n *\n * ```solidity\n * contract Example {\n *     // Add the library methods\n *     using EnumerableSet for EnumerableSet.AddressSet;\n *\n *     // Declare a set state variable\n *     EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * The following types are supported:\n *\n * - `bytes32` (`Bytes32Set`) since v3.3.0\n * - `address` (`AddressSet`) since v3.3.0\n * - `uint256` (`UintSet`) since v3.3.0\n * - `string` (`StringSet`) since v5.4.0\n * - `bytes` (`BytesSet`) since v5.4.0\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n    // To implement this library for multiple types with as little code\n    // repetition as possible, we write it in terms of a generic Set type with\n    // bytes32 values.\n    // The Set implementation uses private functions, and user-facing\n    // implementations (such as AddressSet) are just wrappers around the\n    // underlying Set.\n    // This means that we can only create new EnumerableSets for types that fit\n    // in bytes32.\n\n    struct Set {\n        // Storage of set values\n        bytes32[] _values;\n        // Position is the index of the value in the `values` array plus 1.\n        // Position 0 is used to mean a value is not in the set.\n        mapping(bytes32 value => uint256) _positions;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function _add(Set storage set, bytes32 value) private returns (bool) {\n        if (!_contains(set, value)) {\n            set._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._positions[value] = set._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function _remove(Set storage set, bytes32 value) private returns (bool) {\n        // We cache the value's position to prevent multiple reads from the same storage slot\n        uint256 position = set._positions[value];\n\n        if (position != 0) {\n            // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 valueIndex = position - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            if (valueIndex != lastIndex) {\n                bytes32 lastValue = set._values[lastIndex];\n\n                // Move the lastValue to the index where the value to delete is\n                set._values[valueIndex] = lastValue;\n                // Update the tracked position of the lastValue (that was just moved)\n                set._positions[lastValue] = position;\n            }\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the tracked position for the deleted slot\n            delete set._positions[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes all the values from a set. O(n).\n     *\n     * WARNING: This function has an unbounded cost that scales with set size. Developers should keep in mind that\n     * using it may render the function uncallable if the set grows to the point where clearing it consumes too much\n     * gas to fit in a block.\n     */\n    function _clear(Set storage set) private {\n        uint256 len = _length(set);\n        for (uint256 i = 0; i < len; ++i) {\n            delete set._positions[set._values[i]];\n        }\n        Arrays.unsafeSetLength(set._values, 0);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function _contains(Set storage set, bytes32 value) private view returns (bool) {\n        return set._positions[value] != 0;\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function _length(Set storage set) private view returns (uint256) {\n        return set._values.length;\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function _at(Set storage set, uint256 index) private view returns (bytes32) {\n        return set._values[index];\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function _values(Set storage set) private view returns (bytes32[] memory) {\n        return set._values;\n    }\n\n    /**\n     * @dev Return a slice of the set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function _values(Set storage set, uint256 start, uint256 end) private view returns (bytes32[] memory) {\n        unchecked {\n            end = Math.min(end, _length(set));\n            start = Math.min(start, end);\n\n            uint256 len = end - start;\n            bytes32[] memory result = new bytes32[](len);\n            for (uint256 i = 0; i < len; ++i) {\n                result[i] = Arrays.unsafeAccess(set._values, start + i).value;\n            }\n            return result;\n        }\n    }\n\n    // Bytes32Set\n\n    struct Bytes32Set {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _add(set._inner, value);\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _remove(set._inner, value);\n    }\n\n    /**\n     * @dev Removes all the values from a set. O(n).\n     *\n     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the\n     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.\n     */\n    function clear(Bytes32Set storage set) internal {\n        _clear(set._inner);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n        return _contains(set._inner, value);\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(Bytes32Set storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n        return _at(set._inner, index);\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        bytes32[] memory result;\n\n        assembly (\"memory-safe\") {\n            result := store\n        }\n\n        return result;\n    }\n\n    /**\n     * @dev Return a slice of the set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n        bytes32[] memory store = _values(set._inner, start, end);\n        bytes32[] memory result;\n\n        assembly (\"memory-safe\") {\n            result := store\n        }\n\n        return result;\n    }\n\n    // AddressSet\n\n    struct AddressSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(AddressSet storage set, address value) internal returns (bool) {\n        return _add(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(AddressSet storage set, address value) internal returns (bool) {\n        return _remove(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Removes all the values from a set. O(n).\n     *\n     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the\n     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.\n     */\n    function clear(AddressSet storage set) internal {\n        _clear(set._inner);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(AddressSet storage set, address value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(AddressSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(AddressSet storage set, uint256 index) internal view returns (address) {\n        return address(uint160(uint256(_at(set._inner, index))));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(AddressSet storage set) internal view returns (address[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        address[] memory result;\n\n        assembly (\"memory-safe\") {\n            result := store\n        }\n\n        return result;\n    }\n\n    /**\n     * @dev Return a slice of the set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\n        bytes32[] memory store = _values(set._inner, start, end);\n        address[] memory result;\n\n        assembly (\"memory-safe\") {\n            result := store\n        }\n\n        return result;\n    }\n\n    // UintSet\n\n    struct UintSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(UintSet storage set, uint256 value) internal returns (bool) {\n        return _add(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(UintSet storage set, uint256 value) internal returns (bool) {\n        return _remove(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Removes all the values from a set. O(n).\n     *\n     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the\n     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.\n     */\n    function clear(UintSet storage set) internal {\n        _clear(set._inner);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(UintSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n        return uint256(_at(set._inner, index));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(UintSet storage set) internal view returns (uint256[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        uint256[] memory result;\n\n        assembly (\"memory-safe\") {\n            result := store\n        }\n\n        return result;\n    }\n\n    /**\n     * @dev Return a slice of the set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\n        bytes32[] memory store = _values(set._inner, start, end);\n        uint256[] memory result;\n\n        assembly (\"memory-safe\") {\n            result := store\n        }\n\n        return result;\n    }\n\n    struct StringSet {\n        // Storage of set values\n        string[] _values;\n        // Position is the index of the value in the `values` array plus 1.\n        // Position 0 is used to mean a value is not in the set.\n        mapping(string value => uint256) _positions;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(StringSet storage set, string memory value) internal returns (bool) {\n        if (!contains(set, value)) {\n            set._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._positions[value] = set._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(StringSet storage set, string memory value) internal returns (bool) {\n        // We cache the value's position to prevent multiple reads from the same storage slot\n        uint256 position = set._positions[value];\n\n        if (position != 0) {\n            // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 valueIndex = position - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            if (valueIndex != lastIndex) {\n                string memory lastValue = set._values[lastIndex];\n\n                // Move the lastValue to the index where the value to delete is\n                set._values[valueIndex] = lastValue;\n                // Update the tracked position of the lastValue (that was just moved)\n                set._positions[lastValue] = position;\n            }\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the tracked position for the deleted slot\n            delete set._positions[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes all the values from a set. O(n).\n     *\n     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the\n     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.\n     */\n    function clear(StringSet storage set) internal {\n        uint256 len = length(set);\n        for (uint256 i = 0; i < len; ++i) {\n            delete set._positions[set._values[i]];\n        }\n        Arrays.unsafeSetLength(set._values, 0);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(StringSet storage set, string memory value) internal view returns (bool) {\n        return set._positions[value] != 0;\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function length(StringSet storage set) internal view returns (uint256) {\n        return set._values.length;\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(StringSet storage set, uint256 index) internal view returns (string memory) {\n        return set._values[index];\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(StringSet storage set) internal view returns (string[] memory) {\n        return set._values;\n    }\n\n    /**\n     * @dev Return a slice of the set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(StringSet storage set, uint256 start, uint256 end) internal view returns (string[] memory) {\n        unchecked {\n            end = Math.min(end, length(set));\n            start = Math.min(start, end);\n\n            uint256 len = end - start;\n            string[] memory result = new string[](len);\n            for (uint256 i = 0; i < len; ++i) {\n                result[i] = Arrays.unsafeAccess(set._values, start + i).value;\n            }\n            return result;\n        }\n    }\n\n    struct BytesSet {\n        // Storage of set values\n        bytes[] _values;\n        // Position is the index of the value in the `values` array plus 1.\n        // Position 0 is used to mean a value is not in the set.\n        mapping(bytes value => uint256) _positions;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(BytesSet storage set, bytes memory value) internal returns (bool) {\n        if (!contains(set, value)) {\n            set._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._positions[value] = set._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(BytesSet storage set, bytes memory value) internal returns (bool) {\n        // We cache the value's position to prevent multiple reads from the same storage slot\n        uint256 position = set._positions[value];\n\n        if (position != 0) {\n            // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 valueIndex = position - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            if (valueIndex != lastIndex) {\n                bytes memory lastValue = set._values[lastIndex];\n\n                // Move the lastValue to the index where the value to delete is\n                set._values[valueIndex] = lastValue;\n                // Update the tracked position of the lastValue (that was just moved)\n                set._positions[lastValue] = position;\n            }\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the tracked position for the deleted slot\n            delete set._positions[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes all the values from a set. O(n).\n     *\n     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the\n     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.\n     */\n    function clear(BytesSet storage set) internal {\n        uint256 len = length(set);\n        for (uint256 i = 0; i < len; ++i) {\n            delete set._positions[set._values[i]];\n        }\n        Arrays.unsafeSetLength(set._values, 0);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(BytesSet storage set, bytes memory value) internal view returns (bool) {\n        return set._positions[value] != 0;\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function length(BytesSet storage set) internal view returns (uint256) {\n        return set._values.length;\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(BytesSet storage set, uint256 index) internal view returns (bytes memory) {\n        return set._values[index];\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(BytesSet storage set) internal view returns (bytes[] memory) {\n        return set._values;\n    }\n\n    /**\n     * @dev Return a slice of the set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(BytesSet storage set, uint256 start, uint256 end) internal view returns (bytes[] memory) {\n        unchecked {\n            end = Math.min(end, length(set));\n            start = Math.min(start, end);\n\n            uint256 len = end - start;\n            bytes[] memory result = new bytes[](len);\n            for (uint256 i = 0; i < len; ++i) {\n                result[i] = Arrays.unsafeAccess(set._values, start + i).value;\n            }\n            return result;\n        }\n    }\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"_trUSDAddress","type":"address"},{"internalType":"address[]","name":"_allowedTokens","type":"address[]"},{"components":[{"internalType":"enum ToriMinting.TokenType","name":"tokenType","type":"uint8"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint128","name":"maxMintPerBlock","type":"uint128"},{"internalType":"uint128","name":"maxRedeemPerBlock","type":"uint128"}],"internalType":"struct ToriMinting.TokenConfig[]","name":"_tokenConfigs","type":"tuple[]"},{"internalType":"uint128","name":"_globalMaxMintPerBlock","type":"uint128"},{"internalType":"uint128","name":"_globalMaxRedeemPerBlock","type":"uint128"},{"internalType":"address","name":"_admin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"uint48","name":"schedule","type":"uint48"}],"name":"AccessControlEnforcedDefaultAdminDelay","type":"error"},{"inputs":[],"name":"AccessControlEnforcedDefaultAdminRules","type":"error"},{"inputs":[{"internalType":"address","name":"defaultAdmin","type":"address"}],"name":"AccessControlInvalidDefaultAdmin","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"GlobalMaxMintPerBlockExceeded","type":"error"},{"inputs":[],"name":"GlobalMaxRedeemPerBlockExceeded","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidCustodianAddress","type":"error"},{"inputs":[],"name":"InvalidEIP1271Signature","type":"error"},{"inputs":[],"name":"InvalidEIP712Signature","type":"error"},{"inputs":[],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"InvalidOrder","type":"error"},{"inputs":[],"name":"InvalidRoute","type":"error"},{"inputs":[],"name":"InvalidStablePrice","type":"error"},{"inputs":[],"name":"InvalidTokenAddress","type":"error"},{"inputs":[],"name":"MaxMintPerBlockExceeded","type":"error"},{"inputs":[],"name":"MaxRedeemPerBlockExceeded","type":"error"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"NotWhitelisted","type":"error"},{"inputs":[],"name":"RecipientNotApproved","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"SignatureExpired","type":"error"},{"inputs":[],"name":"TimelockAdminAlreadyInitialized","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"TokenNotAllowed","type":"error"},{"inputs":[],"name":"UnknownSignatureType","type":"error"},{"inputs":[],"name":"UnsupportedAsset","type":"error"},{"inputs":[],"name":"UseSetTimelockAdmin","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"custodian","type":"address"}],"name":"CustodianAddressAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"custodian","type":"address"}],"name":"CustodianAddressRemoved","type":"event"},{"anonymous":false,"inputs":[],"name":"DefaultAdminDelayChangeCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint48","name":"newDelay","type":"uint48"},{"indexed":false,"internalType":"uint48","name":"effectSchedule","type":"uint48"}],"name":"DefaultAdminDelayChangeScheduled","type":"event"},{"anonymous":false,"inputs":[],"name":"DefaultAdminTransferCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"},{"indexed":false,"internalType":"uint48","name":"acceptSchedule","type":"uint48"}],"name":"DefaultAdminTransferScheduled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"globalMaxMintPerBlock","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"globalMaxRedeemPerBlock","type":"uint128"}],"name":"GlobalLimitsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"oldMaxMintPerBlock","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"newMaxMintPerBlock","type":"uint128"},{"indexed":true,"internalType":"address","name":"asset","type":"address"}],"name":"MaxMintPerBlockChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"oldMaxRedeemPerBlock","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"newMaxRedeemPerBlock","type":"uint128"},{"indexed":true,"internalType":"address","name":"asset","type":"address"}],"name":"MaxRedeemPerBlockChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"address","name":"collateral_asset","type":"address"},{"indexed":false,"internalType":"uint128","name":"collateral_amount","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"trusd_amount","type":"uint128"},{"indexed":false,"internalType":"string","name":"order_id","type":"string"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"RecipientAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"RecipientRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"address","name":"collateral_asset","type":"address"},{"indexed":false,"internalType":"uint128","name":"trusd_amount","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"collateral_amount","type":"uint128"},{"indexed":false,"internalType":"string","name":"order_id","type":"string"}],"name":"Redeemed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldTimelockAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"newTimelockAdmin","type":"address"}],"name":"TimelockAdminUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"TokenAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"TokenRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"UserRemovedFromWhitelist","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"UserWhitelisted","type":"event"},{"inputs":[],"name":"COLLATERAL_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GATEKEEPER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REDEEMER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIMELOCK_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TRUSD_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WHITELISTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptDefaultAdminTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"components":[{"internalType":"enum ToriMinting.TokenType","name":"tokenType","type":"uint8"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint128","name":"maxMintPerBlock","type":"uint128"},{"internalType":"uint128","name":"maxRedeemPerBlock","type":"uint128"}],"internalType":"struct ToriMinting.TokenConfig","name":"_config","type":"tuple"}],"name":"addAllowedToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"custodian","type":"address"}],"name":"addCustodianAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"addToWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_users","type":"address[]"}],"name":"addToWhitelistBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"beginDefaultAdminTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelDefaultAdminTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint48","name":"newDelay","type":"uint48"}],"name":"changeDefaultAdminDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultAdminDelay","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultAdminDelayIncreaseWait","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"disableAllowedToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableMintRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"enableAllowedToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"enum ToriMinting.OrderType","name":"order_type","type":"uint8"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"collateral_asset","type":"address"},{"internalType":"uint128","name":"collateral_amount","type":"uint128"},{"internalType":"uint128","name":"trusd_amount","type":"uint128"},{"internalType":"uint128","name":"expiry","type":"uint128"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"string","name":"order_id","type":"string"}],"internalType":"struct ToriMinting.Order","name":"order","type":"tuple"}],"name":"encodeOrder","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getCustodianAddresses","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDomainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalMaxMintPerBlock","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalMaxRedeemPerBlock","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"enum ToriMinting.OrderType","name":"order_type","type":"uint8"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"collateral_asset","type":"address"},{"internalType":"uint128","name":"collateral_amount","type":"uint128"},{"internalType":"uint128","name":"trusd_amount","type":"uint128"},{"internalType":"uint128","name":"expiry","type":"uint128"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"string","name":"order_id","type":"string"}],"internalType":"struct ToriMinting.Order","name":"order","type":"tuple"}],"name":"hashOrder","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"timelockAdmin","type":"address"}],"name":"initializeTimelockAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"isApprovedRecipient","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"isSupportedAsset","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"enum ToriMinting.OrderType","name":"order_type","type":"uint8"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"collateral_asset","type":"address"},{"internalType":"uint128","name":"collateral_amount","type":"uint128"},{"internalType":"uint128","name":"trusd_amount","type":"uint128"},{"internalType":"uint128","name":"expiry","type":"uint128"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"string","name":"order_id","type":"string"}],"internalType":"struct ToriMinting.Order","name":"order","type":"tuple"},{"components":[{"internalType":"enum ToriMinting.SignatureType","name":"signature_type","type":"uint8"},{"internalType":"bytes","name":"signature_bytes","type":"bytes"}],"internalType":"struct ToriMinting.Signature","name":"signature","type":"tuple"},{"components":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint128[]","name":"ratios","type":"uint128[]"}],"internalType":"struct ToriMinting.Route","name":"route","type":"tuple"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingDefaultAdmin","outputs":[{"internalType":"address","name":"newAdmin","type":"address"},{"internalType":"uint48","name":"schedule","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingDefaultAdminDelay","outputs":[{"internalType":"uint48","name":"newDelay","type":"uint48"},{"internalType":"uint48","name":"schedule","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"enum ToriMinting.OrderType","name":"order_type","type":"uint8"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"collateral_asset","type":"address"},{"internalType":"uint128","name":"collateral_amount","type":"uint128"},{"internalType":"uint128","name":"trusd_amount","type":"uint128"},{"internalType":"uint128","name":"expiry","type":"uint128"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"string","name":"order_id","type":"string"}],"internalType":"struct ToriMinting.Order","name":"order","type":"tuple"},{"components":[{"internalType":"enum ToriMinting.SignatureType","name":"signature_type","type":"uint8"},{"internalType":"bytes","name":"signature_bytes","type":"bytes"}],"internalType":"struct ToriMinting.Signature","name":"signature","type":"tuple"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"removeAllowedToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collateralManager","type":"address"}],"name":"removeCollateralManagerRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"custodian","type":"address"}],"name":"removeCustodianAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"removeFromWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"removeMinterRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"redeemer","type":"address"}],"name":"removeRedeemerRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rollbackDefaultAdminDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bool","name":"status","type":"bool"}],"name":"setApprovedRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_globalMaxMintPerBlock","type":"uint128"},{"internalType":"uint128","name":"_globalMaxRedeemPerBlock","type":"uint128"}],"name":"setGlobalLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_maxMintPerBlock","type":"uint128"},{"internalType":"address","name":"asset","type":"address"}],"name":"setMaxMintPerBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_maxRedeemPerBlock","type":"uint128"},{"internalType":"address","name":"asset","type":"address"}],"name":"setMaxRedeemPerBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_stablesDeltaLimit","type":"uint128"}],"name":"setStablesDeltaLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newTimelockAdmin","type":"address"}],"name":"setTimelockAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stablesDeltaLimit","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenConfig","outputs":[{"internalType":"enum ToriMinting.TokenType","name":"tokenType","type":"uint8"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"uint128","name":"maxMintPerBlock","type":"uint128"},{"internalType":"uint128","name":"maxRedeemPerBlock","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalPerBlock","outputs":[{"internalType":"uint128","name":"mintedPerBlock","type":"uint128"},{"internalType":"uint128","name":"redeemedPerBlock","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"totalPerBlockPerAsset","outputs":[{"internalType":"uint128","name":"mintedPerBlock","type":"uint128"},{"internalType":"uint128","name":"redeemedPerBlock","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"components":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint128[]","name":"ratios","type":"uint128[]"}],"internalType":"struct ToriMinting.Route","name":"route","type":"tuple"}],"name":"transferToCustody","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"verifyNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"enum ToriMinting.OrderType","name":"order_type","type":"uint8"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"collateral_asset","type":"address"},{"internalType":"uint128","name":"collateral_amount","type":"uint128"},{"internalType":"uint128","name":"trusd_amount","type":"uint128"},{"internalType":"uint128","name":"expiry","type":"uint128"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"string","name":"order_id","type":"string"}],"internalType":"struct ToriMinting.Order","name":"order","type":"tuple"},{"components":[{"internalType":"enum ToriMinting.SignatureType","name":"signature_type","type":"uint8"},{"internalType":"bytes","name":"signature_bytes","type":"bytes"}],"internalType":"struct ToriMinting.Signature","name":"signature","type":"tuple"}],"name":"verifyOrder","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint128[]","name":"ratios","type":"uint128[]"}],"internalType":"struct ToriMinting.Route","name":"route","type":"tuple"}],"name":"verifyRoute","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"collateralAmount","type":"uint128"},{"internalType":"uint128","name":"trusdAmount","type":"uint128"},{"internalType":"address","name":"collateralAsset","type":"address"},{"internalType":"enum ToriMinting.OrderType","name":"orderType","type":"uint8"}],"name":"verifyStablesLimit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"0x000000000000000000000000d0580192e98ea6ceb9c7b6191ed2e2756091169700000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000002b5e3af16b18800000000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000c6bbfd2d5666d44bf28580edeec0263692c83160000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000002b5e3af16b18800000000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000002b5e3af16b18800000000000000000000000000000000000000000000000000004563918244f40000"}