{"file_path":"contracts/rwaf/TokenBlender.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.19;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\n/**\n * @title ITokenBlender\n * @notice Interface for the TokenBlender contract\n */\ninterface ITokenBlender {\n    function deposit(address token, uint256 amount, uint256 minAmountOut) external;\n    function previewDeposit(address token, uint256 amount) external view returns (uint256);\n    function withdraw(address token, uint256 amountOut, uint256 maxAmountBurned) external;\n    function previewWithdraw(address token, uint256 amountOut) external view returns (uint256);\n    function swap(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut) external;\n    function previewSwap(address tokenIn, address tokenOut, uint256 amountIn) external view returns (uint256);\n    function emergencyWithdraw(address token, uint256 amount, bool forceRemove) external;\n    function getTokenRatio(address token) external view returns (uint256);\n    function updateTokenRatio(address token, uint256 newRatio) external;\n    function addSupportedToken(address token, uint256 ratio) external;\n    function removeSupportedToken(address token) external;\n    function getReserveBalance() external view returns (uint256);\n    function getTokenReserveBalance(address token) external view returns (uint256);\n    function getSupportedTokenCount() external view returns (uint256);\n    function getSupportedTokens() external view returns (address[] memory);\n    function pause() external;\n    function unpause() external;\n\n\n    error InvalidAddress();\n    error ZeroAmount();\n    error TokenNotSupported();\n    error TokenAlreadySupported();\n    error InvalidRatio();\n    error InsufficientAmountOut();\n    error SlippageExceeded();\n    error InvalidDecimals();\n    error InvalidToken();\n    error TokenHasBalance();\n    event TokenDeposited(address indexed token, uint256 amount, uint256 amountOut);\n    event TokenWithdrawn(address indexed token, uint256 amountOut, uint256 amountBurned);\n    event TokenAdded(address indexed token, uint256 ratio);\n    event TokenRemoved(address indexed token);\n    event TokenRatioUpdated(address indexed token, uint256 newRatio);\n    event EmergencyWithdrawn(address indexed token, uint256 amount);\n    event TokenSwapped(address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n}\n\n/**\n /**\n * @title TokenBlender – Transitional wrapper for discounted ION → audited Instruxi token\n * @notice The contract accepts multiple tokens and blends them into a single token.\n * @dev The contract uses token ratios based on a global token (such as Instruxi share token where 1 token is worth 1 XAU)\n * @dev The system is designed to run in a centralized, admin-controlled manner. Suggested to have it behind a multi-sig contract.\n * @dev Supports 18 decimals tokens only.\n * @dev Any dust produced by the contract rounding will benefit the contract than the user. It can be taken out using the emergencyWithdraw function.\n  */\n\ncontract TokenBlender is ITokenBlender, Initializable, AccessControlUpgradeable, ERC20Upgradeable, PausableUpgradeable, ReentrancyGuardUpgradeable {\n    using SafeERC20 for IERC20;\n\n    /// @notice Admin role - can update parameters\n    bytes32 public constant ADMIN_ROLE = keccak256(\"ADMIN_ROLE\");\n    /// @notice Manager role - can manage deposit/withdraw/swap\n    bytes32 public constant MANAGER_ROLE = keccak256(\"MANAGER_ROLE\");\n    /// @notice Emergency role - can perform emergency withdrawals\n    bytes32 public constant EMERGENCY_ROLE = keccak256(\"EMERGENCY_ROLE\");\n\n    /// @notice Ratio at which each token is blended\n    /// @dev if a token has a ratio of 5 (5 * RATIO_PRECISION), then 1 TokenBlender token is worth 5 of the token\n    /// @dev If a token is not supported, the ratio is 0\n    mapping(address => uint256) public ratios;\n    /// @notice list of supported tokens\n    address[] public supportedTokens;\n    /// @notice ration decimal precision\n    uint256 public constant RATIO_PRECISION = 10 ** 18; // 18 decimals\n\n    /// @custom:oz-upgrades-unsafe-allow constructor\n    constructor() {\n        _disableInitializers();\n    }\n\n    /**\n     * @notice Initializes the TokenBlender contract\n     * @param name The name of the token\n     * @param symbol The symbol of the token\n     * @param initialOwner The address that will be granted all roles (DEFAULT_ADMIN_ROLE, MANAGER_ROLE, EMERGENCY_ROLE)\n     */\n    function initialize(string memory name, string memory symbol, address initialOwner) public initializer {\n        if (initialOwner == address(0)) revert InvalidAddress();\n        \n        __AccessControl_init();\n        __ERC20_init(name, symbol);\n        __Pausable_init();\n        __ReentrancyGuard_init();\n\n        // Grant all roles to initialOwner\n        _grantRole(DEFAULT_ADMIN_ROLE, initialOwner);\n        _grantRole(ADMIN_ROLE, initialOwner);\n        _grantRole(MANAGER_ROLE, initialOwner);\n        _grantRole(EMERGENCY_ROLE, initialOwner);\n    }\n\n    /**\n     * @notice Deposits tokens into the TokenBlender\n     * @param token The address of the token to deposit\n     * @param amount The amount of tokens to deposit\n     * @param minAmountOut The minimum amount of tokens to receive\n     * @dev To reduce rounding dust, it is ideal for the amountOut to be `amount % ratio == 0`\n     */\n    function deposit(address token, uint256 amount, uint256 minAmountOut) external override nonReentrant whenNotPaused onlyRole(MANAGER_ROLE) {\n        uint256 amountOut = previewDeposit(token, amount);\n        if (amountOut == 0) revert ZeroAmount();\n        if (amountOut < minAmountOut) revert InsufficientAmountOut();\n        IERC20(token).safeTransferFrom(msg.sender, address(this), amount);\n        _mint(msg.sender, amountOut);\n        emit TokenDeposited(token, amount, amountOut);\n    }\n    /**\n     * @notice Previews the amount of tokens that will be minted for a given amount of tokens\n     * @param token The address of the token to preview\n     * @param amount The amount of tokens to preview\n     * @return The amount of tokens that will be minted\n     */\n    function previewDeposit(address token, uint256 amount) public view returns (uint256) {\n        if (token == address(0)) revert InvalidAddress();\n        if (ratios[token] == 0) revert TokenNotSupported();\n        if (amount == 0) revert ZeroAmount();\n\n        return amount * RATIO_PRECISION / ratios[token]; // round down\n    }\n\n    /**\n     * @notice Withdraws tokens from the TokenBlender\n     * @param token The address of the token to withdraw\n     * @param amountOut The amount of tokens to withdraw\n     * @param maxAmountBurned The maximum amount of tokens that can be burned\n     * @dev To reduce rounding dust, it is ideal for the amountOut to be `amount % ratio == 0`\n     */\n    function withdraw(address token, uint256 amountOut, uint256 maxAmountBurned) external override nonReentrant whenNotPaused onlyRole(MANAGER_ROLE) {\n        uint256 amountBurned = previewWithdraw(token, amountOut);\n        if (amountBurned > maxAmountBurned) revert SlippageExceeded();\n        _burn(msg.sender, amountBurned);\n        IERC20(token).safeTransfer(msg.sender, amountOut);\n        emit TokenWithdrawn(token, amountOut, amountBurned);\n    }\n    /**\n     * @notice Previews the amount of TokenBlender tokens that will be burned to withdraw a given amount of underlying tokens.\n     * @param token The address of the token to preview\n     * @param amountOut The amount of tokens to preview\n     * @return amountBurned The amount of tokens that will be burned\n     */\n    function previewWithdraw(address token, uint256 amountOut) public view returns (uint256 amountBurned) {\n        if (token == address(0)) revert InvalidAddress();\n        if (ratios[token] == 0) revert TokenNotSupported();\n        if (amountOut == 0) revert ZeroAmount();\n        amountBurned = (amountOut * RATIO_PRECISION + ratios[token] - 1) / ratios[token]; // round up to avoid burning less than expected\n        if (amountBurned == 0) revert ZeroAmount();\n    }\n\n    /**\n     * @notice Swaps tokens based on the ratio\n     * @param tokenIn The address of the token to swap\n     * @param tokenOut The address of the token to swap\n     * @param amountIn The amount of tokens to swap\n     */\n    function swap(address tokenIn, address tokenOut, uint256 amountIn, uint256 minAmountOut) external override nonReentrant whenNotPaused onlyRole(MANAGER_ROLE) {\n        uint256 amountOut = previewSwap(tokenIn, tokenOut, amountIn);\n        if (amountOut < minAmountOut) revert InsufficientAmountOut();\n        IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n        IERC20(tokenOut).safeTransfer(msg.sender, amountOut);\n        emit TokenSwapped(tokenIn, tokenOut, amountIn, amountOut);\n    }\n    /**\n     * @notice Previews the amount of tokens that will be swapped for a given amount of tokens\n     * @param tokenIn The address of the token to swap\n     * @param tokenOut The address of the token to swap\n     * @param amountIn The amount of tokens to swap\n     * @return amountOut The amount of tokens that will be swapped\n     * @dev To reduce rounding dust, it is ideal for the amountOut to be `amountIn % ratio == 0`\n     */\n    function previewSwap(address tokenIn, address tokenOut, uint256 amountIn) public view returns (uint256 amountOut) {\n        if (tokenIn == address(0) || tokenOut == address(0)) revert InvalidAddress();\n        if (tokenIn == tokenOut) revert InvalidToken();\n        if (ratios[tokenIn] == 0) revert TokenNotSupported();\n        if (ratios[tokenOut] == 0) revert TokenNotSupported();\n        if (amountIn == 0) revert ZeroAmount();\n        amountOut = amountIn * ratios[tokenOut] / ratios[tokenIn]; // round down\n        if (amountOut == 0) revert ZeroAmount();\n    }\n\n    /**\n     * @notice Emergency withdraws of tokens from the TokenBlender\n     * @param token The address of the token to withdraw\n     * @param amount The amount of tokens to withdraw\n     * @param forceRemove Whether to force remove the token after withdraw\n     * @dev To mitigate any 1 wei deposit which would prevent token removal after withdraw of dust, it is possible to force remove the token after withdraw.\n     */\n    function emergencyWithdraw(address token, uint256 amount, bool forceRemove) external override nonReentrant onlyRole(EMERGENCY_ROLE) {\n        if (token == address(0)) revert InvalidAddress();\n        if (amount == 0) revert ZeroAmount();\n        IERC20(token).safeTransfer(msg.sender, amount);\n        if (forceRemove) _removeSupportedToken(token);\n        emit EmergencyWithdrawn(token, amount);\n    }\n\n    /**\n     * @notice Gets the ratio of a given token\n     * @param token The address of the token to get the ratio\n     * @return The ratio of the token\n     */\n    function getTokenRatio(address token) public view override returns (uint256) {\n        if (token == address(0)) revert InvalidAddress();\n        if (ratios[token] == 0) revert TokenNotSupported();\n        return ratios[token];\n    }\n\n    /**\n     * @notice Updates the ratio of a given token\n     * @param token The address of the token to update\n     * @param newRatio The new ratio of the token\n     * @dev The new ratio must be smaller than the current ratio. That would mean that the asset has increased in value. \n     * @dev Any excess of reserve can be taken out using the emergencyWithdraw function, to bring the reserve balance = total supply.\n     */\n    function updateTokenRatio(address token, uint256 newRatio) external override nonReentrant onlyRole(ADMIN_ROLE) {\n        if (token == address(0)) revert InvalidAddress();\n        if (ratios[token] == 0) revert TokenNotSupported();\n        if (newRatio < RATIO_PRECISION || newRatio >= ratios[token]) revert InvalidRatio();\n        ratios[token] = newRatio;\n        emit TokenRatioUpdated(token, newRatio);\n    }\n\n    /**\n     * @notice Adds a supported token to the TokenBlender\n     * @param token The address of the token to add\n     */\n    function addSupportedToken(address token, uint256 ratio) external override nonReentrant onlyRole(ADMIN_ROLE) {\n        if (token == address(0)) revert InvalidAddress();\n        if (ratios[token] != 0) revert TokenAlreadySupported();\n        // no ratio is less than 1 (meaning it is worth more than 1 TokenBlender token)\n        if (ratio < RATIO_PRECISION) revert InvalidRatio();\n        if (IERC20Metadata(token).decimals() != 18) revert InvalidDecimals();\n        ratios[token] = ratio;\n        supportedTokens.push(token);\n        emit TokenAdded(token, ratio);\n    }\n    /**\n     * @notice Removes a supported token from the TokenBlender\n     * @param token The address of the token to remove\n     * @dev The token must have no balance in the contract. It must be fully swapped out or withdrawn.\n     * @dev For forced removal with dust remaining, use emergencyWithdraw with forceRemove=true.\n     */\n    function removeSupportedToken(address token) external override nonReentrant onlyRole(ADMIN_ROLE) {\n        if (IERC20(token).balanceOf(address(this)) > 0) revert TokenHasBalance();\n        _removeSupportedToken(token);\n    }\n\n    /**\n     * @notice Removes a supported token from the TokenBlender\n     * @param token The address of the token to remove\n     * @dev Internal function to remove a supported token from the TokenBlender\n     * @dev Note: Balance check is intentionally omitted here to allow forced removal via emergencyWithdraw.\n     * Any dust remaining will stay in the contract.\n     */\n    function _removeSupportedToken(address token) internal {\n        if (token == address(0)) revert InvalidAddress();\n        if (ratios[token] == 0) revert TokenNotSupported();\n        delete ratios[token];\n        for (uint256 i = 0; i < supportedTokens.length; i++) {\n            if (supportedTokens[i] == token) {\n                supportedTokens[i] = supportedTokens[supportedTokens.length - 1];\n                supportedTokens.pop();\n                break;\n            }\n        }\n        emit TokenRemoved(token);\n    }\n\n    /**\n     * @notice Gets the list of supported tokens\n     * @return The list of supported tokens\n     */\n    function getSupportedTokens() external view returns (address[] memory) {\n        return supportedTokens;\n    }\n\n    /**\n     * @notice Gets the number of supported tokens\n     * @return The number of supported tokens\n     */\n    function getSupportedTokenCount() external view returns (uint256) {\n        return supportedTokens.length;\n    }\n\n    /**\n    /**\n     * @notice Returns the total reserve balance, normalized to the TokenBlender aggregate precision.\n     * @dev Sums all supported tokens' balances, converting each to the common TokenBlender value using its ratio.\n     * This value can be compared to the total TB token supply. It is expected to be equal to or greater than the total supply (due to rounding or residual balances).\n     * @return totalBalance The aggregate reserve balance denominated in TokenBlender units.\n     */\n    function getReserveBalance() external view returns (uint256 totalBalance) {\n        for (uint256 i = 0; i < supportedTokens.length; i++) {\n            totalBalance += IERC20(supportedTokens[i]).balanceOf(address(this)) * RATIO_PRECISION / ratios[supportedTokens[i]];\n        }\n    }\n\n    /**\n     /**\n      * @notice Returns the worth of a specific token's balance in the reserve, converted to the equivalent value in TB tokens using its ratio.\n      * @param token The address of the token to query.\n      * @return The token's reserve balance represented in terms of TB token value.\n      */\n    function getTokenReserveBalance(address token) external view returns (uint256) {\n        if (token == address(0)) revert InvalidAddress();\n        if (ratios[token] == 0) revert TokenNotSupported();\n        return IERC20(token).balanceOf(address(this)) * RATIO_PRECISION / ratios[token];\n    }\n\n    /**\n     * @notice Pauses the contract\n     * @dev Only callable by the admin\n     */\n    function pause() external onlyRole(ADMIN_ROLE) {\n        _pause();\n    }\n\n    /**\n     * @notice Unpauses the contract\n     * @dev Only callable by the admin\n     */\n    function unpause() external onlyRole(ADMIN_ROLE) {\n        _unpause();\n    }\n}","deployed_bytecode":"0x608080604052600436101561001357600080fd5b60003560e01c90816301ffc9a71461193d5750806306fdde031461188d578063077f224a146113e3578063095ea7b3146113625780630efe6a8b1461124a57806318160ddd1461121f57806320df4359146111f657806323b872dd14611128578063248a9ca31461110a57806324c71ece146110d05780632f2ff15d1461109f578063313ce5671461108357806336568abe1461103d5780633f4ba83a14610fba57806344bad40214610f665780634d8e3d3b14610dc75780635c975abb14610d975780636945a10c14610cb957806370a0823114610c7257806375b238fc14610c495780637631919014610b875780638456cb5914610b1357806391d1485414610ab957806395d89b41146109d45780639d911465146108cf578063a217fddf146108b3578063a9059cbb14610882578063b5c5f6721461072c578063b8f82b2614610705578063bbbaffab146106ec578063bbc6f1dc146106c5578063c625562614610683578063cb765c1d1461057a578063ce67be261461055c578063d32867d014610539578063d3c7c2c714610489578063d547741f14610451578063dd62ed3e14610408578063ec87621c146103df578063f711034f146102b85763fe029156146101e257600080fd5b346102b35760803660031901126102b3576101fb611a52565b610203611a68565b60443561020e61200f565b61021661204b565b61021e612075565b610229818385611c28565b9260643584106102a2576001600160a01b0316917f30b60ee4dc75c0fb04420331b13e9ad7f8ff8fc51eac9c97d36fb20ccbe09d669160409161026e8230338861215b565b6001600160a01b031694610283813388612408565b82519182526020820152a360016000805160206126cd83398151915255005b637294b85560e11b60005260046000fd5b600080fd5b346102b35760203660031901126102b3576001600160a01b036102d9611a52565b1680156103ce57806000526000602052604060002054156103bd576040516370a0823160e01b815230600482015290602082602481845afa9182156103b15760009261037a575b50670de0b6b3a7640000820291808304670de0b6b3a764000014901517156103645760209161035c916000526000835260406000205490611ba7565b604051908152f35b634e487b7160e01b600052601160045260246000fd5b90916020823d6020116103a9575b81610395602093836119d9565b810103126103a65750519082610320565b80fd5b3d9150610388565b6040513d6000823e3d90fd5b633dd1b30560e01b60005260046000fd5b63e6c4247b60e01b60005260046000fd5b346102b35760003660031901126102b357602060405160008051602061260d8339815191528152f35b346102b35760403660031901126102b357610421611a52565b61043261042c611a68565b91611ae2565b9060018060a01b03166000526020526020604060002054604051908152f35b346102b35760403660031901126102b357610487600435610470611a68565b9061048261047d82611b86565b612111565b612257565b005b346102b35760003660031901126102b35760405180602060015492838152018092600160005260206000209060005b81811061051a57505050816104ce9103826119d9565b6040519182916020830190602084525180915260408301919060005b8181106104f8575050500390f35b82516001600160a01b03168452859450602093840193909201916001016104ea565b82546001600160a01b03168452602090930192600192830192016104b8565b346102b35760003660031901126102b3576020604051670de0b6b3a76400008152f35b346102b35760003660031901126102b3576020600154604051908152f35b346102b35760003660031901126102b3576000806001545b8083106105a457602082604051908152f35b90602460206105b285611b1b565b90546040516370a0823160e01b81523060048201529384929091839160031b1c6001600160a01b03165afa9081156103b157600091610652575b50670de0b6b3a7640000810290808204670de0b6b3a76400001490151715610364576001916106436106499261062187611b1b565b868060a01b0391549060031b1c16600052600060205260406000205490611ba7565b90611cda565b92019190610592565b906020823d821161067b575b8161066b602093836119d9565b810103126103a6575051846105ec565b3d915061065e565b346102b35760203660031901126102b3576004356001548110156102b3576106ac602091611b1b565b905460405160039290921b1c6001600160a01b03168152f35b346102b35760403660031901126102b357602061035c6106e3611a52565b60243590611ce7565b346102b357602061035c6106ff36611aa8565b91611c28565b346102b35760403660031901126102b357602061035c610723611a52565b60243590611bc7565b346102b35761073a36611a7e565b61074261200f565b61074a61204b565b610752612075565b61075c8284611ce7565b90811161087157331561085b5760009133835260008051602061256d833981519152602052604083205493828510610840577f87941ed80175e66d99234a2a90bcf26c6dd49f0fd15c0fd5cb5d3d6acd9cabf791604091848733885260008051602061256d8339815191526020520383872055846000805160206125cd83398151915254036000805160206125cd8339815191525585835186815260008051602061262d83398151915260203392a36001600160a01b031693610820823387612408565b82519182526020820152a260016000805160206126cd8339815191525580f35b505060649263391434e360e21b835233600452602452604452fd5b634b637e8f60e11b600052600060045260246000fd5b638199f5f360e01b60005260046000fd5b346102b35760403660031901126102b3576108a861089e611a52565b60243590336121a6565b602060405160018152f35b346102b35760003660031901126102b357602060405160008152f35b346102b35760603660031901126102b3576108e8611a52565b6024359060443580151581036102b35761090061200f565b33600090815260008051602061250d833981519152602052604090205460ff16156109ad576001600160a01b0382169283156103ce57801561099c577f2e39961a70a10f4d46383948095ac2752b3ee642a7c76aa827410aaff08c2e519260209261096c833388612408565b61098d575b50604051908152a260016000805160206126cd83398151915255005b610996906122f7565b84610971565b631f2a200560e01b60005260046000fd5b63e2517d3f60e01b6000523360045260008051602061254d83398151915260245260446000fd5b346102b35760003660031901126102b35760405160006000805160206125ad83398151915254610a0381611b4c565b8084529060018116908115610a955750600114610a3b575b610a3783610a2b818503826119d9565b60405191829182611990565b0390f35b6000805160206125ad833981519152600090815260008051602061268d833981519152939250905b808210610a7b57509091508101602001610a2b610a1b565b919260018160209254838588010152019101909291610a63565b60ff191660208086019190915291151560051b84019091019150610a2b9050610a1b565b346102b35760403660031901126102b357610ad2611a68565b60043560005260008051602061264d83398151915260205260406000209060018060a01b0316600052602052602060ff604060002054166040519015158152f35b346102b35760003660031901126102b357610b2c6120c3565b610b3461204b565b600160ff1960008051602061266d83398151915254161760008051602061266d833981519152557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b346102b35760203660031901126102b357610ba0611a52565b610ba861200f565b610bb06120c3565b6040516370a0823160e01b81523060048201526020816024816001600160a01b0386165afa9081156103b157600091610c17575b50610c0657610bf2906122f7565b60016000805160206126cd83398151915255005b6341c0751160e01b60005260046000fd5b90506020813d602011610c41575b81610c32602093836119d9565b810103126102b3575182610be4565b3d9150610c25565b346102b35760003660031901126102b35760206040516000805160206126ed8339815191528152f35b346102b35760203660031901126102b3576001600160a01b03610c93611a52565b1660005260008051602061256d8339815191526020526020604060002054604051908152f35b346102b35760403660031901126102b357610cd2611a52565b60243590610cde61200f565b610ce66120c3565b6001600160a01b03169081156103ce57816000526000602052604060002054156103bd57670de0b6b3a764000081108015610d7f575b610d6e5760207f7f94fe4848c2990c2f0c69eca631abc9da62f0451ce92e2708b0e2f9b4e1aa4a91836000526000825280604060002055604051908152a260016000805160206126cd83398151915255005b63648564d360e01b60005260046000fd5b50816000526000602052604060002054811015610d1c565b346102b35760003660031901126102b357602060ff60008051602061266d83398151915254166040519015158152f35b346102b35760403660031901126102b357610de0611a52565b602435610deb61200f565b610df36120c3565b6001600160a01b0382169182156103ce57826000526000602052604060002054610f5557670de0b6b3a76400008210610d6e5760405163313ce56760e01b8152602081600481875afa9081156103b157600091610f14575b5060ff6012911603610f03578260005260006020528160406000205560015491600160401b831015610eed57610ed2602092610eae8560017ff4c563a3ea86ff1f4275e8c207df0375a51963f2b831b7bf4da8be938d92876c9701600155611b1b565b9080546001600160a01b0360039390931b83811b199091169290931690921b179055565b604051908152a260016000805160206126cd83398151915255005b634e487b7160e01b600052604160045260246000fd5b630692acc560e51b60005260046000fd5b6020813d602011610f4d575b81610f2d602093836119d9565b81010312610f4957519060ff821682036103a6575060ff610e4b565b5080fd5b3d9150610f20565b63c78e82ad60e01b60005260046000fd5b346102b35760203660031901126102b3576001600160a01b03610f87611a52565b1680156103ce57806000526000602052604060002054156103bd5760005260006020526020604060002054604051908152f35b346102b35760003660031901126102b357610fd36120c3565b60008051602061266d8339815191525460ff81161561102c5760ff191660008051602061266d833981519152557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b638dfc202b60e01b60005260046000fd5b346102b35760403660031901126102b357611056611a68565b336001600160a01b038216036110725761048790600435612257565b63334bd91960e11b60005260046000fd5b346102b35760003660031901126102b357602060405160128152f35b346102b35760403660031901126102b3576104876004356110be611a68565b906110cb61047d82611b86565b611f78565b346102b35760203660031901126102b3576001600160a01b036110f1611a52565b1660005260006020526020604060002054604051908152f35b346102b35760203660031901126102b357602061035c600435611b86565b346102b35761113636611aa8565b9061114083611ae2565b3360009081526020919091526040902054926000198410611166575b6108a893506121a6565b8284106111d9576001600160a01b038116156111c35733156111ad576108a89361118f82611ae2565b60018060a01b0333166000526020528360406000209103905561115c565b634a1406b160e11b600052600060045260246000fd5b63e602df0560e01b600052600060045260246000fd5b8284637dc7a0d960e11b6000523360045260245260445260646000fd5b346102b35760003660031901126102b357602060405160008051602061254d8339815191528152f35b346102b35760003660031901126102b35760206000805160206125cd83398151915254604051908152f35b346102b35761125836611a7e565b9161126161200f565b61126961204b565b611271612075565b61127b8282611bc7565b92831561099c5783106102a2576001600160a01b03169061129e8130338561215b565b331561134c5760407f1c83e520720711a18cf486e7e5a403bad3f020deb71d3326a4bbf507260e365f916112e1856000805160206125cd83398151915254611cda565b6000805160206125cd8339815191525560009433865260008051602061256d83398151915260205282862081815401905582518181528660008051602061262d83398151915260203393a382519182526020820152a260016000805160206126cd8339815191525580f35b63ec442f0560e01b600052600060045260246000fd5b346102b35760403660031901126102b35761137b611a52565b6024359033156111c3576001600160a01b03169081156111ad5761139e33611ae2565b82600052602052806040600020556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b346102b35760603660031901126102b3576004356001600160401b0381116102b3576114139036906004016119fc565b6024356001600160401b0381116102b3576114329036906004016119fc565b6044356001600160a01b038116918282036102b35760008051602061270d83398151915254604081901c60ff161593906001600160401b03811680159081611885575b600114908161187b575b159081611872575b50611861576001600160401b0319811660011760008051602061270d8339815191525584611838575b50156103ce576114be612443565b6114c6612443565b6114ce612443565b83516001600160401b038111610eed576114f660008051602061252d83398151915254611b4c565b601f81116117d8575b50602094601f82116001146117575794819293949560009261174c575b50508160011b916000199060031b1c19161760008051602061252d833981519152555b8051906001600160401b038211610eed576115686000805160206125ad83398151915254611b4c565b601f81116116ec575b50602090601f8311600114611665576115ff9392916000918361165a575b50508160011b916000199060031b1c1916176000805160206125ad833981519152555b6115ba612443565b6115c2612443565b6115ca612443565b60016000805160206126cd833981519152556115e581611d6a565b506115ef81611de6565b506115f981611e6c565b50611ef2565b5061160657005b60ff60401b1960008051602061270d833981519152541660008051602061270d833981519152557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b01519050858061158f565b90601f198316916000805160206125ad833981519152600052816000209260005b8181106116d457509160019391856115ff979694106116bb575b505050811b016000805160206125ad833981519152556115b2565b015160001960f88460031b161c191690558580806116a0565b92936020600181928786015181550195019301611686565b6000805160206125ad83398151915260005260008051602061268d833981519152601f840160051c81019160208510611742575b601f0160051c01905b8181106117365750611571565b60008155600101611729565b9091508190611720565b01519050858061151c565b601f1982169560008051602061252d833981519152600052806000209160005b8881106117c0575083600195969798106117a7575b505050811b0160008051602061252d8339815191525561153f565b015160001960f88460031b161c1916905585808061178c565b91926020600181928685015181550194019201611777565b60008051602061252d8339815191526000526000805160206124ed833981519152601f830160051c8101916020841061182e575b601f0160051c01905b81811061182257506114ff565b60008155600101611815565b909150819061180c565b6001600160481b0319166001600160401b011760008051602061270d83398151915255856114b0565b63f92ee8a960e01b60005260046000fd5b90501587611487565b303b15915061147f565b869150611475565b346102b35760003660031901126102b357604051600060008051602061252d833981519152546118bc81611b4c565b8084529060018116908115610a9557506001146118e357610a3783610a2b818503826119d9565b60008051602061252d83398151915260009081526000805160206124ed833981519152939250905b80821061192357509091508101602001610a2b610a1b565b91926001816020925483858801015201910190929161190b565b346102b35760203660031901126102b3576004359063ffffffff60e01b82168092036102b357602091637965db0b60e01b811490811561197f575b5015158152f35b6301ffc9a760e01b14905083611978565b91909160208152825180602083015260005b8181106119c3575060409293506000838284010152601f8019910116010190565b80602080928701015160408286010152016119a2565b601f909101601f19168101906001600160401b03821190821017610eed57604052565b81601f820112156102b3578035906001600160401b038211610eed5760405192611a30601f8401601f1916602001856119d9565b828452602083830101116102b357816000926020809301838601378301015290565b600435906001600160a01b03821682036102b357565b602435906001600160a01b03821682036102b357565b60609060031901126102b3576004356001600160a01b03811681036102b357906024359060443590565b60609060031901126102b3576004356001600160a01b03811681036102b357906024356001600160a01b03811681036102b3579060443590565b6001600160a01b031660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020526040902090565b600154811015611b3657600160005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b90600182811c92168015611b7c575b6020831014611b6657565b634e487b7160e01b600052602260045260246000fd5b91607f1691611b5b565b60005260008051602061264d83398151915260205260016040600020015490565b8115611bb1570490565b634e487b7160e01b600052601260045260246000fd5b6001600160a01b03169081156103ce57816000526000602052604060002054156103bd57801561099c57670de0b6b3a76400008102908104670de0b6b3a76400000361036457611c2591600052600060205260406000205490611ba7565b90565b6001600160a01b0316919082158015611cc9575b6103ce576001600160a01b0316828114611cb857826000526000602052604060002054156103bd57806000526000602052604060002054156103bd57811561099c5760005260006020526040600020548082029182040361036457611caf91600052600060205260406000205490611ba7565b90811561099c57565b63c1ab6dc160e01b60005260046000fd5b506001600160a01b03811615611c3c565b9190820180921161036457565b6001600160a01b03169081156103ce57816000526000602052604060002054156103bd57801561099c57670de0b6b3a76400008102908104670de0b6b3a76400000361036457611d469082600052600060205260406000205490611cda565b600019810190811161036457611caf91600052600060205260406000205490611ba7565b6001600160a01b03811660009081526000805160206125ed833981519152602052604090205460ff16611de0576001600160a01b031660008181526000805160206125ed83398151915260205260408120805460ff191660011790553391906000805160206124cd8339815191528180a4600190565b50600090565b6001600160a01b038116600090815260008051602061258d833981519152602052604090205460ff16611de0576001600160a01b0316600081815260008051602061258d83398151915260205260408120805460ff191660011790553391906000805160206126ed833981519152906000805160206124cd8339815191529080a4600190565b6001600160a01b03811660009081526000805160206126ad833981519152602052604090205460ff16611de0576001600160a01b031660008181526000805160206126ad83398151915260205260408120805460ff1916600117905533919060008051602061260d833981519152906000805160206124cd8339815191529080a4600190565b6001600160a01b038116600090815260008051602061250d833981519152602052604090205460ff16611de0576001600160a01b0316600081815260008051602061250d83398151915260205260408120805460ff1916600117905533919060008051602061254d833981519152906000805160206124cd8339815191529080a4600190565b600081815260008051602061264d833981519152602090815260408083206001600160a01b038616845290915290205460ff1661200857600081815260008051602061264d833981519152602090815260408083206001600160a01b0395909516808452949091528120805460ff19166001179055339291906000805160206124cd8339815191529080a4600190565b5050600090565b60026000805160206126cd833981519152541461203a5760026000805160206126cd83398151915255565b633ee5aeb560e01b60005260046000fd5b60ff60008051602061266d833981519152541661206457565b63d93c066560e01b60005260046000fd5b3360009081526000805160206126ad833981519152602052604090205460ff161561209c57565b63e2517d3f60e01b6000523360045260008051602061260d83398151915260245260446000fd5b33600090815260008051602061258d833981519152602052604090205460ff16156120ea57565b63e2517d3f60e01b600052336004526000805160206126ed83398151915260245260446000fd5b600081815260008051602061264d8339815191526020908152604080832033845290915290205460ff16156121435750565b63e2517d3f60e01b6000523360045260245260446000fd5b6040516323b872dd60e01b60208201526001600160a01b0392831660248201529290911660448301526064808301939093529181526121a49161219f6084836119d9565b612471565b565b6001600160a01b031690811561085b576001600160a01b031691821561134c57600082815260008051602061256d833981519152602052604081205482811061223d57916040828260008051602061262d83398151915295876020965260008051602061256d8339815191528652038282205586815260008051602061256d833981519152845220818154019055604051908152a3565b916064928463391434e360e21b8452600452602452604452fd5b600081815260008051602061264d833981519152602090815260408083206001600160a01b038616845290915290205460ff161561200857600081815260008051602061264d833981519152602090815260408083206001600160a01b0395909516808452949091528120805460ff19169055339291907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9080a4600190565b6001600160a01b031680156103ce57806000526000602052604060002054156103bd578060005260006020526000604081205560005b6001549081811015612401578261234382611b1b565b905460039190911b1c6001600160a01b03161461236457600191500161232d565b600019820191821161036457610eae61237f61239793611b1b565b905460039190911b1c6001600160a01b031691611b1b565b60015480156123eb57600019016123ad81611b1b565b81549060018060a01b039060031b1b191690556001555b7f4c910b69fe65a61f7531b9c5042b2329ca7179c77290aa7e2eb3afa3c8511fd3600080a2565b634e487b7160e01b600052603160045260246000fd5b50506123c4565b60405163a9059cbb60e01b60208201526001600160a01b0390921660248301526044808301939093529181526121a49161219f6064836119d9565b60ff60008051602061270d8339815191525460401c161561246057565b631afcd79f60e31b60005260046000fd5b906000602091828151910182855af1156103b1576000513d6124c357506001600160a01b0381163b155b6124a25750565b635274afe760e01b60009081526001600160a01b0391909116600452602490fd5b6001141561249b56fe2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d2ae08a8e29253f69ac5d979a101956ab8f8d9d7ded63fa7a83b16fc47648eab0762c7c328dd70a077c65c77b60e4c38eed3d2f6aa056d4d0fa114aeff8234b5652c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace03bf233dd2aafeb4d50879c4aa5c81e96d92f6e6945c906a58f9f2d1c1631b4b2652c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00b16e88c42fd4e48df2dd6a2eabd6bc9aec654ec170056b470819f8892cc6431c52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0452c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02b7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800cd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330046a2803e59a4de4e7a4c574b1243f25977ac4c77d5a1a4a609b5394cebb4a2aa06484cc59dc38e4f67c31122333a17ca81b3ca18cdf02bfc298072fa52b0316a9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a26469706673582212207a1a3b9c643b64915b6170d741abd13b4576fb9970c7f3f5684c40d5b7d0e5b864736f6c634300081e0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"paris","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":true,"runs":1},"outputSelection":{"*":{"":["*"],"*":["*"]}},"viaIR":true},"optimization_runs":1,"sourcify_repo_url":null,"decoded_constructor_args":null,"compiler_version":"v0.8.30+commit.73712a01","is_verified_via_verifier_alliance":false,"verified_at":"2025-12-11T02:17:23.741686Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x6080806040523460d2577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c1660c1576002600160401b03196001600160401b03821601605c575b60405161276290816100d88239f35b6001600160401b0319166001600160401b039081177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005581527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a13880604d565b63f92ee8a960e01b60005260046000fd5b600080fdfe608080604052600436101561001357600080fd5b60003560e01c90816301ffc9a71461193d5750806306fdde031461188d578063077f224a146113e3578063095ea7b3146113625780630efe6a8b1461124a57806318160ddd1461121f57806320df4359146111f657806323b872dd14611128578063248a9ca31461110a57806324c71ece146110d05780632f2ff15d1461109f578063313ce5671461108357806336568abe1461103d5780633f4ba83a14610fba57806344bad40214610f665780634d8e3d3b14610dc75780635c975abb14610d975780636945a10c14610cb957806370a0823114610c7257806375b238fc14610c495780637631919014610b875780638456cb5914610b1357806391d1485414610ab957806395d89b41146109d45780639d911465146108cf578063a217fddf146108b3578063a9059cbb14610882578063b5c5f6721461072c578063b8f82b2614610705578063bbbaffab146106ec578063bbc6f1dc146106c5578063c625562614610683578063cb765c1d1461057a578063ce67be261461055c578063d32867d014610539578063d3c7c2c714610489578063d547741f14610451578063dd62ed3e14610408578063ec87621c146103df578063f711034f146102b85763fe029156146101e257600080fd5b346102b35760803660031901126102b3576101fb611a52565b610203611a68565b60443561020e61200f565b61021661204b565b61021e612075565b610229818385611c28565b9260643584106102a2576001600160a01b0316917f30b60ee4dc75c0fb04420331b13e9ad7f8ff8fc51eac9c97d36fb20ccbe09d669160409161026e8230338861215b565b6001600160a01b031694610283813388612408565b82519182526020820152a360016000805160206126cd83398151915255005b637294b85560e11b60005260046000fd5b600080fd5b346102b35760203660031901126102b3576001600160a01b036102d9611a52565b1680156103ce57806000526000602052604060002054156103bd576040516370a0823160e01b815230600482015290602082602481845afa9182156103b15760009261037a575b50670de0b6b3a7640000820291808304670de0b6b3a764000014901517156103645760209161035c916000526000835260406000205490611ba7565b604051908152f35b634e487b7160e01b600052601160045260246000fd5b90916020823d6020116103a9575b81610395602093836119d9565b810103126103a65750519082610320565b80fd5b3d9150610388565b6040513d6000823e3d90fd5b633dd1b30560e01b60005260046000fd5b63e6c4247b60e01b60005260046000fd5b346102b35760003660031901126102b357602060405160008051602061260d8339815191528152f35b346102b35760403660031901126102b357610421611a52565b61043261042c611a68565b91611ae2565b9060018060a01b03166000526020526020604060002054604051908152f35b346102b35760403660031901126102b357610487600435610470611a68565b9061048261047d82611b86565b612111565b612257565b005b346102b35760003660031901126102b35760405180602060015492838152018092600160005260206000209060005b81811061051a57505050816104ce9103826119d9565b6040519182916020830190602084525180915260408301919060005b8181106104f8575050500390f35b82516001600160a01b03168452859450602093840193909201916001016104ea565b82546001600160a01b03168452602090930192600192830192016104b8565b346102b35760003660031901126102b3576020604051670de0b6b3a76400008152f35b346102b35760003660031901126102b3576020600154604051908152f35b346102b35760003660031901126102b3576000806001545b8083106105a457602082604051908152f35b90602460206105b285611b1b565b90546040516370a0823160e01b81523060048201529384929091839160031b1c6001600160a01b03165afa9081156103b157600091610652575b50670de0b6b3a7640000810290808204670de0b6b3a76400001490151715610364576001916106436106499261062187611b1b565b868060a01b0391549060031b1c16600052600060205260406000205490611ba7565b90611cda565b92019190610592565b906020823d821161067b575b8161066b602093836119d9565b810103126103a6575051846105ec565b3d915061065e565b346102b35760203660031901126102b3576004356001548110156102b3576106ac602091611b1b565b905460405160039290921b1c6001600160a01b03168152f35b346102b35760403660031901126102b357602061035c6106e3611a52565b60243590611ce7565b346102b357602061035c6106ff36611aa8565b91611c28565b346102b35760403660031901126102b357602061035c610723611a52565b60243590611bc7565b346102b35761073a36611a7e565b61074261200f565b61074a61204b565b610752612075565b61075c8284611ce7565b90811161087157331561085b5760009133835260008051602061256d833981519152602052604083205493828510610840577f87941ed80175e66d99234a2a90bcf26c6dd49f0fd15c0fd5cb5d3d6acd9cabf791604091848733885260008051602061256d8339815191526020520383872055846000805160206125cd83398151915254036000805160206125cd8339815191525585835186815260008051602061262d83398151915260203392a36001600160a01b031693610820823387612408565b82519182526020820152a260016000805160206126cd8339815191525580f35b505060649263391434e360e21b835233600452602452604452fd5b634b637e8f60e11b600052600060045260246000fd5b638199f5f360e01b60005260046000fd5b346102b35760403660031901126102b3576108a861089e611a52565b60243590336121a6565b602060405160018152f35b346102b35760003660031901126102b357602060405160008152f35b346102b35760603660031901126102b3576108e8611a52565b6024359060443580151581036102b35761090061200f565b33600090815260008051602061250d833981519152602052604090205460ff16156109ad576001600160a01b0382169283156103ce57801561099c577f2e39961a70a10f4d46383948095ac2752b3ee642a7c76aa827410aaff08c2e519260209261096c833388612408565b61098d575b50604051908152a260016000805160206126cd83398151915255005b610996906122f7565b84610971565b631f2a200560e01b60005260046000fd5b63e2517d3f60e01b6000523360045260008051602061254d83398151915260245260446000fd5b346102b35760003660031901126102b35760405160006000805160206125ad83398151915254610a0381611b4c565b8084529060018116908115610a955750600114610a3b575b610a3783610a2b818503826119d9565b60405191829182611990565b0390f35b6000805160206125ad833981519152600090815260008051602061268d833981519152939250905b808210610a7b57509091508101602001610a2b610a1b565b919260018160209254838588010152019101909291610a63565b60ff191660208086019190915291151560051b84019091019150610a2b9050610a1b565b346102b35760403660031901126102b357610ad2611a68565b60043560005260008051602061264d83398151915260205260406000209060018060a01b0316600052602052602060ff604060002054166040519015158152f35b346102b35760003660031901126102b357610b2c6120c3565b610b3461204b565b600160ff1960008051602061266d83398151915254161760008051602061266d833981519152557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b346102b35760203660031901126102b357610ba0611a52565b610ba861200f565b610bb06120c3565b6040516370a0823160e01b81523060048201526020816024816001600160a01b0386165afa9081156103b157600091610c17575b50610c0657610bf2906122f7565b60016000805160206126cd83398151915255005b6341c0751160e01b60005260046000fd5b90506020813d602011610c41575b81610c32602093836119d9565b810103126102b3575182610be4565b3d9150610c25565b346102b35760003660031901126102b35760206040516000805160206126ed8339815191528152f35b346102b35760203660031901126102b3576001600160a01b03610c93611a52565b1660005260008051602061256d8339815191526020526020604060002054604051908152f35b346102b35760403660031901126102b357610cd2611a52565b60243590610cde61200f565b610ce66120c3565b6001600160a01b03169081156103ce57816000526000602052604060002054156103bd57670de0b6b3a764000081108015610d7f575b610d6e5760207f7f94fe4848c2990c2f0c69eca631abc9da62f0451ce92e2708b0e2f9b4e1aa4a91836000526000825280604060002055604051908152a260016000805160206126cd83398151915255005b63648564d360e01b60005260046000fd5b50816000526000602052604060002054811015610d1c565b346102b35760003660031901126102b357602060ff60008051602061266d83398151915254166040519015158152f35b346102b35760403660031901126102b357610de0611a52565b602435610deb61200f565b610df36120c3565b6001600160a01b0382169182156103ce57826000526000602052604060002054610f5557670de0b6b3a76400008210610d6e5760405163313ce56760e01b8152602081600481875afa9081156103b157600091610f14575b5060ff6012911603610f03578260005260006020528160406000205560015491600160401b831015610eed57610ed2602092610eae8560017ff4c563a3ea86ff1f4275e8c207df0375a51963f2b831b7bf4da8be938d92876c9701600155611b1b565b9080546001600160a01b0360039390931b83811b199091169290931690921b179055565b604051908152a260016000805160206126cd83398151915255005b634e487b7160e01b600052604160045260246000fd5b630692acc560e51b60005260046000fd5b6020813d602011610f4d575b81610f2d602093836119d9565b81010312610f4957519060ff821682036103a6575060ff610e4b565b5080fd5b3d9150610f20565b63c78e82ad60e01b60005260046000fd5b346102b35760203660031901126102b3576001600160a01b03610f87611a52565b1680156103ce57806000526000602052604060002054156103bd5760005260006020526020604060002054604051908152f35b346102b35760003660031901126102b357610fd36120c3565b60008051602061266d8339815191525460ff81161561102c5760ff191660008051602061266d833981519152557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b638dfc202b60e01b60005260046000fd5b346102b35760403660031901126102b357611056611a68565b336001600160a01b038216036110725761048790600435612257565b63334bd91960e11b60005260046000fd5b346102b35760003660031901126102b357602060405160128152f35b346102b35760403660031901126102b3576104876004356110be611a68565b906110cb61047d82611b86565b611f78565b346102b35760203660031901126102b3576001600160a01b036110f1611a52565b1660005260006020526020604060002054604051908152f35b346102b35760203660031901126102b357602061035c600435611b86565b346102b35761113636611aa8565b9061114083611ae2565b3360009081526020919091526040902054926000198410611166575b6108a893506121a6565b8284106111d9576001600160a01b038116156111c35733156111ad576108a89361118f82611ae2565b60018060a01b0333166000526020528360406000209103905561115c565b634a1406b160e11b600052600060045260246000fd5b63e602df0560e01b600052600060045260246000fd5b8284637dc7a0d960e11b6000523360045260245260445260646000fd5b346102b35760003660031901126102b357602060405160008051602061254d8339815191528152f35b346102b35760003660031901126102b35760206000805160206125cd83398151915254604051908152f35b346102b35761125836611a7e565b9161126161200f565b61126961204b565b611271612075565b61127b8282611bc7565b92831561099c5783106102a2576001600160a01b03169061129e8130338561215b565b331561134c5760407f1c83e520720711a18cf486e7e5a403bad3f020deb71d3326a4bbf507260e365f916112e1856000805160206125cd83398151915254611cda565b6000805160206125cd8339815191525560009433865260008051602061256d83398151915260205282862081815401905582518181528660008051602061262d83398151915260203393a382519182526020820152a260016000805160206126cd8339815191525580f35b63ec442f0560e01b600052600060045260246000fd5b346102b35760403660031901126102b35761137b611a52565b6024359033156111c3576001600160a01b03169081156111ad5761139e33611ae2565b82600052602052806040600020556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b346102b35760603660031901126102b3576004356001600160401b0381116102b3576114139036906004016119fc565b6024356001600160401b0381116102b3576114329036906004016119fc565b6044356001600160a01b038116918282036102b35760008051602061270d83398151915254604081901c60ff161593906001600160401b03811680159081611885575b600114908161187b575b159081611872575b50611861576001600160401b0319811660011760008051602061270d8339815191525584611838575b50156103ce576114be612443565b6114c6612443565b6114ce612443565b83516001600160401b038111610eed576114f660008051602061252d83398151915254611b4c565b601f81116117d8575b50602094601f82116001146117575794819293949560009261174c575b50508160011b916000199060031b1c19161760008051602061252d833981519152555b8051906001600160401b038211610eed576115686000805160206125ad83398151915254611b4c565b601f81116116ec575b50602090601f8311600114611665576115ff9392916000918361165a575b50508160011b916000199060031b1c1916176000805160206125ad833981519152555b6115ba612443565b6115c2612443565b6115ca612443565b60016000805160206126cd833981519152556115e581611d6a565b506115ef81611de6565b506115f981611e6c565b50611ef2565b5061160657005b60ff60401b1960008051602061270d833981519152541660008051602061270d833981519152557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b01519050858061158f565b90601f198316916000805160206125ad833981519152600052816000209260005b8181106116d457509160019391856115ff979694106116bb575b505050811b016000805160206125ad833981519152556115b2565b015160001960f88460031b161c191690558580806116a0565b92936020600181928786015181550195019301611686565b6000805160206125ad83398151915260005260008051602061268d833981519152601f840160051c81019160208510611742575b601f0160051c01905b8181106117365750611571565b60008155600101611729565b9091508190611720565b01519050858061151c565b601f1982169560008051602061252d833981519152600052806000209160005b8881106117c0575083600195969798106117a7575b505050811b0160008051602061252d8339815191525561153f565b015160001960f88460031b161c1916905585808061178c565b91926020600181928685015181550194019201611777565b60008051602061252d8339815191526000526000805160206124ed833981519152601f830160051c8101916020841061182e575b601f0160051c01905b81811061182257506114ff565b60008155600101611815565b909150819061180c565b6001600160481b0319166001600160401b011760008051602061270d83398151915255856114b0565b63f92ee8a960e01b60005260046000fd5b90501587611487565b303b15915061147f565b869150611475565b346102b35760003660031901126102b357604051600060008051602061252d833981519152546118bc81611b4c565b8084529060018116908115610a9557506001146118e357610a3783610a2b818503826119d9565b60008051602061252d83398151915260009081526000805160206124ed833981519152939250905b80821061192357509091508101602001610a2b610a1b565b91926001816020925483858801015201910190929161190b565b346102b35760203660031901126102b3576004359063ffffffff60e01b82168092036102b357602091637965db0b60e01b811490811561197f575b5015158152f35b6301ffc9a760e01b14905083611978565b91909160208152825180602083015260005b8181106119c3575060409293506000838284010152601f8019910116010190565b80602080928701015160408286010152016119a2565b601f909101601f19168101906001600160401b03821190821017610eed57604052565b81601f820112156102b3578035906001600160401b038211610eed5760405192611a30601f8401601f1916602001856119d9565b828452602083830101116102b357816000926020809301838601378301015290565b600435906001600160a01b03821682036102b357565b602435906001600160a01b03821682036102b357565b60609060031901126102b3576004356001600160a01b03811681036102b357906024359060443590565b60609060031901126102b3576004356001600160a01b03811681036102b357906024356001600160a01b03811681036102b3579060443590565b6001600160a01b031660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020526040902090565b600154811015611b3657600160005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b90600182811c92168015611b7c575b6020831014611b6657565b634e487b7160e01b600052602260045260246000fd5b91607f1691611b5b565b60005260008051602061264d83398151915260205260016040600020015490565b8115611bb1570490565b634e487b7160e01b600052601260045260246000fd5b6001600160a01b03169081156103ce57816000526000602052604060002054156103bd57801561099c57670de0b6b3a76400008102908104670de0b6b3a76400000361036457611c2591600052600060205260406000205490611ba7565b90565b6001600160a01b0316919082158015611cc9575b6103ce576001600160a01b0316828114611cb857826000526000602052604060002054156103bd57806000526000602052604060002054156103bd57811561099c5760005260006020526040600020548082029182040361036457611caf91600052600060205260406000205490611ba7565b90811561099c57565b63c1ab6dc160e01b60005260046000fd5b506001600160a01b03811615611c3c565b9190820180921161036457565b6001600160a01b03169081156103ce57816000526000602052604060002054156103bd57801561099c57670de0b6b3a76400008102908104670de0b6b3a76400000361036457611d469082600052600060205260406000205490611cda565b600019810190811161036457611caf91600052600060205260406000205490611ba7565b6001600160a01b03811660009081526000805160206125ed833981519152602052604090205460ff16611de0576001600160a01b031660008181526000805160206125ed83398151915260205260408120805460ff191660011790553391906000805160206124cd8339815191528180a4600190565b50600090565b6001600160a01b038116600090815260008051602061258d833981519152602052604090205460ff16611de0576001600160a01b0316600081815260008051602061258d83398151915260205260408120805460ff191660011790553391906000805160206126ed833981519152906000805160206124cd8339815191529080a4600190565b6001600160a01b03811660009081526000805160206126ad833981519152602052604090205460ff16611de0576001600160a01b031660008181526000805160206126ad83398151915260205260408120805460ff1916600117905533919060008051602061260d833981519152906000805160206124cd8339815191529080a4600190565b6001600160a01b038116600090815260008051602061250d833981519152602052604090205460ff16611de0576001600160a01b0316600081815260008051602061250d83398151915260205260408120805460ff1916600117905533919060008051602061254d833981519152906000805160206124cd8339815191529080a4600190565b600081815260008051602061264d833981519152602090815260408083206001600160a01b038616845290915290205460ff1661200857600081815260008051602061264d833981519152602090815260408083206001600160a01b0395909516808452949091528120805460ff19166001179055339291906000805160206124cd8339815191529080a4600190565b5050600090565b60026000805160206126cd833981519152541461203a5760026000805160206126cd83398151915255565b633ee5aeb560e01b60005260046000fd5b60ff60008051602061266d833981519152541661206457565b63d93c066560e01b60005260046000fd5b3360009081526000805160206126ad833981519152602052604090205460ff161561209c57565b63e2517d3f60e01b6000523360045260008051602061260d83398151915260245260446000fd5b33600090815260008051602061258d833981519152602052604090205460ff16156120ea57565b63e2517d3f60e01b600052336004526000805160206126ed83398151915260245260446000fd5b600081815260008051602061264d8339815191526020908152604080832033845290915290205460ff16156121435750565b63e2517d3f60e01b6000523360045260245260446000fd5b6040516323b872dd60e01b60208201526001600160a01b0392831660248201529290911660448301526064808301939093529181526121a49161219f6084836119d9565b612471565b565b6001600160a01b031690811561085b576001600160a01b031691821561134c57600082815260008051602061256d833981519152602052604081205482811061223d57916040828260008051602061262d83398151915295876020965260008051602061256d8339815191528652038282205586815260008051602061256d833981519152845220818154019055604051908152a3565b916064928463391434e360e21b8452600452602452604452fd5b600081815260008051602061264d833981519152602090815260408083206001600160a01b038616845290915290205460ff161561200857600081815260008051602061264d833981519152602090815260408083206001600160a01b0395909516808452949091528120805460ff19169055339291907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9080a4600190565b6001600160a01b031680156103ce57806000526000602052604060002054156103bd578060005260006020526000604081205560005b6001549081811015612401578261234382611b1b565b905460039190911b1c6001600160a01b03161461236457600191500161232d565b600019820191821161036457610eae61237f61239793611b1b565b905460039190911b1c6001600160a01b031691611b1b565b60015480156123eb57600019016123ad81611b1b565b81549060018060a01b039060031b1b191690556001555b7f4c910b69fe65a61f7531b9c5042b2329ca7179c77290aa7e2eb3afa3c8511fd3600080a2565b634e487b7160e01b600052603160045260246000fd5b50506123c4565b60405163a9059cbb60e01b60208201526001600160a01b0390921660248301526044808301939093529181526121a49161219f6064836119d9565b60ff60008051602061270d8339815191525460401c161561246057565b631afcd79f60e31b60005260046000fd5b906000602091828151910182855af1156103b1576000513d6124c357506001600160a01b0381163b155b6124a25750565b635274afe760e01b60009081526001600160a01b0391909116600452602490fd5b6001141561249b56fe2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d2ae08a8e29253f69ac5d979a101956ab8f8d9d7ded63fa7a83b16fc47648eab0762c7c328dd70a077c65c77b60e4c38eed3d2f6aa056d4d0fa114aeff8234b5652c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace03bf233dd2aafeb4d50879c4aa5c81e96d92f6e6945c906a58f9f2d1c1631b4b2652c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00b16e88c42fd4e48df2dd6a2eabd6bc9aec654ec170056b470819f8892cc6431c52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0452c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02b7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800cd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330046a2803e59a4de4e7a4c574b1243f25977ac4c77d5a1a4a609b5394cebb4a2aa06484cc59dc38e4f67c31122333a17ca81b3ca18cdf02bfc298072fa52b0316a9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a26469706673582212207a1a3b9c643b64915b6170d741abd13b4576fb9970c7f3f5684c40d5b7d0e5b864736f6c634300081e0033","name":"TokenBlender","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":false,"language":"solidity","evm_version":"paris","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.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 \"@openzeppelin/contracts/access/IAccessControl.sol\";\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport {ERC165Upgradeable} from \"../utils/introspection/ERC165Upgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.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 AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControl, ERC165Upgradeable {\n    struct RoleData {\n        mapping(address account => bool) hasRole;\n        bytes32 adminRole;\n    }\n\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n\n    /// @custom:storage-location erc7201:openzeppelin.storage.AccessControl\n    struct AccessControlStorage {\n        mapping(bytes32 role => RoleData) _roles;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.AccessControl\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant AccessControlStorageLocation = 0x02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800;\n\n    function _getAccessControlStorage() private pure returns (AccessControlStorage storage $) {\n        assembly {\n            $.slot := AccessControlStorageLocation\n        }\n    }\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    function __AccessControl_init() internal onlyInitializing {\n    }\n\n    function __AccessControl_init_unchained() internal onlyInitializing {\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        AccessControlStorage storage $ = _getAccessControlStorage();\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        AccessControlStorage storage $ = _getAccessControlStorage();\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        AccessControlStorage storage $ = _getAccessControlStorage();\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        AccessControlStorage storage $ = _getAccessControlStorage();\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        AccessControlStorage storage $ = _getAccessControlStorage();\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-upgradeable/proxy/utils/Initializable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Storage of the initializable contract.\n     *\n     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n     * when using with upgradeable contracts.\n     *\n     * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n     */\n    struct InitializableStorage {\n        /**\n         * @dev Indicates that the contract has been initialized.\n         */\n        uint64 _initialized;\n        /**\n         * @dev Indicates that the contract is in the process of being initialized.\n         */\n        bool _initializing;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n    /**\n     * @dev The contract is already initialized.\n     */\n    error InvalidInitialization();\n\n    /**\n     * @dev The contract is not initializing.\n     */\n    error NotInitializing();\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint64 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n     * production.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        // Cache values to avoid duplicated sloads\n        bool isTopLevelCall = !$._initializing;\n        uint64 initialized = $._initialized;\n\n        // Allowed calls:\n        // - initialSetup: the contract is not in the initializing state and no previous version was\n        //                 initialized\n        // - construction: the contract is initialized at version 1 (no reinitialization) and the\n        //                 current contract is just being deployed\n        bool initialSetup = initialized == 0 && isTopLevelCall;\n        bool construction = initialized == 1 && address(this).code.length == 0;\n\n        if (!initialSetup && !construction) {\n            revert InvalidInitialization();\n        }\n        $._initialized = 1;\n        if (isTopLevelCall) {\n            $._initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            $._initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint64 version) {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing || $._initialized >= version) {\n            revert InvalidInitialization();\n        }\n        $._initialized = version;\n        $._initializing = true;\n        _;\n        $._initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        _checkInitializing();\n        _;\n    }\n\n    /**\n     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n     */\n    function _checkInitializing() internal view virtual {\n        if (!_isInitializing()) {\n            revert NotInitializing();\n        }\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing) {\n            revert InvalidInitialization();\n        }\n        if ($._initialized != type(uint64).max) {\n            $._initialized = type(uint64).max;\n            emit Initialized(type(uint64).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint64) {\n        return _getInitializableStorage()._initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _getInitializableStorage()._initializing;\n    }\n\n    /**\n     * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.\n     *\n     * NOTE: Consider following the ERC-7201 formula to derive storage locations.\n     */\n    function _initializableStorageSlot() internal pure virtual returns (bytes32) {\n        return INITIALIZABLE_STORAGE;\n    }\n\n    /**\n     * @dev Returns a pointer to the storage namespace.\n     */\n    // solhint-disable-next-line var-name-mixedcase\n    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n        bytes32 slot = _initializableStorageSlot();\n        assembly {\n            $.slot := slot\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IERC20Metadata} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport {ContextUpgradeable} from \"../../utils/ContextUpgradeable.sol\";\nimport {IERC20Errors} from \"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\";\nimport {Initializable} from \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC-20\n * applications.\n */\nabstract contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20, IERC20Metadata, IERC20Errors {\n    /// @custom:storage-location erc7201:openzeppelin.storage.ERC20\n    struct ERC20Storage {\n        mapping(address account => uint256) _balances;\n\n        mapping(address account => mapping(address spender => uint256)) _allowances;\n\n        uint256 _totalSupply;\n\n        string _name;\n        string _symbol;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ERC20\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00;\n\n    function _getERC20Storage() private pure returns (ERC20Storage storage $) {\n        assembly {\n            $.slot := ERC20StorageLocation\n        }\n    }\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * Both values are immutable: they can only be set once during construction.\n     */\n    function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {\n        __ERC20_init_unchained(name_, symbol_);\n    }\n\n    function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n        ERC20Storage storage $ = _getERC20Storage();\n        $._name = name_;\n        $._symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual returns (string memory) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $._name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual returns (string memory) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $._symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the default value returned by this function, unless\n     * it's overridden.\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual returns (uint8) {\n        return 18;\n    }\n\n    /// @inheritdoc IERC20\n    function totalSupply() public view virtual returns (uint256) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $._totalSupply;\n    }\n\n    /// @inheritdoc IERC20\n    function balanceOf(address account) public view virtual returns (uint256) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $._balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - the caller must have a balance of at least `value`.\n     */\n    function transfer(address to, uint256 value) public virtual returns (bool) {\n        address owner = _msgSender();\n        _transfer(owner, to, value);\n        return true;\n    }\n\n    /// @inheritdoc IERC20\n    function allowance(address owner, address spender) public view virtual returns (uint256) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $._allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 value) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, value);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Skips emitting an {Approval} event indicating an allowance update. This is not\n     * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].\n     *\n     * NOTE: Does not update the allowance if the current allowance\n     * is the maximum `uint256`.\n     *\n     * Requirements:\n     *\n     * - `from` and `to` cannot be the zero address.\n     * - `from` must have a balance of at least `value`.\n     * - the caller must have allowance for ``from``'s tokens of at least\n     * `value`.\n     */\n    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(from, spender, value);\n        _transfer(from, to, value);\n        return true;\n    }\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead.\n     */\n    function _transfer(address from, address to, uint256 value) internal {\n        if (from == address(0)) {\n            revert ERC20InvalidSender(address(0));\n        }\n        if (to == address(0)) {\n            revert ERC20InvalidReceiver(address(0));\n        }\n        _update(from, to, value);\n    }\n\n    /**\n     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`\n     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding\n     * this function.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _update(address from, address to, uint256 value) internal virtual {\n        ERC20Storage storage $ = _getERC20Storage();\n        if (from == address(0)) {\n            // Overflow check required: The rest of the code assumes that totalSupply never overflows\n            $._totalSupply += value;\n        } else {\n            uint256 fromBalance = $._balances[from];\n            if (fromBalance < value) {\n                revert ERC20InsufficientBalance(from, fromBalance, value);\n            }\n            unchecked {\n                // Overflow not possible: value <= fromBalance <= totalSupply.\n                $._balances[from] = fromBalance - value;\n            }\n        }\n\n        if (to == address(0)) {\n            unchecked {\n                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.\n                $._totalSupply -= value;\n            }\n        } else {\n            unchecked {\n                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.\n                $._balances[to] += value;\n            }\n        }\n\n        emit Transfer(from, to, value);\n    }\n\n    /**\n     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).\n     * Relies on the `_update` mechanism\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead.\n     */\n    function _mint(address account, uint256 value) internal {\n        if (account == address(0)) {\n            revert ERC20InvalidReceiver(address(0));\n        }\n        _update(address(0), account, value);\n    }\n\n    /**\n     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.\n     * Relies on the `_update` mechanism.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * NOTE: This function is not virtual, {_update} should be overridden instead\n     */\n    function _burn(address account, uint256 value) internal {\n        if (account == address(0)) {\n            revert ERC20InvalidSender(address(0));\n        }\n        _update(account, address(0), value);\n    }\n\n    /**\n     * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     *\n     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\n     */\n    function _approve(address owner, address spender, uint256 value) internal {\n        _approve(owner, spender, value, true);\n    }\n\n    /**\n     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.\n     *\n     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by\n     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any\n     * `Approval` event during `transferFrom` operations.\n     *\n     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to\n     * true using the following override:\n     *\n     * ```solidity\n     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {\n     *     super._approve(owner, spender, value, true);\n     * }\n     * ```\n     *\n     * Requirements are the same as {_approve}.\n     */\n    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {\n        ERC20Storage storage $ = _getERC20Storage();\n        if (owner == address(0)) {\n            revert ERC20InvalidApprover(address(0));\n        }\n        if (spender == address(0)) {\n            revert ERC20InvalidSpender(address(0));\n        }\n        $._allowances[owner][spender] = value;\n        if (emitEvent) {\n            emit Approval(owner, spender, value);\n        }\n    }\n\n    /**\n     * @dev Updates `owner`'s allowance for `spender` based on spent `value`.\n     *\n     * Does not update the allowance value in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Does not emit an {Approval} event.\n     */\n    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance < type(uint256).max) {\n            if (currentAllowance < value) {\n                revert ERC20InsufficientAllowance(spender, currentAllowance, value);\n            }\n            unchecked {\n                _approve(owner, spender, currentAllowance - value, false);\n            }\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\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-upgradeable/utils/PausableUpgradeable.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 {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.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 PausableUpgradeable is Initializable, ContextUpgradeable {\n    /// @custom:storage-location erc7201:openzeppelin.storage.Pausable\n    struct PausableStorage {\n        bool _paused;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Pausable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300;\n\n    function _getPausableStorage() private pure returns (PausableStorage storage $) {\n        assembly {\n            $.slot := PausableStorageLocation\n        }\n    }\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    function __Pausable_init() internal onlyInitializing {\n    }\n\n    function __Pausable_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        PausableStorage storage $ = _getPausableStorage();\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        PausableStorage storage $ = _getPausableStorage();\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        PausableStorage storage $ = _getPausableStorage();\n        $._paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\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 ReentrancyGuardUpgradeable is Initializable {\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    /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard\n    struct ReentrancyGuardStorage {\n        uint256 _status;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n    function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) {\n        assembly {\n            $.slot := ReentrancyGuardStorageLocation\n        }\n    }\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\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        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\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        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\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        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        return $._status == ENTERED;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.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 \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport {Initializable} from \"../../proxy/utils/Initializable.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 ERC165Upgradeable is Initializable, IERC165 {\n    function __ERC165_init() internal onlyInitializing {\n    }\n\n    function __ERC165_init_unchained() internal onlyInitializing {\n    }\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/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/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/draft-IERC6093.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC6093.sol)\npragma solidity >=0.8.4;\n\n/**\n * @dev Standard ERC-20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\n */\ninterface IERC20Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC20InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC20InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     * @param allowance Amount of tokens a `spender` is allowed to operate with.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC20InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC-721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\n */\ninterface IERC721Errors {\n    /**\n     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\n     * Used in balance queries.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721InvalidOwner(address owner);\n\n    /**\n     * @dev Indicates a `tokenId` whose `owner` is the zero address.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721NonexistentToken(uint256 tokenId);\n\n    /**\n     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param tokenId Identifier number of a token.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC721InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC721InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC721InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC-1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\n */\ninterface IERC1155Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC1155InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC1155InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC1155MissingApprovalForAll(address operator, address owner);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC1155InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC1155InvalidOperator(address operator);\n\n    /**\n     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n     * Used in batch transfers.\n     * @param idsLength Length of the array of token identifiers\n     * @param valuesLength Length of the array of token amounts\n     */\n    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n"},{"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/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"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"InsufficientAmountOut","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidDecimals","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidRatio","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"SlippageExceeded","type":"error"},{"inputs":[],"name":"TokenAlreadySupported","type":"error"},{"inputs":[],"name":"TokenHasBalance","type":"error"},{"inputs":[],"name":"TokenNotSupported","type":"error"},{"inputs":[],"name":"ZeroAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","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":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"ratio","type":"uint256"}],"name":"TokenAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"TokenDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"newRatio","type":"uint256"}],"name":"TokenRatioUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"TokenRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"TokenSwapped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountBurned","type":"uint256"}],"name":"TokenWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"ADMIN_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":"EMERGENCY_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RATIO_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"ratio","type":"uint256"}],"name":"addSupportedToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"forceRemove","type":"bool"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getReserveBalance","outputs":[{"internalType":"uint256","name":"totalBalance","type":"uint256"}],"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":"getSupportedTokenCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSupportedTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getTokenRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getTokenReserveBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"address","name":"initialOwner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"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":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"previewSwap","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"amountBurned","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"ratios","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"removeSupportedToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","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":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"supportedTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"}],"name":"swap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"newRatio","type":"uint256"}],"name":"updateTokenRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"maxAmountBurned","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":null}