{"file_path":"contracts/sYUSD.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IYUSD } from \"./interfaces/IYUSD.sol\";\nimport { sYUSDSilo } from \"./sYUSDSilo.sol\";\n\n/**\n * @title sYUSDUpgradeable\n * @dev Staked YUSD (sYUSD) - an interest-bearing token that represents YUSD staked in the protocol.\n * The token's value increases over time relative to YUSD, reflecting staking rewards.\n * Implements ERC4626 Tokenized Vault Standard.\n * \n * @dev Staking Mechanics:\n * - Users deposit YUSD and receive sYUSD shares in return\n * - The exchange rate between YUSD and sYUSD can increase over time as rewards are added\n * - The value of sYUSD (relative to YUSD) never decreases, making it a yield-bearing asset\n * \n * @dev Unstaking Process:\n * - 2-step withdrawal process: cooldown, then unstake\n * - Cooldown initiates an unstaking period based on the cooldown duration\n * - Users cannot withdraw their shares until the cooldown period expires\n * - When cooldown duration is set to 0, direct withdrawals are allowed without cooldown\n * \n * @dev Upgrade Features:\n * - Uses TransparentUpgradeableProxy pattern\n * - The admin role can upgrade the implementation contract\n * - TimelockController is set as the proxy admin to provide time-delayed governance\n * \n * @dev Security Features:\n * - Based on OpenZeppelin's upgradeable contracts\n * - Admin role is required for changing critical parameters\n * - Rescue function for recovering non-YUSD tokens sent to the contract accidentally\n * - Safeguards against withdrawing during cooldown period\n * \n * @dev Integration Notes:\n * - Fully compatible with ERC4626 interfaces for better composability\n * - Implements maxWithdraw and maxDeposit to properly communicate withdrawal limitations\n * - Uses ERC20Permit for gasless approvals\n */\ncontract sYUSD is \n    Initializable, \n    ERC4626Upgradeable, \n    ERC20PermitUpgradeable, \n    AccessControlUpgradeable, \n    ReentrancyGuardUpgradeable\n{\n    using SafeERC20 for IERC20;\n    \n    // Constants for roles\n    bytes32 public constant ADMIN_ROLE = keccak256(\"ADMIN_ROLE\");\n    \n    // Maximum cooldown duration (90 days)\n    uint24 public constant MAX_COOLDOWN_DURATION = 90 days;\n    \n    // Cooldown duration in seconds (7 days by default)\n    // When set to 0, cooldown is disabled and direct withdrawals are allowed\n    uint24 public cooldownDuration;\n\n    sYUSDSilo public silo;\n    \n    // Struct to track user cooldown status\n    struct Cooldown {\n        uint104 cooldownEnd;\n        uint152 underlyingAmount;\n    }\n    \n    // Mapping of user address to cooldown status\n    mapping(address => Cooldown) public cooldowns;\n\n    // ===== NEW STORAGE VARIABLES (added in upgrade) =====\n    // Instant unstaking fee in basis points (0.5% = 50 bps)\n    uint16 public INSTANT_UNSTAKING_FEE;\n    \n    // Insurance fund address\n    address public INSURANCE_FUND;\n\n    error InsufficientShares(uint256 requested, uint256 available);\n    error CooldownNotEnded();\n    error ZeroAddress(string paramName);\n    error ZeroAmount();\n    error InvalidToken();\n    error ExpectedCooldownOn();\n    error ExpectedCooldownOff();\n    error DurationExceedsMax();\n    error DurationNotChanged();\n    error InvalidFee();\n    error FeeNotChanged();\n    error InsuranceFundNotSet();\n    error InsuranceFundNotChanged();\n    \n    event CooldownDurationUpdated(uint24 previousDuration, uint24 newDuration);\n    event CooldownStarted(address indexed user, uint256 assets, uint256 shares, uint256 cooldownEnd);\n    event Unstaked(address indexed user, address indexed receiver, uint256 assets);\n    event InstantUnstakingFeeUpdated(uint16 previousFee, uint16 newFee);\n    event InsuranceFundUpdated(address previousFund, address newFund);\n    event InstantUnstaking(address indexed user, address indexed receiver, uint256 assets, uint256 fee);\n\n    /// @custom:oz-upgrades-unsafe-allow constructor\n    constructor() {\n        _disableInitializers();\n    }\n\n    // Modifiers to check cooldown mode\n    modifier ensureCooldownOff() {\n        if (cooldownDuration > 0) revert ExpectedCooldownOff();\n        _;\n    }\n\n    modifier ensureCooldownOn() {\n        if (cooldownDuration == 0) revert ExpectedCooldownOn();\n        _;\n    }\n\n    /**\n     * @dev Initializer function\n     * @param _yusd Address of the YUSD token\n     * @param admin Address of the admin\n     */\n    function initialize(\n        address _yusd,\n        address admin\n    ) public initializer {\n        if (_yusd == address(0)) revert ZeroAddress(\"YUSD\");\n        if (admin == address(0)) revert ZeroAddress(\"Admin\");\n\n        __ERC20_init(\"Staked YUSD\", \"sYUSD\");\n        __ERC4626_init(IERC20(_yusd));\n        __ERC20Permit_init(\"Staked YUSD\");\n        __AccessControl_init();\n        __ReentrancyGuard_init();\n\n        silo = new sYUSDSilo(address(this), _yusd);\n        \n        cooldownDuration = 7 days; // Default value\n\n        _grantRole(DEFAULT_ADMIN_ROLE, admin);\n        _grantRole(ADMIN_ROLE, admin);\n    }\n\n    /**\n     * @dev Override decimals function to resolve conflict between ERC20 and ERC4626\n     */\n    function decimals() public view virtual override(ERC4626Upgradeable, ERC20Upgradeable) returns (uint8) {\n        return super.decimals();\n    }\n\n    /**\n     * @dev Allows admin to set the cooldown duration\n     * @param newDuration New cooldown duration in seconds\n     */\n    function setCooldownDuration(uint24 newDuration) external onlyRole(ADMIN_ROLE) {\n        _setCooldownDuration(newDuration);\n    }\n\n    /**\n     * @dev Allows admin to set the instant unstaking fee\n     * @param newFee New instant unstaking fee in basis points (max 10000 = 100%)\n     */\n    function setInstantUnstakingFee(uint16 newFee) external onlyRole(ADMIN_ROLE) {\n        if (newFee > 10000) revert InvalidFee(); // Max 100%\n        if (INSTANT_UNSTAKING_FEE == newFee) revert FeeNotChanged();\n        \n        uint16 previousFee = INSTANT_UNSTAKING_FEE;\n        INSTANT_UNSTAKING_FEE = newFee;\n        \n        emit InstantUnstakingFeeUpdated(previousFee, newFee);\n    }\n\n    /**\n     * @dev Allows admin to set the insurance fund address\n     * @param newInsuranceFund New insurance fund address\n     */\n    function setInsuranceFund(address newInsuranceFund) external onlyRole(ADMIN_ROLE) {\n        if (newInsuranceFund == address(0)) revert ZeroAddress(\"insuranceFund\");\n        if (INSURANCE_FUND == newInsuranceFund) revert InsuranceFundNotChanged();\n        \n        address previousFund = INSURANCE_FUND;\n        INSURANCE_FUND = newInsuranceFund;\n        \n        emit InsuranceFundUpdated(previousFund, newInsuranceFund);\n    }\n\n    /**\n     * @dev Initialize new variables added in upgrade (call once after upgrade)\n     * @param initialFee Initial instant unstaking fee in basis points (default: 50 = 0.5%)\n     * @param initialInsuranceFund Initial insurance fund address\n     */\n    function initializeV2(uint16 initialFee, address initialInsuranceFund) external onlyRole(ADMIN_ROLE) {\n        // Only allow initialization if variables are still at default values\n        if (INSTANT_UNSTAKING_FEE != 0 || INSURANCE_FUND != address(0)) {\n            revert(\"Already initialized\");\n        }\n        \n        if (initialFee > 10000) revert InvalidFee(); // Max 100%\n        if (initialInsuranceFund == address(0)) revert ZeroAddress(\"insuranceFund\");\n        \n        INSTANT_UNSTAKING_FEE = initialFee;\n        INSURANCE_FUND = initialInsuranceFund;\n        \n        emit InstantUnstakingFeeUpdated(0, initialFee);\n        emit InsuranceFundUpdated(address(0), initialInsuranceFund);\n    }\n\n    /**\n     * @dev Override of withdraw with instant unstaking support\n     * @dev When cooldown is enabled, charges INSTANT_UNSTAKING_FEE and transfers fee to INSURANCE_FUND\n     * @dev When cooldown is disabled, works as normal withdrawal\n     * @inheritdoc ERC4626Upgradeable\n     */\n    function withdraw(\n        uint256 assets,\n        address receiver,\n        address owner\n    ) public virtual override returns (uint256) {\n        if (cooldownDuration == 0) {\n            // Normal withdrawal when cooldown is disabled\n            return super.withdraw(assets, receiver, owner);\n        } else {\n            // Instant unstaking with fee when cooldown is enabled\n            return _instantUnstakeAssets(assets, receiver, owner);\n        }\n    }\n\n    /**\n     * @dev Override of redeem with instant unstaking support\n     * @dev When cooldown is enabled, charges INSTANT_UNSTAKING_FEE and transfers fee to INSURANCE_FUND\n     * @dev When cooldown is disabled, works as normal redemption\n     * @inheritdoc ERC4626Upgradeable\n     */\n    function redeem(\n        uint256 shares,\n        address receiver,\n        address owner\n    ) public virtual override returns (uint256) {\n        if (cooldownDuration == 0) {\n            // Normal redemption when cooldown is disabled\n            return super.redeem(shares, receiver, owner);\n        } else {\n            // Instant unstaking with fee when cooldown is enabled\n            return _instantUnstakeShares(shares, receiver, owner);\n        }\n    }\n\n    /**\n     * @dev Step 1: Cooldown assets to initiate the unstaking process\n     * @param assets Amount of assets to unstake\n     * @param owner Address of the owner\n     * @return shares Amount of shares burned\n     */\n    function cooldownAssets(uint256 assets, address owner) external ensureCooldownOn returns (uint256 shares) {\n        if (assets == 0) revert ZeroAmount();\n        if (owner != msg.sender) revert(\"Only owner can initiate cooldown\");\n        \n        cooldowns[owner].cooldownEnd = uint104(block.timestamp) + cooldownDuration;\n        cooldowns[owner].underlyingAmount += uint152(assets);\n\n        shares = super.withdraw(assets, address(silo), owner);\n        \n        emit CooldownStarted(owner, assets, shares, cooldowns[owner].cooldownEnd);\n        \n        return shares;\n    }\n\n    /**\n     * @dev Step 1: Cooldown shares to initiate the unstaking process\n     * @param shares Amount of shares to unstake\n     * @param owner Address of the owner\n     * @return assets Amount of underlying assets\n     */\n    function cooldownShares(uint256 shares, address owner) external ensureCooldownOn returns (uint256 assets) {        \n        if (shares == 0) revert ZeroAmount();\n        if (owner != msg.sender) revert(\"Only owner can initiate cooldown\");\n        \n        assets = super.redeem(shares, address(silo), owner);\n\n        cooldowns[owner].cooldownEnd = uint104(block.timestamp) + cooldownDuration;\n        cooldowns[owner].underlyingAmount += uint152(assets);\n        \n        emit CooldownStarted(owner, assets, shares, cooldowns[owner].cooldownEnd);\n        \n        return assets;\n    }\n\n    /**\n     * @dev Step 2: Unstake after cooldown period has ended\n     * @param receiver Address to receive the assets\n     */\n    function unstake(address receiver) external nonReentrant {        \n        if (receiver == address(0)) revert ZeroAddress(\"receiver\");\n        \n        Cooldown storage cooldown = cooldowns[msg.sender];\n        uint256 assets = cooldown.underlyingAmount;\n        \n        if (block.timestamp >= cooldown.cooldownEnd || cooldownDuration == 0) {\n            cooldown.cooldownEnd = 0;\n            cooldown.underlyingAmount = 0;\n\n            silo.withdraw(receiver, assets);\n        } else {\n            revert CooldownNotEnded();\n        }\n        \n        emit Unstaked(msg.sender, receiver, assets);\n    }\n\n    /**\n     * @dev Gets the cooldown status for a user\n     * @param user Address of the user\n     * @return cooldownEnd Timestamp when cooldown ends\n     * @return underlyingAmount Amount of underlying assets in cooldown\n     */\n    function getUserCooldownStatus(address user) external view returns (uint256 cooldownEnd, uint256 underlyingAmount) {\n        Cooldown storage cooldown = cooldowns[user];\n        return (cooldown.cooldownEnd, cooldown.underlyingAmount);\n    }\n\n    /**\n     * @dev Internal function to set cooldown duration with validation\n     */\n    function _setCooldownDuration(uint24 newDuration) internal {\n        uint24 previousDuration = cooldownDuration;\n        if (previousDuration == newDuration) revert DurationNotChanged();\n        if (newDuration > MAX_COOLDOWN_DURATION) revert DurationExceedsMax();\n\n        cooldownDuration = newDuration;\n        emit CooldownDurationUpdated(previousDuration, newDuration);\n    }\n\n    /**\n     * @dev Internal function for instant unstaking by assets with fee\n     * @param assets Amount of assets to withdraw\n     * @param receiver Address to receive the assets (minus fee)\n     * @param owner Address of the owner of shares\n     * @return shares Amount of shares burned\n     */\n    function _instantUnstakeAssets(uint256 assets, address receiver, address owner) internal returns (uint256 shares) {\n        if (INSURANCE_FUND == address(0)) revert InsuranceFundNotSet();\n        \n        // Calculate fee and net assets\n        uint256 fee = (assets * INSTANT_UNSTAKING_FEE) / 10000;\n        uint256 netAssets = assets - fee;\n        \n        // Perform the withdrawal to get the total assets\n        shares = super.withdraw(assets, address(this), owner);\n        \n        // Transfer fee to insurance fund\n        if (fee > 0) {\n            IERC20(asset()).safeTransfer(INSURANCE_FUND, fee);\n        }\n        \n        // Transfer remaining assets to receiver\n        IERC20(asset()).safeTransfer(receiver, netAssets);\n        \n        emit InstantUnstaking(owner, receiver, netAssets, fee);\n        \n        return shares;\n    }\n\n    /**\n     * @dev Internal function for instant unstaking by shares with fee\n     * @param shares Amount of shares to redeem\n     * @param receiver Address to receive the assets (minus fee)\n     * @param owner Address of the owner of shares\n     * @return assets Amount of net assets transferred to receiver (after fee)\n     */\n    function _instantUnstakeShares(uint256 shares, address receiver, address owner) internal returns (uint256 assets) {\n        if (INSURANCE_FUND == address(0)) revert InsuranceFundNotSet();\n        \n        // Perform the redemption to get total assets\n        uint256 totalAssets = super.redeem(shares, address(this), owner);\n        \n        // Calculate fee and net assets\n        uint256 fee = (totalAssets * INSTANT_UNSTAKING_FEE) / 10000;\n        assets = totalAssets - fee;\n        \n        // Transfer fee to insurance fund\n        if (fee > 0) {\n            IERC20(asset()).safeTransfer(INSURANCE_FUND, fee);\n        }\n        \n        // Transfer remaining assets to receiver\n        IERC20(asset()).safeTransfer(receiver, assets);\n        \n        emit InstantUnstaking(owner, receiver, assets, fee);\n        \n        return assets;\n    }\n\n    /**\n     * @notice Allows admin to rescue ERC20 tokens accidentally sent to this contract\n     * @dev This function can only be called by an account with DEFAULT_ADMIN_ROLE\n     * @dev The underlying asset (YUSD) cannot be rescued to prevent manipulation\n     * @dev Uses nonReentrant modifier to prevent potential reentrancy attacks\n     * @dev Verifies the token is not the underlying asset before transfer\n     * @param token Address of the ERC20 token to rescue\n     * @param amount Amount of tokens to rescue\n     * @param to Address to send the rescued tokens to\n     */\n    function rescueTokens(address token, uint256 amount, address to) external nonReentrant onlyRole(DEFAULT_ADMIN_ROLE) {\n        if (token == address(0)) revert ZeroAddress(\"token\");\n        if (to == address(0)) revert ZeroAddress(\"to\");\n        if (amount == 0) revert ZeroAmount();\n        if (token == asset()) revert InvalidToken();\n        \n        IERC20(token).safeTransfer(to, amount);\n    }\n} ","deployed_bytecode":"0x608080604052600436101561001357600080fd5b600090813560e01c90816301320fe21461215d5750806301e1d1141461214257806301ffc9a7146120eb57806306fdde031461202a57806307a2d13a14611463578063095ea7b3146120035780630a28a47714611fe457806318160ddd14611fb95780631e9049cf14611f9b57806323b872dd14611f62578063248a9ca314611f435780632f2ff15d14611f11578063313ce56714611ec25780633526931514611ea05780633644e51514611e8557806336568abe14611e4057806338d52e0f14611e0a578063402d267d146108a7578063485cc955146114685780634cdad506146114635780634f115da514611419578063597a3fd3146113f75780636e553f65146113c357806370a082311461044e57806375b238fc146113885780637ecebe001461133157806380060c851461129557806384b0196e14610fb957806391d1485414610f6357806394bf804d14610f2f57806395d89b4114610e2e578063a217fddf14610e12578063a2af490014610cf4578063a9059cbb14610cc2578063b37fd19014610b6c578063b3d7f6b914610b4d578063b460af9414610b33578063b6306ce5146109eb578063ba087652146109d1578063c1d3e026146109a4578063c3c05293146108ac578063c63d75b6146108a7578063c6e6f592146103d5578063ce23eb3c14610806578063ce96cb77146107e2578063d505accf14610674578063d50655b0146104d8578063d547741f1461049d578063d905777e1461044e578063dd62ed3e14610405578063eb3beb29146103da578063ef8b30f7146103d55763f2888dbb1461026857600080fd5b346103d25760203660031901126103d2576102816121a5565b610289612e7c565b6001600160a01b0381169081156103a157338352600160205260408320908154916001600160681b038360681c93164210801590610393575b156103845760009055835460181c6001600160a01b0316908490823b156103805760405163f3fef3a360e01b81526001600160a01b0391909116600482015260248101849052918290604490829084905af1801561037557610361575b506040519081527fd8654fcc8cf5b36d30b3f5e4688fc78118e6d68de60b9994e09902268b57c3e360203392a36001600080516020613b678339815191525580f35b8361036e919492946122fd565b913861031f565b6040513d86823e3d90fd5b5080fd5b63039a040560e21b8552600485fd5b5062ffffff855416156102c2565b60405163eac0d38960e01b81526020600482015260086024820152673932b1b2b4bb32b960c11b6044820152606490fd5b80fd5b6122df565b50346103d257806003193601126103d2575460405160189190911c6001600160a01b03168152602090f35b50346103d25760403660031901126103d25760406020916104246121a5565b61043561042f6121c0565b916121d6565b6001600160a01b03909116825283522054604051908152f35b50346103d25760203660031901126103d257602061049561046d6121a5565b6001600160a01b03166000908152600080516020613a87833981519152602052604090205490565b604051908152f35b50346103d25760403660031901126103d2576104d46004356104bd6121c0565b906104cf6104ca826123f5565b6129f2565b612c65565b5080f35b50346103d25760403660031901126103d257600435906104f66121c0565b9062ffffff815416918215610665578315610656576001600160a01b03811691338303610611576020946106066001600160681b036105d17feeb98a30820c610e8eb6fd5624b21085d2d6a6e4180ca779e46b3d03992892729561055e60409984421661243f565b88875260018b52838a88209116841982541617905587865260018a526105bd8987206105976001600160981b038816825460681c612475565b81546001600160681b031660689190911b6cffffffffffffffffffffffffff1916179055565b855460181c6001600160a01b031685612f16565b96848789965260018a52205416604051938493849160409194936001600160681b039160608501968552602085015216910152565b0390a2604051908152f35b60405162461bcd60e51b815260206004820181905260248201527f4f6e6c79206f776e65722063616e20696e69746961746520636f6f6c646f776e6044820152606490fd5b631f2a200560e01b8252600482fd5b631ad051bd60e11b8252600482fd5b50346103d25760e03660031901126103d25761068e6121a5565b906106976121c0565b604435906064359360843560ff811681036107de578542116107ca5761078a6107939160018060a01b038416978888527f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb0060205260408820908154916001830190556040519060208201927f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c984528b604084015260018060a01b038916606084015289608084015260a083015260c082015260c0815261075860e0826122fd565b519020610763613033565b906040519161190160f01b83526002830152602282015260c43591604260a435922061327d565b90929192613326565b6001600160a01b0316948086036107b357506107b0939450612fce565b80f35b6325c0072360e11b85526004869052602452604484fd5b63313c898160e11b85526004869052602485fd5b8480fd5b50346103d25760203660031901126103d25760206104956108016121a5565b61269b565b50346103d25760203660031901126103d25760043562ffffff811680910361038057610830612980565b81549062ffffff821691818314610898576276a70082116108895791816040927f180eacdf7dbaeecaa983d93173b4285db2f2c0de0044697e1f932bbbb73dcaa69462ffffff191617855582519182526020820152a180f35b630dd0b9f560e21b8452600484fd5b632600ca5160e01b8452600484fd5b61226e565b50346103d25760203660031901126103d2576108c66121a5565b906108cf612980565b6001600160a01b03821691821561096e5760025492601084901c6001600160a01b031690811461095f5762010000600160b01b031993909316601082901b62010000600160b01b031617600255604080516001600160a01b03948516815293909116602084015290917f775be72f3c02cdfa3ef9fd431e09d13a08a983f92a707fcc00192a62c6e44d719190a180f35b630a16a5ff60e21b8352600483fd5b60405163eac0d38960e01b815260206004820152600d60248201526c1a5b9cdd5c985b98d9519d5b99609a1b6044820152606490fd5b50346103d257806003193601126103d25760025460405160109190911c6001600160a01b03168152602090f35b50346103d25760206104956109e5366122a5565b916125a0565b50346103d25760403660031901126103d257610a05612294565b610a0d6121c0565b90610a16612980565b6002549061ffff821615801590610b1d575b610ae25761ffff16906127108211610ad3576001600160a01b03831690811561096e576040837ffc2e3ec7f4564261ba6f9f8a56d29b5047d6709ba32beffceea07ba302b5861c9282957f775be72f3c02cdfa3ef9fd431e09d13a08a983f92a707fcc00192a62c6e44d719762010000600160b01b039060101b169169ffffffffffffffffffff60b01b1617176002558151908782526020820152a18151908482526020820152a180f35b6358d620b360e01b8452600484fd5b60405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606490fd5b50601082901c6001600160a01b03161515610a28565b50346103d2576020610495610b47366122a5565b91612495565b50346103d25760203660031901126103d25760206104956004356126d6565b50346103d25760603660031901126103d257610b866121a5565b6044356001600160a01b03811692916024359190848203610cbe57610ba9612e7c565b838052600080516020613b278339815191526020908152604080862033875290915284205460ff1615610ca6576001600160a01b0316938415610c785715610c4d578115610c3e57600080516020613b47833981519152546001600160a01b03168414610c2f57610c1a9293612eb8565b6001600080516020613b678339815191525580f35b63c1ab6dc160e01b8352600483fd5b631f2a200560e01b8352600483fd5b60405163eac0d38960e01b8152602060048201526002602482015261746f60f01b6044820152606490fd5b60405163eac0d38960e01b81526020600482015260056024820152643a37b5b2b760d91b6044820152606490fd5b63e2517d3f60e01b8452336004526024849052604484fd5b8380fd5b50346103d25760403660031901126103d257610ce9610cdf6121a5565b6024359033612891565b602060405160018152f35b50346103d25760403660031901126103d25760043590610d126121c0565b9181549262ffffff841615610e03578115610c3e576001600160a01b03811691338303610611576020947feeb98a30820c610e8eb6fd5624b21085d2d6a6e4180ca779e46b3d0399289272926001600160681b0391604091610d809160181c6001600160a01b031685612e16565b95610d9362ffffff82541684421661243f565b86825260018952838383209116841982541617905585815260018852610dcc8282206105976001600160981b038a16825460681c612475565b858152600188522054169061060660405192839287849160409194936001600160681b039160608501968552602085015216910152565b631ad051bd60e11b8352600483fd5b50346103d257806003193601126103d257602090604051908152f35b50346103d257806003193601126103d2576040519080600080516020613ac78339815191525490610e5e826123bb565b8085529160018116908115610f085750600114610e9e575b610e9a84610e86818603826122fd565b60405191829160208352602083019061220f565b0390f35b600080516020613ac783398151915281527f46a2803e59a4de4e7a4c574b1243f25977ac4c77d5a1a4a609b5394cebb4a2aa939250905b808210610eee57509091508101602001610e8682610e76565b919260018160209254838588010152019101909291610ed5565b60ff191660208087019190915292151560051b85019092019250610e869150839050610e76565b50346103d25760403660031901126103d2576020600435610495610f516121c0565b91610f5b816126d6565b809333612d05565b50346103d25760403660031901126103d25760ff6040602092610f846121c0565b6004358252600080516020613b2783398151915285528282206001600160a01b03909116825284522054604051911615158152f35b50346103d257806003193601126103d2577fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10054158061126c575b1561122f57604051908082600080516020613aa78339815191525491611018836123bb565b808352926001811690811561121057506001146111a5575b61103c925003836122fd565b604051908082600080516020613b07833981519152549161105c836123bb565b8083529260018116908115611186575060011461111b575b61108891939250936110bf959403836122fd565b60206110cd6040519361109b83866122fd565b83855283368137604051968796600f60f81b885260e08589015260e088019061220f565b90868203604088015261220f565b904660608601523060808601528260a086015284820360c08601528080855193848152019401925b82811061110457505050500390f35b8351855286955093810193928101926001016110f5565b50600080516020613b0783398151915283529082907f5f9ce34815f8e11431c7bb75a8e6886a91478f7ffc1dbb0a98dc240fddd76b755b81831061116a57505090602061108892820101611074565b6020919350806001915483858901015201910190918492611152565b6020925061108894915060ff191682840152151560051b820101611074565b50600080516020613aa783398151915283529082907f42ad5d3e1f2e6e70edcf6d991b8a3023d3fca8047a131592f9edb9fd9b89d57d5b8183106111f457505090602061103c92820101611030565b60209193508060019154838589010152019101909184926111dc565b6020925061103c94915060ff191682840152151560051b820101611030565b60405162461bcd60e51b81526020600482015260156024820152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b6044820152606490fd5b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1015415610ff3565b50346103d25760203660031901126103d25761ffff6112b2612294565b6112ba612980565b166127108111611322576002549061ffff8216918183146113135791816040927ffc2e3ec7f4564261ba6f9f8a56d29b5047d6709ba32beffceea07ba302b5861c9461ffff19161760025582519182526020820152a180f35b63989b0a8560e01b8452600484fd5b6358d620b360e01b8252600482fd5b50346103d25760203660031901126103d25760406020916113506121a5565b6001600160a01b031681527f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb0083522054604051908152f35b50346103d257806003193601126103d25760206040517fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217758152f35b50346103d25760403660031901126103d25760206004356104956113e56121c0565b6113ee83612785565b92839133612d05565b50346103d257806003193601126103d257602061ffff60025416604051908152f35b50346103d25760203660031901126103d25760409081906001600160a01b036114406121a5565b168152600160205220548151906001600160681b038116825260681c6020820152f35b612250565b50346103d25760403660031901126103d2576114826121a5565b61148a6121c0565b600080516020613b87833981519152549060ff8260401c16159167ffffffffffffffff811680159081611e02575b6001149081611df8575b159081611def575b50611de05767ffffffffffffffff198116600117600080516020613b878339815191525582611db3575b506001600160a01b038316928315611d87576001600160a01b03821615611d595761151d612416565b9360409485519061152e87836122fd565b60058252641cd65554d160da1b602083015261154861309a565b61155061309a565b80519067ffffffffffffffff8211611d4557819061157c600080516020613a67833981519152546123bb565b601f8111611cca575b50602090601f8311600114611c4b578a92611c40575b50508160011b916000199060031b1c191617600080516020613a67833981519152555b80519067ffffffffffffffff82116119015781906115ea600080516020613ac7833981519152546123bb565b601f8111611bc5575b50602090601f8311600114611b46578992611b3b575b50508160011b916000199060031b1c191617600080516020613ac7833981519152555b61163461309a565b61163c61309a565b611645816136c1565b9015611b33575b600080516020613b47833981519152549060ff60a01b9060a01b16906affffffffffffffffffffff60a81b161717600080516020613b4783398151915255611692612416565b61169a61309a565b8451906116a786836122fd565b60018252603160f81b60208301526116bd61309a565b80519067ffffffffffffffff82116119015781906116e9600080516020613aa7833981519152546123bb565b601f8111611ab8575b50602090601f8311600114611a39578992611a2e575b50508160011b916000199060031b1c191617600080516020613aa7833981519152555b80519067ffffffffffffffff8211611a1a578190611757600080516020613b07833981519152546123bb565b601f811161199f575b50602090601f8311600114611920578892611915575b50508160011b916000199060031b1c191617600080516020613b07833981519152555b847fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10055847fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d101556117e761309a565b6117ef61309a565b6117f761309a565b6001600080516020613b67833981519152558351906102c28083019083821067ffffffffffffffff831117611901579161184b9184936137a585393081526001600160a01b03909116602082015260400190565b039085f09081156118f45784546001600160b81b03191660189290921b6301000000600160b81b03169190911762093a801784556118929061188c81612a3c565b50612aee565b5061189b575080f35b60207fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29168ff000000000000000019600080516020613b878339815191525416600080516020613b87833981519152555160018152a180f35b50505051903d90823e3d90fd5b634e487b7160e01b88526041600452602488fd5b015190503880611776565b600080516020613b0783398151915289528189209250601f198416895b818110611987575090846001959493921061196e575b505050811b01600080516020613b0783398151915255611799565b015160001960f88460031b161c19169055388080611953565b9293602060018192878601518155019501930161193d565b600080516020613b0783398151915289529091507f5f9ce34815f8e11431c7bb75a8e6886a91478f7ffc1dbb0a98dc240fddd76b75601f840160051c81019160208510611a10575b90601f859493920160051c01905b818110611a025750611760565b8981558493506001016119f5565b90915081906119e7565b634e487b7160e01b87526041600452602487fd5b015190503880611708565b600080516020613aa78339815191528a52818a209250601f1984168a5b818110611aa05750908460019594939210611a87575b505050811b01600080516020613aa78339815191525561172b565b015160001960f88460031b161c19169055388080611a6c565b92936020600181928786015181550195019301611a56565b600080516020613aa78339815191528a529091507f42ad5d3e1f2e6e70edcf6d991b8a3023d3fca8047a131592f9edb9fd9b89d57d601f840160051c81019160208510611b29575b90601f859493920160051c01905b818110611b1b57506116f2565b8a8155849350600101611b0e565b9091508190611b00565b50601261164c565b015190503880611609565b600080516020613ac78339815191528a52818a209250601f1984168a5b818110611bad5750908460019594939210611b94575b505050811b01600080516020613ac78339815191525561162c565b015160001960f88460031b161c19169055388080611b79565b92936020600181928786015181550195019301611b63565b600080516020613ac78339815191528a529091507f46a2803e59a4de4e7a4c574b1243f25977ac4c77d5a1a4a609b5394cebb4a2aa601f840160051c81019160208510611c36575b90601f859493920160051c01905b818110611c2857506115f3565b8a8155849350600101611c1b565b9091508190611c0d565b01519050388061159b565b600080516020613a678339815191528b52818b209250601f1984168b5b818110611cb25750908460019594939210611c99575b505050811b01600080516020613a67833981519152556115be565b015160001960f88460031b161c19169055388080611c7e565b92936020600181928786015181550195019301611c68565b600080516020613a678339815191528b529091507f2ae08a8e29253f69ac5d979a101956ab8f8d9d7ded63fa7a83b16fc47648eab0601f840160051c81019160208510611d3b575b90601f859493920160051c01905b818110611d2d5750611585565b8b8155849350600101611d20565b9091508190611d12565b634e487b7160e01b89526041600452602489fd5b60405163eac0d38960e01b815260206004820152600560248201526420b236b4b760d91b6044820152606490fd5b606460405163eac0d38960e01b8152602060048201526004602482015263165554d160e21b6044820152fd5b68ffffffffffffffffff19166801000000000000000117600080516020613b8783398151915255386114f4565b63f92ee8a960e01b8552600485fd5b905015386114ca565b303b1591506114c2565b8491506114b8565b50346103d257806003193601126103d257600080516020613b47833981519152546040516001600160a01b039091168152602090f35b50346103d25760403660031901126103d257611e5a6121c0565b336001600160a01b03821603611e76576104d490600435612c65565b63334bd91960e11b8252600482fd5b50346103d257806003193601126103d2576020610495613033565b50346103d257806003193601126103d25762ffffff6020915416604051908152f35b50346103d257806003193601126103d25760ff600080516020613b478339815191525460a01c169060ff8211611efd57602082604051908152f35b634e487b7160e01b81526011600452602490fd5b50346103d25760403660031901126103d2576104d4600435611f316121c0565b90611f3e6104ca826123f5565b612bbc565b50346103d25760203660031901126103d25760206104956004356123f5565b50346103d25760603660031901126103d257610ce9611f7f6121a5565b611f876121c0565b60443591611f968333836127c0565b612891565b50346103d257806003193601126103d25760206040516276a7008152f35b50346103d257806003193601126103d2576020600080516020613ae783398151915254604051908152f35b50346103d25760203660031901126103d257602061049560043561274c565b50346103d25760403660031901126103d257610ce96120206121a5565b6024359033612fce565b50346103d257806003193601126103d2576040519080600080516020613a67833981519152549061205a826123bb565b8085529160018116908115610f08575060011461208157610e9a84610e86818603826122fd565b600080516020613a6783398151915281527f2ae08a8e29253f69ac5d979a101956ab8f8d9d7ded63fa7a83b16fc47648eab0939250905b8082106120d157509091508101602001610e8682610e76565b9192600181602092548385880101520191019092916120b8565b50346103d25760203660031901126103d25760043563ffffffff60e01b811680910361038057602090637965db0b60e01b8114908115612131575b506040519015158152f35b6301ffc9a760e01b14905082612126565b50346103d257806003193601126103d2576020610495612335565b9050346103805760203660031901126103805760409182906001600160a01b036121856121a5565b168152600160205220546001600160681b038116825260681c6020820152f35b600435906001600160a01b03821682036121bb57565b600080fd5b602435906001600160a01b03821682036121bb57565b6001600160a01b031660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020526040902090565b919082519283825260005b84811061223b575050826000602080949584010152601f8019910116010190565b8060208092840101518282860101520161221a565b346121bb5760203660031901126121bb576020610495600435612711565b346121bb5760203660031901126121bb576122876121a5565b5060206040516000198152f35b6004359061ffff821682036121bb57565b60609060031901126121bb57600435906024356001600160a01b03811681036121bb57906044356001600160a01b03811681036121bb5790565b346121bb5760203660031901126121bb576020610495600435612785565b90601f8019910116810190811067ffffffffffffffff82111761231f57604052565b634e487b7160e01b600052604160045260246000fd5b600080516020613b47833981519152546040516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa9081156123af57600091612380575090565b90506020813d6020116123a7575b8161239b602093836122fd565b810103126121bb575190565b3d915061238e565b6040513d6000823e3d90fd5b90600182811c921680156123eb575b60208310146123d557565b634e487b7160e01b600052602260045260246000fd5b91607f16916123ca565b600052600080516020613b2783398151915260205260016040600020015490565b604051906124256040836122fd565b600b82526a14dd185ad95908165554d160aa1b6020830152565b906001600160681b03809116911601906001600160681b03821161245f57565b634e487b7160e01b600052601160045260246000fd5b906001600160981b03809116911601906001600160981b03821161245f57565b60005491929162ffffff166124b157916124ae92612f16565b90565b600254601081901c6001600160a01b03161561258f5760406127106124fb61ffff7fc8dfda6e2d197297ceadecc95d363b1c65f67f827b63379405f05e3eab2f5cbc941685612ef6565b04946125138561250b8887612f09565b953090612f16565b958061255c575b600080516020613b478339815191525461254090869084906001600160a01b0316612eb8565b825194855260208501526001600160a01b03908116941692a390565b600080516020613b478339815191525460025461258a91839160101c6001600160a01b039081169116612eb8565b61251a565b63ff8907f960e01b60005260046000fd5b60005491929162ffffff166125b957916124ae92612e16565b60025460101c6001600160a01b03161561258f57816125d9913090612e16565b7fc8dfda6e2d197297ceadecc95d363b1c65f67f827b63379405f05e3eab2f5cbc60406002549461261c61271061261461ffff891687612ef6565b048095612f09565b95848061266b575b5050600080516020613b478339815191525461264c90879083906001600160a01b0316612eb8565b815186815260208101949094526001600160a01b03908116941692a390565b600080516020613b47833981519152546126949260101c6001600160a01b039081169116612eb8565b3884612624565b6001600160a01b03166000908152600080516020613a8783398151915260205260409020546124ae90612711565b9190820180921161245f57565b6126de612335565b906001820180921161245f57600080516020613ae7833981519152546001810180911161245f576124ae92600192612f68565b612719612335565b906001820180921161245f57600080516020613ae7833981519152546001810180911161245f576124ae92600092612f68565b600080516020613ae78339815191525460019081810180911161245f57612771612335565b9082820180921161245f576124ae93612f68565b600080516020613ae783398151915254906001820180921161245f576127a9612335565b6001810180911161245f576124ae92600092612f68565b91906127cb836121d6565b60018060a01b0382166000526020526040600020549260001984036127f1575b50505050565b82841061286c576001600160a01b03811615612856576001600160a01b038216156128405761281f906121d6565b9060018060a01b0316600052602052604060002091039055388080806127eb565b634a1406b160e11b600052600060045260246000fd5b63e602df0560e01b600052600060045260246000fd5b508290637dc7a0d960e11b60005260018060a01b031660045260245260445260646000fd5b6001600160a01b031690811561296a576001600160a01b0316918215612954576000828152600080516020613a87833981519152602052604081205482811061293a5791604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef958760209652600080516020613a8783398151915286520382822055868152600080516020613a87833981519152845220818154019055604051908152a3565b916064928463391434e360e21b8452600452602452604452fd5b63ec442f0560e01b600052600060045260246000fd5b634b637e8f60e11b600052600060045260246000fd5b3360009081527fb16e88c42fd4e48df2dd6a2eabd6bc9aec654ec170056b470819f8892cc6431c602052604090205460ff16156129b957565b63e2517d3f60e01b600052336004527fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177560245260446000fd5b6000818152600080516020613b278339815191526020908152604080832033845290915290205460ff1615612a245750565b63e2517d3f60e01b6000523360045260245260446000fd5b6001600160a01b03811660009081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16612ae8576001600160a01b031660008181527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d60205260408120805460ff191660011790553391907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d8180a4600190565b50600090565b6001600160a01b03811660009081527fb16e88c42fd4e48df2dd6a2eabd6bc9aec654ec170056b470819f8892cc6431c602052604090205460ff16612ae8576001600160a01b031660008181527fb16e88c42fd4e48df2dd6a2eabd6bc9aec654ec170056b470819f8892cc6431c60205260408120805460ff191660011790553391907fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9080a4600190565b6000818152600080516020613b27833981519152602090815260408083206001600160a01b038616845290915290205460ff16612c5e576000818152600080516020613b27833981519152602090815260408083206001600160a01b0395909516808452949091528120805460ff19166001179055339291907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9080a4600190565b5050600090565b6000818152600080516020613b27833981519152602090815260408083206001600160a01b038616845290915290205460ff1615612c5e576000818152600080516020613b27833981519152602090815260408083206001600160a01b0395909516808452949091528120805460ff19169055339291907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9080a4600190565b600080516020613b47833981519152546040516323b872dd60e01b60208201526001600160a01b039283166024820181905230604483015260648083018790528252949392612d5f9216612d5a6084836122fd565b613206565b6001600160a01b0316928315612954577fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d79181612dad604093600080516020613ae7833981519152546126c9565b600080516020613ae78339815191525585600052600080516020613a87833981519152602052826000208181540190558560007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60208651858152a382519182526020820152a3565b6001600160a01b0383166000818152600080516020613a87833981519152602052604090205491929190818411612e60575050906124ae91612e5782612711565b938491336130c8565b8390632e52afbb60e21b60005260045260245260445260646000fd5b6002600080516020613b678339815191525414612ea7576002600080516020613b6783398151915255565b633ee5aeb560e01b60005260046000fd5b60405163a9059cbb60e01b60208201526001600160a01b03929092166024830152604480830193909352918152612ef491612d5a6064836122fd565b565b8181029291811591840414171561245f57565b9190820391821161245f57565b929190612f228261269b565b93848111612f43576124ae92939450612f3a8161274c565b938492336130c8565b925050633fa733bb60e21b60005260018060a01b031660045260245260445260646000fd5b9190600180612f788484876133a8565b95612f8281613306565b16149283612fa3575b505050612f955790565b6001810180911161245f5790565b909180935015612fb857091515388080612f8b565b634e487b7160e01b600052601260045260246000fd5b916001600160a01b038316918215612856576001600160a01b0316928315612840577f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259161301d6020926121d6565b85600052825280604060002055604051908152a3565b61303b613442565b613043613574565b6040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a0815261309460c0826122fd565b51902090565b60ff600080516020613b878339815191525460401c16156130b757565b631afcd79f60e31b60005260046000fd5b6001600160a01b038084169590821693909182908786036131f5575b505050841561296a576000858152600080516020613a8783398151915260205260408120548281106131db57918181604094897ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db979552600080516020613a87833981519152602052038482205581600080516020613ae78339815191525403600080516020613ae783398151915255877fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60208651858152a3600080516020613b47833981519152546131c490879084906001600160a01b0316612eb8565b825195865260208601526001600160a01b031693a4565b916064928763391434e360e21b8452600452602452604452fd5b6131fe926127c0565b3881816130e4565b60008061322f9260018060a01b03169360208151910182865af1613228613681565b9083613743565b8051908115159182613259575b50506132455750565b635274afe760e01b60005260045260246000fd5b81925090602091810103126121bb57602001518015908115036121bb57388061323c565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116132fa579160209360809260ff60009560405194855216868401526040830152606082015282805260015afa156123af576000516001600160a01b038116156132ee5790600090600090565b50600090600190600090565b50505060009160039190565b6004111561331057565b634e487b7160e01b600052602160045260246000fd5b61332f81613306565b80613338575050565b61334181613306565b6001810361335a5763f645eedf60e01b60005260046000fd5b61336381613306565b60028103613380575063fce698f760e01b60005260045260246000fd5b60039061338c81613306565b146133945750565b6335e2f38360e21b60005260045260246000fd5b90918282029160001984820993838086109503948086039514613434578483111561342357829109816000038216809204600281600302188082026002030280820260020302808202600203028082026002030280820260020302809102600203029360018380600003040190848311900302920304170290565b63227bc15360e01b60005260046000fd5b505091508115612fb8570490565b604051600080516020613aa78339815191525490600081613462846123bb565b91828252602082019460018116908160001461355857506001146134eb575b61348d925003826122fd565b51908115613499572090565b50507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1005480156134c65790565b507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47090565b50600080516020613aa7833981519152600090815290917f42ad5d3e1f2e6e70edcf6d991b8a3023d3fca8047a131592f9edb9fd9b89d57d5b81831061353c57505090602061348d92820101613481565b6020919350806001915483858801015201910190918392613524565b60ff191686525061348d92151560051b82016020019050613481565b604051600080516020613b078339815191525490600081613594846123bb565b91828252602082019460018116908160001461366557506001146135f8575b6135bf925003826122fd565b519081156135cb572090565b50507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1015480156134c65790565b50600080516020613b07833981519152600090815290917f5f9ce34815f8e11431c7bb75a8e6886a91478f7ffc1dbb0a98dc240fddd76b755b8183106136495750509060206135bf928201016135b3565b6020919350806001915483858801015201910190918392613631565b60ff19168652506135bf92151560051b820160200190506135b3565b3d156136bc573d9067ffffffffffffffff821161231f57604051916136b0601f8201601f1916602001846122fd565b82523d6000602084013e565b606090565b60008091604051602081019063313ce56760e01b8252600481526136e66024826122fd565b51916001600160a01b03165afa6136fb613681565b9080613737575b613710575b50600090600090565b602081519181808201938492010103126121bb575160ff8111613707579060ff6001921690565b50602081511015613702565b90613769575080511561375857805190602001fd5b630a12f52160e11b60005260046000fd5b8151158061379b575b61377a575090565b639996b31560e01b60009081526001600160a01b0391909116600452602490fd5b50803b1561377256fe60c034608a57601f6102c238819003918201601f19168301916001600160401b03831184841017608f578084926040948552833981010312608a57604b602060458360a5565b920160a5565b6080919091526001600160a01b031660a05260405161020990816100b98239608051818181606801526101cd015260a05181818160bd015261018b0152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203608a5756fe608080604052600436101561001357600080fd5b60003560e01c9081636aae211e146101ba57508063ac089a09146101755763f3fef3a31461004057600080fd5b34610136576040366003190112610136576004356001600160a01b03811690819003610136577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633036101645760405163a9059cbb60e01b81526004810191909152602480359082015260208160448160007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af18015610158576100f357005b60203d602011610151575b601f8101601f1916820167ffffffffffffffff81118382101761013b5760209183916040528101031261013657518015150361013657005b600080fd5b634e487b7160e01b600052604160045260246000fd5b503d6100fe565b6040513d6000823e3d90fd5b6317dd114560e01b60005260046000fd5b34610136576000366003190112610136576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610136576000366003190112610136577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f3fea164736f6c634300081a000a52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0352c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00a16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10252c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0452c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02a16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10302dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268000773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e009b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a164736f6c634300081a000a","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"paris","libraries":{},"metadata":{"bytecodeHash":"none"},"optimizer":{"enabled":true,"runs":200},"remappings":[],"viaIR":true},"optimization_runs":200,"sourcify_repo_url":null,"decoded_constructor_args":null,"compiler_version":"0.8.26+commit.8a97fa7a","is_verified_via_verifier_alliance":true,"verified_at":"2025-10-17T16:45:53.708861Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x6080806040523460d2577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c1660c1576002600160401b03196001600160401b03821601605c575b604051613bb390816100d88239f35b6001600160401b0319166001600160401b039081177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005581527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a13880604d565b63f92ee8a960e01b60005260046000fd5b600080fdfe608080604052600436101561001357600080fd5b600090813560e01c90816301320fe21461215d5750806301e1d1141461214257806301ffc9a7146120eb57806306fdde031461202a57806307a2d13a14611463578063095ea7b3146120035780630a28a47714611fe457806318160ddd14611fb95780631e9049cf14611f9b57806323b872dd14611f62578063248a9ca314611f435780632f2ff15d14611f11578063313ce56714611ec25780633526931514611ea05780633644e51514611e8557806336568abe14611e4057806338d52e0f14611e0a578063402d267d146108a7578063485cc955146114685780634cdad506146114635780634f115da514611419578063597a3fd3146113f75780636e553f65146113c357806370a082311461044e57806375b238fc146113885780637ecebe001461133157806380060c851461129557806384b0196e14610fb957806391d1485414610f6357806394bf804d14610f2f57806395d89b4114610e2e578063a217fddf14610e12578063a2af490014610cf4578063a9059cbb14610cc2578063b37fd19014610b6c578063b3d7f6b914610b4d578063b460af9414610b33578063b6306ce5146109eb578063ba087652146109d1578063c1d3e026146109a4578063c3c05293146108ac578063c63d75b6146108a7578063c6e6f592146103d5578063ce23eb3c14610806578063ce96cb77146107e2578063d505accf14610674578063d50655b0146104d8578063d547741f1461049d578063d905777e1461044e578063dd62ed3e14610405578063eb3beb29146103da578063ef8b30f7146103d55763f2888dbb1461026857600080fd5b346103d25760203660031901126103d2576102816121a5565b610289612e7c565b6001600160a01b0381169081156103a157338352600160205260408320908154916001600160681b038360681c93164210801590610393575b156103845760009055835460181c6001600160a01b0316908490823b156103805760405163f3fef3a360e01b81526001600160a01b0391909116600482015260248101849052918290604490829084905af1801561037557610361575b506040519081527fd8654fcc8cf5b36d30b3f5e4688fc78118e6d68de60b9994e09902268b57c3e360203392a36001600080516020613b678339815191525580f35b8361036e919492946122fd565b913861031f565b6040513d86823e3d90fd5b5080fd5b63039a040560e21b8552600485fd5b5062ffffff855416156102c2565b60405163eac0d38960e01b81526020600482015260086024820152673932b1b2b4bb32b960c11b6044820152606490fd5b80fd5b6122df565b50346103d257806003193601126103d2575460405160189190911c6001600160a01b03168152602090f35b50346103d25760403660031901126103d25760406020916104246121a5565b61043561042f6121c0565b916121d6565b6001600160a01b03909116825283522054604051908152f35b50346103d25760203660031901126103d257602061049561046d6121a5565b6001600160a01b03166000908152600080516020613a87833981519152602052604090205490565b604051908152f35b50346103d25760403660031901126103d2576104d46004356104bd6121c0565b906104cf6104ca826123f5565b6129f2565b612c65565b5080f35b50346103d25760403660031901126103d257600435906104f66121c0565b9062ffffff815416918215610665578315610656576001600160a01b03811691338303610611576020946106066001600160681b036105d17feeb98a30820c610e8eb6fd5624b21085d2d6a6e4180ca779e46b3d03992892729561055e60409984421661243f565b88875260018b52838a88209116841982541617905587865260018a526105bd8987206105976001600160981b038816825460681c612475565b81546001600160681b031660689190911b6cffffffffffffffffffffffffff1916179055565b855460181c6001600160a01b031685612f16565b96848789965260018a52205416604051938493849160409194936001600160681b039160608501968552602085015216910152565b0390a2604051908152f35b60405162461bcd60e51b815260206004820181905260248201527f4f6e6c79206f776e65722063616e20696e69746961746520636f6f6c646f776e6044820152606490fd5b631f2a200560e01b8252600482fd5b631ad051bd60e11b8252600482fd5b50346103d25760e03660031901126103d25761068e6121a5565b906106976121c0565b604435906064359360843560ff811681036107de578542116107ca5761078a6107939160018060a01b038416978888527f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb0060205260408820908154916001830190556040519060208201927f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c984528b604084015260018060a01b038916606084015289608084015260a083015260c082015260c0815261075860e0826122fd565b519020610763613033565b906040519161190160f01b83526002830152602282015260c43591604260a435922061327d565b90929192613326565b6001600160a01b0316948086036107b357506107b0939450612fce565b80f35b6325c0072360e11b85526004869052602452604484fd5b63313c898160e11b85526004869052602485fd5b8480fd5b50346103d25760203660031901126103d25760206104956108016121a5565b61269b565b50346103d25760203660031901126103d25760043562ffffff811680910361038057610830612980565b81549062ffffff821691818314610898576276a70082116108895791816040927f180eacdf7dbaeecaa983d93173b4285db2f2c0de0044697e1f932bbbb73dcaa69462ffffff191617855582519182526020820152a180f35b630dd0b9f560e21b8452600484fd5b632600ca5160e01b8452600484fd5b61226e565b50346103d25760203660031901126103d2576108c66121a5565b906108cf612980565b6001600160a01b03821691821561096e5760025492601084901c6001600160a01b031690811461095f5762010000600160b01b031993909316601082901b62010000600160b01b031617600255604080516001600160a01b03948516815293909116602084015290917f775be72f3c02cdfa3ef9fd431e09d13a08a983f92a707fcc00192a62c6e44d719190a180f35b630a16a5ff60e21b8352600483fd5b60405163eac0d38960e01b815260206004820152600d60248201526c1a5b9cdd5c985b98d9519d5b99609a1b6044820152606490fd5b50346103d257806003193601126103d25760025460405160109190911c6001600160a01b03168152602090f35b50346103d25760206104956109e5366122a5565b916125a0565b50346103d25760403660031901126103d257610a05612294565b610a0d6121c0565b90610a16612980565b6002549061ffff821615801590610b1d575b610ae25761ffff16906127108211610ad3576001600160a01b03831690811561096e576040837ffc2e3ec7f4564261ba6f9f8a56d29b5047d6709ba32beffceea07ba302b5861c9282957f775be72f3c02cdfa3ef9fd431e09d13a08a983f92a707fcc00192a62c6e44d719762010000600160b01b039060101b169169ffffffffffffffffffff60b01b1617176002558151908782526020820152a18151908482526020820152a180f35b6358d620b360e01b8452600484fd5b60405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606490fd5b50601082901c6001600160a01b03161515610a28565b50346103d2576020610495610b47366122a5565b91612495565b50346103d25760203660031901126103d25760206104956004356126d6565b50346103d25760603660031901126103d257610b866121a5565b6044356001600160a01b03811692916024359190848203610cbe57610ba9612e7c565b838052600080516020613b278339815191526020908152604080862033875290915284205460ff1615610ca6576001600160a01b0316938415610c785715610c4d578115610c3e57600080516020613b47833981519152546001600160a01b03168414610c2f57610c1a9293612eb8565b6001600080516020613b678339815191525580f35b63c1ab6dc160e01b8352600483fd5b631f2a200560e01b8352600483fd5b60405163eac0d38960e01b8152602060048201526002602482015261746f60f01b6044820152606490fd5b60405163eac0d38960e01b81526020600482015260056024820152643a37b5b2b760d91b6044820152606490fd5b63e2517d3f60e01b8452336004526024849052604484fd5b8380fd5b50346103d25760403660031901126103d257610ce9610cdf6121a5565b6024359033612891565b602060405160018152f35b50346103d25760403660031901126103d25760043590610d126121c0565b9181549262ffffff841615610e03578115610c3e576001600160a01b03811691338303610611576020947feeb98a30820c610e8eb6fd5624b21085d2d6a6e4180ca779e46b3d0399289272926001600160681b0391604091610d809160181c6001600160a01b031685612e16565b95610d9362ffffff82541684421661243f565b86825260018952838383209116841982541617905585815260018852610dcc8282206105976001600160981b038a16825460681c612475565b858152600188522054169061060660405192839287849160409194936001600160681b039160608501968552602085015216910152565b631ad051bd60e11b8352600483fd5b50346103d257806003193601126103d257602090604051908152f35b50346103d257806003193601126103d2576040519080600080516020613ac78339815191525490610e5e826123bb565b8085529160018116908115610f085750600114610e9e575b610e9a84610e86818603826122fd565b60405191829160208352602083019061220f565b0390f35b600080516020613ac783398151915281527f46a2803e59a4de4e7a4c574b1243f25977ac4c77d5a1a4a609b5394cebb4a2aa939250905b808210610eee57509091508101602001610e8682610e76565b919260018160209254838588010152019101909291610ed5565b60ff191660208087019190915292151560051b85019092019250610e869150839050610e76565b50346103d25760403660031901126103d2576020600435610495610f516121c0565b91610f5b816126d6565b809333612d05565b50346103d25760403660031901126103d25760ff6040602092610f846121c0565b6004358252600080516020613b2783398151915285528282206001600160a01b03909116825284522054604051911615158152f35b50346103d257806003193601126103d2577fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10054158061126c575b1561122f57604051908082600080516020613aa78339815191525491611018836123bb565b808352926001811690811561121057506001146111a5575b61103c925003836122fd565b604051908082600080516020613b07833981519152549161105c836123bb565b8083529260018116908115611186575060011461111b575b61108891939250936110bf959403836122fd565b60206110cd6040519361109b83866122fd565b83855283368137604051968796600f60f81b885260e08589015260e088019061220f565b90868203604088015261220f565b904660608601523060808601528260a086015284820360c08601528080855193848152019401925b82811061110457505050500390f35b8351855286955093810193928101926001016110f5565b50600080516020613b0783398151915283529082907f5f9ce34815f8e11431c7bb75a8e6886a91478f7ffc1dbb0a98dc240fddd76b755b81831061116a57505090602061108892820101611074565b6020919350806001915483858901015201910190918492611152565b6020925061108894915060ff191682840152151560051b820101611074565b50600080516020613aa783398151915283529082907f42ad5d3e1f2e6e70edcf6d991b8a3023d3fca8047a131592f9edb9fd9b89d57d5b8183106111f457505090602061103c92820101611030565b60209193508060019154838589010152019101909184926111dc565b6020925061103c94915060ff191682840152151560051b820101611030565b60405162461bcd60e51b81526020600482015260156024820152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b6044820152606490fd5b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1015415610ff3565b50346103d25760203660031901126103d25761ffff6112b2612294565b6112ba612980565b166127108111611322576002549061ffff8216918183146113135791816040927ffc2e3ec7f4564261ba6f9f8a56d29b5047d6709ba32beffceea07ba302b5861c9461ffff19161760025582519182526020820152a180f35b63989b0a8560e01b8452600484fd5b6358d620b360e01b8252600482fd5b50346103d25760203660031901126103d25760406020916113506121a5565b6001600160a01b031681527f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb0083522054604051908152f35b50346103d257806003193601126103d25760206040517fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217758152f35b50346103d25760403660031901126103d25760206004356104956113e56121c0565b6113ee83612785565b92839133612d05565b50346103d257806003193601126103d257602061ffff60025416604051908152f35b50346103d25760203660031901126103d25760409081906001600160a01b036114406121a5565b168152600160205220548151906001600160681b038116825260681c6020820152f35b612250565b50346103d25760403660031901126103d2576114826121a5565b61148a6121c0565b600080516020613b87833981519152549060ff8260401c16159167ffffffffffffffff811680159081611e02575b6001149081611df8575b159081611def575b50611de05767ffffffffffffffff198116600117600080516020613b878339815191525582611db3575b506001600160a01b038316928315611d87576001600160a01b03821615611d595761151d612416565b9360409485519061152e87836122fd565b60058252641cd65554d160da1b602083015261154861309a565b61155061309a565b80519067ffffffffffffffff8211611d4557819061157c600080516020613a67833981519152546123bb565b601f8111611cca575b50602090601f8311600114611c4b578a92611c40575b50508160011b916000199060031b1c191617600080516020613a67833981519152555b80519067ffffffffffffffff82116119015781906115ea600080516020613ac7833981519152546123bb565b601f8111611bc5575b50602090601f8311600114611b46578992611b3b575b50508160011b916000199060031b1c191617600080516020613ac7833981519152555b61163461309a565b61163c61309a565b611645816136c1565b9015611b33575b600080516020613b47833981519152549060ff60a01b9060a01b16906affffffffffffffffffffff60a81b161717600080516020613b4783398151915255611692612416565b61169a61309a565b8451906116a786836122fd565b60018252603160f81b60208301526116bd61309a565b80519067ffffffffffffffff82116119015781906116e9600080516020613aa7833981519152546123bb565b601f8111611ab8575b50602090601f8311600114611a39578992611a2e575b50508160011b916000199060031b1c191617600080516020613aa7833981519152555b80519067ffffffffffffffff8211611a1a578190611757600080516020613b07833981519152546123bb565b601f811161199f575b50602090601f8311600114611920578892611915575b50508160011b916000199060031b1c191617600080516020613b07833981519152555b847fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10055847fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d101556117e761309a565b6117ef61309a565b6117f761309a565b6001600080516020613b67833981519152558351906102c28083019083821067ffffffffffffffff831117611901579161184b9184936137a585393081526001600160a01b03909116602082015260400190565b039085f09081156118f45784546001600160b81b03191660189290921b6301000000600160b81b03169190911762093a801784556118929061188c81612a3c565b50612aee565b5061189b575080f35b60207fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29168ff000000000000000019600080516020613b878339815191525416600080516020613b87833981519152555160018152a180f35b50505051903d90823e3d90fd5b634e487b7160e01b88526041600452602488fd5b015190503880611776565b600080516020613b0783398151915289528189209250601f198416895b818110611987575090846001959493921061196e575b505050811b01600080516020613b0783398151915255611799565b015160001960f88460031b161c19169055388080611953565b9293602060018192878601518155019501930161193d565b600080516020613b0783398151915289529091507f5f9ce34815f8e11431c7bb75a8e6886a91478f7ffc1dbb0a98dc240fddd76b75601f840160051c81019160208510611a10575b90601f859493920160051c01905b818110611a025750611760565b8981558493506001016119f5565b90915081906119e7565b634e487b7160e01b87526041600452602487fd5b015190503880611708565b600080516020613aa78339815191528a52818a209250601f1984168a5b818110611aa05750908460019594939210611a87575b505050811b01600080516020613aa78339815191525561172b565b015160001960f88460031b161c19169055388080611a6c565b92936020600181928786015181550195019301611a56565b600080516020613aa78339815191528a529091507f42ad5d3e1f2e6e70edcf6d991b8a3023d3fca8047a131592f9edb9fd9b89d57d601f840160051c81019160208510611b29575b90601f859493920160051c01905b818110611b1b57506116f2565b8a8155849350600101611b0e565b9091508190611b00565b50601261164c565b015190503880611609565b600080516020613ac78339815191528a52818a209250601f1984168a5b818110611bad5750908460019594939210611b94575b505050811b01600080516020613ac78339815191525561162c565b015160001960f88460031b161c19169055388080611b79565b92936020600181928786015181550195019301611b63565b600080516020613ac78339815191528a529091507f46a2803e59a4de4e7a4c574b1243f25977ac4c77d5a1a4a609b5394cebb4a2aa601f840160051c81019160208510611c36575b90601f859493920160051c01905b818110611c2857506115f3565b8a8155849350600101611c1b565b9091508190611c0d565b01519050388061159b565b600080516020613a678339815191528b52818b209250601f1984168b5b818110611cb25750908460019594939210611c99575b505050811b01600080516020613a67833981519152556115be565b015160001960f88460031b161c19169055388080611c7e565b92936020600181928786015181550195019301611c68565b600080516020613a678339815191528b529091507f2ae08a8e29253f69ac5d979a101956ab8f8d9d7ded63fa7a83b16fc47648eab0601f840160051c81019160208510611d3b575b90601f859493920160051c01905b818110611d2d5750611585565b8b8155849350600101611d20565b9091508190611d12565b634e487b7160e01b89526041600452602489fd5b60405163eac0d38960e01b815260206004820152600560248201526420b236b4b760d91b6044820152606490fd5b606460405163eac0d38960e01b8152602060048201526004602482015263165554d160e21b6044820152fd5b68ffffffffffffffffff19166801000000000000000117600080516020613b8783398151915255386114f4565b63f92ee8a960e01b8552600485fd5b905015386114ca565b303b1591506114c2565b8491506114b8565b50346103d257806003193601126103d257600080516020613b47833981519152546040516001600160a01b039091168152602090f35b50346103d25760403660031901126103d257611e5a6121c0565b336001600160a01b03821603611e76576104d490600435612c65565b63334bd91960e11b8252600482fd5b50346103d257806003193601126103d2576020610495613033565b50346103d257806003193601126103d25762ffffff6020915416604051908152f35b50346103d257806003193601126103d25760ff600080516020613b478339815191525460a01c169060ff8211611efd57602082604051908152f35b634e487b7160e01b81526011600452602490fd5b50346103d25760403660031901126103d2576104d4600435611f316121c0565b90611f3e6104ca826123f5565b612bbc565b50346103d25760203660031901126103d25760206104956004356123f5565b50346103d25760603660031901126103d257610ce9611f7f6121a5565b611f876121c0565b60443591611f968333836127c0565b612891565b50346103d257806003193601126103d25760206040516276a7008152f35b50346103d257806003193601126103d2576020600080516020613ae783398151915254604051908152f35b50346103d25760203660031901126103d257602061049560043561274c565b50346103d25760403660031901126103d257610ce96120206121a5565b6024359033612fce565b50346103d257806003193601126103d2576040519080600080516020613a67833981519152549061205a826123bb565b8085529160018116908115610f08575060011461208157610e9a84610e86818603826122fd565b600080516020613a6783398151915281527f2ae08a8e29253f69ac5d979a101956ab8f8d9d7ded63fa7a83b16fc47648eab0939250905b8082106120d157509091508101602001610e8682610e76565b9192600181602092548385880101520191019092916120b8565b50346103d25760203660031901126103d25760043563ffffffff60e01b811680910361038057602090637965db0b60e01b8114908115612131575b506040519015158152f35b6301ffc9a760e01b14905082612126565b50346103d257806003193601126103d2576020610495612335565b9050346103805760203660031901126103805760409182906001600160a01b036121856121a5565b168152600160205220546001600160681b038116825260681c6020820152f35b600435906001600160a01b03821682036121bb57565b600080fd5b602435906001600160a01b03821682036121bb57565b6001600160a01b031660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020526040902090565b919082519283825260005b84811061223b575050826000602080949584010152601f8019910116010190565b8060208092840101518282860101520161221a565b346121bb5760203660031901126121bb576020610495600435612711565b346121bb5760203660031901126121bb576122876121a5565b5060206040516000198152f35b6004359061ffff821682036121bb57565b60609060031901126121bb57600435906024356001600160a01b03811681036121bb57906044356001600160a01b03811681036121bb5790565b346121bb5760203660031901126121bb576020610495600435612785565b90601f8019910116810190811067ffffffffffffffff82111761231f57604052565b634e487b7160e01b600052604160045260246000fd5b600080516020613b47833981519152546040516370a0823160e01b815230600482015290602090829060249082906001600160a01b03165afa9081156123af57600091612380575090565b90506020813d6020116123a7575b8161239b602093836122fd565b810103126121bb575190565b3d915061238e565b6040513d6000823e3d90fd5b90600182811c921680156123eb575b60208310146123d557565b634e487b7160e01b600052602260045260246000fd5b91607f16916123ca565b600052600080516020613b2783398151915260205260016040600020015490565b604051906124256040836122fd565b600b82526a14dd185ad95908165554d160aa1b6020830152565b906001600160681b03809116911601906001600160681b03821161245f57565b634e487b7160e01b600052601160045260246000fd5b906001600160981b03809116911601906001600160981b03821161245f57565b60005491929162ffffff166124b157916124ae92612f16565b90565b600254601081901c6001600160a01b03161561258f5760406127106124fb61ffff7fc8dfda6e2d197297ceadecc95d363b1c65f67f827b63379405f05e3eab2f5cbc941685612ef6565b04946125138561250b8887612f09565b953090612f16565b958061255c575b600080516020613b478339815191525461254090869084906001600160a01b0316612eb8565b825194855260208501526001600160a01b03908116941692a390565b600080516020613b478339815191525460025461258a91839160101c6001600160a01b039081169116612eb8565b61251a565b63ff8907f960e01b60005260046000fd5b60005491929162ffffff166125b957916124ae92612e16565b60025460101c6001600160a01b03161561258f57816125d9913090612e16565b7fc8dfda6e2d197297ceadecc95d363b1c65f67f827b63379405f05e3eab2f5cbc60406002549461261c61271061261461ffff891687612ef6565b048095612f09565b95848061266b575b5050600080516020613b478339815191525461264c90879083906001600160a01b0316612eb8565b815186815260208101949094526001600160a01b03908116941692a390565b600080516020613b47833981519152546126949260101c6001600160a01b039081169116612eb8565b3884612624565b6001600160a01b03166000908152600080516020613a8783398151915260205260409020546124ae90612711565b9190820180921161245f57565b6126de612335565b906001820180921161245f57600080516020613ae7833981519152546001810180911161245f576124ae92600192612f68565b612719612335565b906001820180921161245f57600080516020613ae7833981519152546001810180911161245f576124ae92600092612f68565b600080516020613ae78339815191525460019081810180911161245f57612771612335565b9082820180921161245f576124ae93612f68565b600080516020613ae783398151915254906001820180921161245f576127a9612335565b6001810180911161245f576124ae92600092612f68565b91906127cb836121d6565b60018060a01b0382166000526020526040600020549260001984036127f1575b50505050565b82841061286c576001600160a01b03811615612856576001600160a01b038216156128405761281f906121d6565b9060018060a01b0316600052602052604060002091039055388080806127eb565b634a1406b160e11b600052600060045260246000fd5b63e602df0560e01b600052600060045260246000fd5b508290637dc7a0d960e11b60005260018060a01b031660045260245260445260646000fd5b6001600160a01b031690811561296a576001600160a01b0316918215612954576000828152600080516020613a87833981519152602052604081205482811061293a5791604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef958760209652600080516020613a8783398151915286520382822055868152600080516020613a87833981519152845220818154019055604051908152a3565b916064928463391434e360e21b8452600452602452604452fd5b63ec442f0560e01b600052600060045260246000fd5b634b637e8f60e11b600052600060045260246000fd5b3360009081527fb16e88c42fd4e48df2dd6a2eabd6bc9aec654ec170056b470819f8892cc6431c602052604090205460ff16156129b957565b63e2517d3f60e01b600052336004527fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177560245260446000fd5b6000818152600080516020613b278339815191526020908152604080832033845290915290205460ff1615612a245750565b63e2517d3f60e01b6000523360045260245260446000fd5b6001600160a01b03811660009081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff16612ae8576001600160a01b031660008181527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d60205260408120805460ff191660011790553391907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d8180a4600190565b50600090565b6001600160a01b03811660009081527fb16e88c42fd4e48df2dd6a2eabd6bc9aec654ec170056b470819f8892cc6431c602052604090205460ff16612ae8576001600160a01b031660008181527fb16e88c42fd4e48df2dd6a2eabd6bc9aec654ec170056b470819f8892cc6431c60205260408120805460ff191660011790553391907fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9080a4600190565b6000818152600080516020613b27833981519152602090815260408083206001600160a01b038616845290915290205460ff16612c5e576000818152600080516020613b27833981519152602090815260408083206001600160a01b0395909516808452949091528120805460ff19166001179055339291907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9080a4600190565b5050600090565b6000818152600080516020613b27833981519152602090815260408083206001600160a01b038616845290915290205460ff1615612c5e576000818152600080516020613b27833981519152602090815260408083206001600160a01b0395909516808452949091528120805460ff19169055339291907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9080a4600190565b600080516020613b47833981519152546040516323b872dd60e01b60208201526001600160a01b039283166024820181905230604483015260648083018790528252949392612d5f9216612d5a6084836122fd565b613206565b6001600160a01b0316928315612954577fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d79181612dad604093600080516020613ae7833981519152546126c9565b600080516020613ae78339815191525585600052600080516020613a87833981519152602052826000208181540190558560007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60208651858152a382519182526020820152a3565b6001600160a01b0383166000818152600080516020613a87833981519152602052604090205491929190818411612e60575050906124ae91612e5782612711565b938491336130c8565b8390632e52afbb60e21b60005260045260245260445260646000fd5b6002600080516020613b678339815191525414612ea7576002600080516020613b6783398151915255565b633ee5aeb560e01b60005260046000fd5b60405163a9059cbb60e01b60208201526001600160a01b03929092166024830152604480830193909352918152612ef491612d5a6064836122fd565b565b8181029291811591840414171561245f57565b9190820391821161245f57565b929190612f228261269b565b93848111612f43576124ae92939450612f3a8161274c565b938492336130c8565b925050633fa733bb60e21b60005260018060a01b031660045260245260445260646000fd5b9190600180612f788484876133a8565b95612f8281613306565b16149283612fa3575b505050612f955790565b6001810180911161245f5790565b909180935015612fb857091515388080612f8b565b634e487b7160e01b600052601260045260246000fd5b916001600160a01b038316918215612856576001600160a01b0316928315612840577f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259161301d6020926121d6565b85600052825280604060002055604051908152a3565b61303b613442565b613043613574565b6040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a0815261309460c0826122fd565b51902090565b60ff600080516020613b878339815191525460401c16156130b757565b631afcd79f60e31b60005260046000fd5b6001600160a01b038084169590821693909182908786036131f5575b505050841561296a576000858152600080516020613a8783398151915260205260408120548281106131db57918181604094897ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db979552600080516020613a87833981519152602052038482205581600080516020613ae78339815191525403600080516020613ae783398151915255877fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60208651858152a3600080516020613b47833981519152546131c490879084906001600160a01b0316612eb8565b825195865260208601526001600160a01b031693a4565b916064928763391434e360e21b8452600452602452604452fd5b6131fe926127c0565b3881816130e4565b60008061322f9260018060a01b03169360208151910182865af1613228613681565b9083613743565b8051908115159182613259575b50506132455750565b635274afe760e01b60005260045260246000fd5b81925090602091810103126121bb57602001518015908115036121bb57388061323c565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116132fa579160209360809260ff60009560405194855216868401526040830152606082015282805260015afa156123af576000516001600160a01b038116156132ee5790600090600090565b50600090600190600090565b50505060009160039190565b6004111561331057565b634e487b7160e01b600052602160045260246000fd5b61332f81613306565b80613338575050565b61334181613306565b6001810361335a5763f645eedf60e01b60005260046000fd5b61336381613306565b60028103613380575063fce698f760e01b60005260045260246000fd5b60039061338c81613306565b146133945750565b6335e2f38360e21b60005260045260246000fd5b90918282029160001984820993838086109503948086039514613434578483111561342357829109816000038216809204600281600302188082026002030280820260020302808202600203028082026002030280820260020302809102600203029360018380600003040190848311900302920304170290565b63227bc15360e01b60005260046000fd5b505091508115612fb8570490565b604051600080516020613aa78339815191525490600081613462846123bb565b91828252602082019460018116908160001461355857506001146134eb575b61348d925003826122fd565b51908115613499572090565b50507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1005480156134c65790565b507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47090565b50600080516020613aa7833981519152600090815290917f42ad5d3e1f2e6e70edcf6d991b8a3023d3fca8047a131592f9edb9fd9b89d57d5b81831061353c57505090602061348d92820101613481565b6020919350806001915483858801015201910190918392613524565b60ff191686525061348d92151560051b82016020019050613481565b604051600080516020613b078339815191525490600081613594846123bb565b91828252602082019460018116908160001461366557506001146135f8575b6135bf925003826122fd565b519081156135cb572090565b50507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1015480156134c65790565b50600080516020613b07833981519152600090815290917f5f9ce34815f8e11431c7bb75a8e6886a91478f7ffc1dbb0a98dc240fddd76b755b8183106136495750509060206135bf928201016135b3565b6020919350806001915483858801015201910190918392613631565b60ff19168652506135bf92151560051b820160200190506135b3565b3d156136bc573d9067ffffffffffffffff821161231f57604051916136b0601f8201601f1916602001846122fd565b82523d6000602084013e565b606090565b60008091604051602081019063313ce56760e01b8252600481526136e66024826122fd565b51916001600160a01b03165afa6136fb613681565b9080613737575b613710575b50600090600090565b602081519181808201938492010103126121bb575160ff8111613707579060ff6001921690565b50602081511015613702565b90613769575080511561375857805190602001fd5b630a12f52160e11b60005260046000fd5b8151158061379b575b61377a575090565b639996b31560e01b60009081526001600160a01b0391909116600452602490fd5b50803b1561377256fe60c034608a57601f6102c238819003918201601f19168301916001600160401b03831184841017608f578084926040948552833981010312608a57604b602060458360a5565b920160a5565b6080919091526001600160a01b031660a05260405161020990816100b98239608051818181606801526101cd015260a05181818160bd015261018b0152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203608a5756fe608080604052600436101561001357600080fd5b60003560e01c9081636aae211e146101ba57508063ac089a09146101755763f3fef3a31461004057600080fd5b34610136576040366003190112610136576004356001600160a01b03811690819003610136577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633036101645760405163a9059cbb60e01b81526004810191909152602480359082015260208160448160007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af18015610158576100f357005b60203d602011610151575b601f8101601f1916820167ffffffffffffffff81118382101761013b5760209183916040528101031261013657518015150361013657005b600080fd5b634e487b7160e01b600052604160045260246000fd5b503d6100fe565b6040513d6000823e3d90fd5b6317dd114560e01b60005260046000fd5b34610136576000366003190112610136576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610136576000366003190112610136577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f3fea164736f6c634300081a000a52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0352c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00a16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10252c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0452c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02a16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10302dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268000773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e009b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a164736f6c634300081a000a","name":"sYUSD","is_blueprint":false,"license_type":"none","is_fully_verified":false,"is_verified_via_eth_bytecode_db":true,"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.0.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 {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    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\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` to `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.0.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 reininitialization) 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 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        assembly {\n            $.slot := INITIALIZABLE_STORAGE\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.0.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 ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\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     * All two of these values are immutable: they can only be set once during\n     * 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    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual returns (uint256) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $._totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\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    /**\n     * @dev See {IERC20-allowance}.\n     */\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     * Emits an {Approval} event indicating the updated allowance. This is not\n     * required by the EIP. See the note at the beginning of {ERC20}.\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     * 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/token/ERC20/extensions/ERC20PermitUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Permit.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20Permit} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\";\nimport {ERC20Upgradeable} from \"../ERC20Upgradeable.sol\";\nimport {ECDSA} from \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport {EIP712Upgradeable} from \"../../../utils/cryptography/EIP712Upgradeable.sol\";\nimport {NoncesUpgradeable} from \"../../../utils/NoncesUpgradeable.sol\";\nimport {Initializable} from \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\nabstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20Permit, EIP712Upgradeable, NoncesUpgradeable {\n    bytes32 private constant PERMIT_TYPEHASH =\n        keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n\n    /**\n     * @dev Permit deadline has expired.\n     */\n    error ERC2612ExpiredSignature(uint256 deadline);\n\n    /**\n     * @dev Mismatched signature.\n     */\n    error ERC2612InvalidSigner(address signer, address owner);\n\n    /**\n     * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n     *\n     * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n     */\n    function __ERC20Permit_init(string memory name) internal onlyInitializing {\n        __EIP712_init_unchained(name, \"1\");\n    }\n\n    function __ERC20Permit_init_unchained(string memory) internal onlyInitializing {}\n\n    /**\n     * @inheritdoc IERC20Permit\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) public virtual {\n        if (block.timestamp > deadline) {\n            revert ERC2612ExpiredSignature(deadline);\n        }\n\n        bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\n\n        bytes32 hash = _hashTypedDataV4(structHash);\n\n        address signer = ECDSA.recover(hash, v, r, s);\n        if (signer != owner) {\n            revert ERC2612InvalidSigner(signer, owner);\n        }\n\n        _approve(owner, spender, value);\n    }\n\n    /**\n     * @inheritdoc IERC20Permit\n     */\n    function nonces(address owner) public view virtual override(IERC20Permit, NoncesUpgradeable) returns (uint256) {\n        return super.nonces(owner);\n    }\n\n    /**\n     * @inheritdoc IERC20Permit\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view virtual returns (bytes32) {\n        return _domainSeparatorV4();\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC4626.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 {ERC20Upgradeable} from \"../ERC20Upgradeable.sol\";\nimport {SafeERC20} from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {IERC4626} from \"@openzeppelin/contracts/interfaces/IERC4626.sol\";\nimport {Math} from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport {Initializable} from \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the ERC4626 \"Tokenized Vault Standard\" as defined in\n * https://eips.ethereum.org/EIPS/eip-4626[EIP-4626].\n *\n * This extension allows the minting and burning of \"shares\" (represented using the ERC20 inheritance) in exchange for\n * underlying \"assets\" through standardized {deposit}, {mint}, {redeem} and {burn} workflows. This contract extends\n * the ERC20 standard. Any additional extensions included along it would affect the \"shares\" token represented by this\n * contract and not the \"assets\" token which is an independent contract.\n *\n * [CAUTION]\n * ====\n * In empty (or nearly empty) ERC-4626 vaults, deposits are at high risk of being stolen through frontrunning\n * with a \"donation\" to the vault that inflates the price of a share. This is variously known as a donation or inflation\n * attack and is essentially a problem of slippage. Vault deployers can protect against this attack by making an initial\n * deposit of a non-trivial amount of the asset, such that price manipulation becomes infeasible. Withdrawals may\n * similarly be affected by slippage. Users can protect against this attack as well as unexpected slippage in general by\n * verifying the amount received is as expected, using a wrapper that performs these checks such as\n * https://github.com/fei-protocol/ERC4626#erc4626router-and-base[ERC4626Router].\n *\n * Since v4.9, this implementation uses virtual assets and shares to mitigate that risk. The `_decimalsOffset()`\n * corresponds to an offset in the decimal representation between the underlying asset's decimals and the vault\n * decimals. This offset also determines the rate of virtual shares to virtual assets in the vault, which itself\n * determines the initial exchange rate. While not fully preventing the attack, analysis shows that the default offset\n * (0) makes it non-profitable, as a result of the value being captured by the virtual shares (out of the attacker's\n * donation) matching the attacker's expected gains. With a larger offset, the attack becomes orders of magnitude more\n * expensive than it is profitable. More details about the underlying math can be found\n * xref:erc4626.adoc#inflation-attack[here].\n *\n * The drawback of this approach is that the virtual shares do capture (a very small) part of the value being accrued\n * to the vault. Also, if the vault experiences losses, the users try to exit the vault, the virtual shares and assets\n * will cause the first user to exit to experience reduced losses in detriment to the last users that will experience\n * bigger losses. Developers willing to revert back to the pre-v4.9 behavior just need to override the\n * `_convertToShares` and `_convertToAssets` functions.\n *\n * To learn more, check out our xref:ROOT:erc4626.adoc[ERC-4626 guide].\n * ====\n */\nabstract contract ERC4626Upgradeable is Initializable, ERC20Upgradeable, IERC4626 {\n    using Math for uint256;\n\n    /// @custom:storage-location erc7201:openzeppelin.storage.ERC4626\n    struct ERC4626Storage {\n        IERC20 _asset;\n        uint8 _underlyingDecimals;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ERC4626\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant ERC4626StorageLocation = 0x0773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e00;\n\n    function _getERC4626Storage() private pure returns (ERC4626Storage storage $) {\n        assembly {\n            $.slot := ERC4626StorageLocation\n        }\n    }\n\n    /**\n     * @dev Attempted to deposit more assets than the max amount for `receiver`.\n     */\n    error ERC4626ExceededMaxDeposit(address receiver, uint256 assets, uint256 max);\n\n    /**\n     * @dev Attempted to mint more shares than the max amount for `receiver`.\n     */\n    error ERC4626ExceededMaxMint(address receiver, uint256 shares, uint256 max);\n\n    /**\n     * @dev Attempted to withdraw more assets than the max amount for `receiver`.\n     */\n    error ERC4626ExceededMaxWithdraw(address owner, uint256 assets, uint256 max);\n\n    /**\n     * @dev Attempted to redeem more shares than the max amount for `receiver`.\n     */\n    error ERC4626ExceededMaxRedeem(address owner, uint256 shares, uint256 max);\n\n    /**\n     * @dev Set the underlying asset contract. This must be an ERC20-compatible contract (ERC20 or ERC777).\n     */\n    function __ERC4626_init(IERC20 asset_) internal onlyInitializing {\n        __ERC4626_init_unchained(asset_);\n    }\n\n    function __ERC4626_init_unchained(IERC20 asset_) internal onlyInitializing {\n        ERC4626Storage storage $ = _getERC4626Storage();\n        (bool success, uint8 assetDecimals) = _tryGetAssetDecimals(asset_);\n        $._underlyingDecimals = success ? assetDecimals : 18;\n        $._asset = asset_;\n    }\n\n    /**\n     * @dev Attempts to fetch the asset decimals. A return value of false indicates that the attempt failed in some way.\n     */\n    function _tryGetAssetDecimals(IERC20 asset_) private view returns (bool, uint8) {\n        (bool success, bytes memory encodedDecimals) = address(asset_).staticcall(\n            abi.encodeCall(IERC20Metadata.decimals, ())\n        );\n        if (success && encodedDecimals.length >= 32) {\n            uint256 returnedDecimals = abi.decode(encodedDecimals, (uint256));\n            if (returnedDecimals <= type(uint8).max) {\n                return (true, uint8(returnedDecimals));\n            }\n        }\n        return (false, 0);\n    }\n\n    /**\n     * @dev Decimals are computed by adding the decimal offset on top of the underlying asset's decimals. This\n     * \"original\" value is cached during construction of the vault contract. If this read operation fails (e.g., the\n     * asset has not been created yet), a default of 18 is used to represent the underlying asset's decimals.\n     *\n     * See {IERC20Metadata-decimals}.\n     */\n    function decimals() public view virtual override(IERC20Metadata, ERC20Upgradeable) returns (uint8) {\n        ERC4626Storage storage $ = _getERC4626Storage();\n        return $._underlyingDecimals + _decimalsOffset();\n    }\n\n    /** @dev See {IERC4626-asset}. */\n    function asset() public view virtual returns (address) {\n        ERC4626Storage storage $ = _getERC4626Storage();\n        return address($._asset);\n    }\n\n    /** @dev See {IERC4626-totalAssets}. */\n    function totalAssets() public view virtual returns (uint256) {\n        ERC4626Storage storage $ = _getERC4626Storage();\n        return $._asset.balanceOf(address(this));\n    }\n\n    /** @dev See {IERC4626-convertToShares}. */\n    function convertToShares(uint256 assets) public view virtual returns (uint256) {\n        return _convertToShares(assets, Math.Rounding.Floor);\n    }\n\n    /** @dev See {IERC4626-convertToAssets}. */\n    function convertToAssets(uint256 shares) public view virtual returns (uint256) {\n        return _convertToAssets(shares, Math.Rounding.Floor);\n    }\n\n    /** @dev See {IERC4626-maxDeposit}. */\n    function maxDeposit(address) public view virtual returns (uint256) {\n        return type(uint256).max;\n    }\n\n    /** @dev See {IERC4626-maxMint}. */\n    function maxMint(address) public view virtual returns (uint256) {\n        return type(uint256).max;\n    }\n\n    /** @dev See {IERC4626-maxWithdraw}. */\n    function maxWithdraw(address owner) public view virtual returns (uint256) {\n        return _convertToAssets(balanceOf(owner), Math.Rounding.Floor);\n    }\n\n    /** @dev See {IERC4626-maxRedeem}. */\n    function maxRedeem(address owner) public view virtual returns (uint256) {\n        return balanceOf(owner);\n    }\n\n    /** @dev See {IERC4626-previewDeposit}. */\n    function previewDeposit(uint256 assets) public view virtual returns (uint256) {\n        return _convertToShares(assets, Math.Rounding.Floor);\n    }\n\n    /** @dev See {IERC4626-previewMint}. */\n    function previewMint(uint256 shares) public view virtual returns (uint256) {\n        return _convertToAssets(shares, Math.Rounding.Ceil);\n    }\n\n    /** @dev See {IERC4626-previewWithdraw}. */\n    function previewWithdraw(uint256 assets) public view virtual returns (uint256) {\n        return _convertToShares(assets, Math.Rounding.Ceil);\n    }\n\n    /** @dev See {IERC4626-previewRedeem}. */\n    function previewRedeem(uint256 shares) public view virtual returns (uint256) {\n        return _convertToAssets(shares, Math.Rounding.Floor);\n    }\n\n    /** @dev See {IERC4626-deposit}. */\n    function deposit(uint256 assets, address receiver) public virtual returns (uint256) {\n        uint256 maxAssets = maxDeposit(receiver);\n        if (assets > maxAssets) {\n            revert ERC4626ExceededMaxDeposit(receiver, assets, maxAssets);\n        }\n\n        uint256 shares = previewDeposit(assets);\n        _deposit(_msgSender(), receiver, assets, shares);\n\n        return shares;\n    }\n\n    /** @dev See {IERC4626-mint}.\n     *\n     * As opposed to {deposit}, minting is allowed even if the vault is in a state where the price of a share is zero.\n     * In this case, the shares will be minted without requiring any assets to be deposited.\n     */\n    function mint(uint256 shares, address receiver) public virtual returns (uint256) {\n        uint256 maxShares = maxMint(receiver);\n        if (shares > maxShares) {\n            revert ERC4626ExceededMaxMint(receiver, shares, maxShares);\n        }\n\n        uint256 assets = previewMint(shares);\n        _deposit(_msgSender(), receiver, assets, shares);\n\n        return assets;\n    }\n\n    /** @dev See {IERC4626-withdraw}. */\n    function withdraw(uint256 assets, address receiver, address owner) public virtual returns (uint256) {\n        uint256 maxAssets = maxWithdraw(owner);\n        if (assets > maxAssets) {\n            revert ERC4626ExceededMaxWithdraw(owner, assets, maxAssets);\n        }\n\n        uint256 shares = previewWithdraw(assets);\n        _withdraw(_msgSender(), receiver, owner, assets, shares);\n\n        return shares;\n    }\n\n    /** @dev See {IERC4626-redeem}. */\n    function redeem(uint256 shares, address receiver, address owner) public virtual returns (uint256) {\n        uint256 maxShares = maxRedeem(owner);\n        if (shares > maxShares) {\n            revert ERC4626ExceededMaxRedeem(owner, shares, maxShares);\n        }\n\n        uint256 assets = previewRedeem(shares);\n        _withdraw(_msgSender(), receiver, owner, assets, shares);\n\n        return assets;\n    }\n\n    /**\n     * @dev Internal conversion function (from assets to shares) with support for rounding direction.\n     */\n    function _convertToShares(uint256 assets, Math.Rounding rounding) internal view virtual returns (uint256) {\n        return assets.mulDiv(totalSupply() + 10 ** _decimalsOffset(), totalAssets() + 1, rounding);\n    }\n\n    /**\n     * @dev Internal conversion function (from shares to assets) with support for rounding direction.\n     */\n    function _convertToAssets(uint256 shares, Math.Rounding rounding) internal view virtual returns (uint256) {\n        return shares.mulDiv(totalAssets() + 1, totalSupply() + 10 ** _decimalsOffset(), rounding);\n    }\n\n    /**\n     * @dev Deposit/mint common workflow.\n     */\n    function _deposit(address caller, address receiver, uint256 assets, uint256 shares) internal virtual {\n        ERC4626Storage storage $ = _getERC4626Storage();\n        // If _asset is ERC777, `transferFrom` can trigger a reentrancy BEFORE the transfer happens through the\n        // `tokensToSend` hook. On the other hand, the `tokenReceived` hook, that is triggered after the transfer,\n        // calls the vault, which is assumed not malicious.\n        //\n        // Conclusion: we need to do the transfer before we mint so that any reentrancy would happen before the\n        // assets are transferred and before the shares are minted, which is a valid state.\n        // slither-disable-next-line reentrancy-no-eth\n        SafeERC20.safeTransferFrom($._asset, caller, address(this), assets);\n        _mint(receiver, shares);\n\n        emit Deposit(caller, receiver, assets, shares);\n    }\n\n    /**\n     * @dev Withdraw/redeem common workflow.\n     */\n    function _withdraw(\n        address caller,\n        address receiver,\n        address owner,\n        uint256 assets,\n        uint256 shares\n    ) internal virtual {\n        ERC4626Storage storage $ = _getERC4626Storage();\n        if (caller != owner) {\n            _spendAllowance(owner, caller, shares);\n        }\n\n        // If _asset is ERC777, `transfer` can trigger a reentrancy AFTER the transfer happens through the\n        // `tokensReceived` hook. On the other hand, the `tokensToSend` hook, that is triggered before the transfer,\n        // calls the vault, which is assumed not malicious.\n        //\n        // Conclusion: we need to do the transfer after the burn so that any reentrancy would happen after the\n        // shares are burned and after the assets are transferred, which is a valid state.\n        _burn(owner, shares);\n        SafeERC20.safeTransfer($._asset, receiver, assets);\n\n        emit Withdraw(caller, receiver, owner, assets, shares);\n    }\n\n    function _decimalsOffset() internal view virtual returns (uint8) {\n        return 0;\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/NoncesUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Nonces.sol)\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides tracking nonces for addresses. Nonces will only increment.\n */\nabstract contract NoncesUpgradeable is Initializable {\n    /**\n     * @dev The nonce used for an `account` is not the expected current nonce.\n     */\n    error InvalidAccountNonce(address account, uint256 currentNonce);\n\n    /// @custom:storage-location erc7201:openzeppelin.storage.Nonces\n    struct NoncesStorage {\n        mapping(address account => uint256) _nonces;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Nonces\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant NoncesStorageLocation = 0x5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb00;\n\n    function _getNoncesStorage() private pure returns (NoncesStorage storage $) {\n        assembly {\n            $.slot := NoncesStorageLocation\n        }\n    }\n\n    function __Nonces_init() internal onlyInitializing {\n    }\n\n    function __Nonces_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev Returns the next unused nonce for an address.\n     */\n    function nonces(address owner) public view virtual returns (uint256) {\n        NoncesStorage storage $ = _getNoncesStorage();\n        return $._nonces[owner];\n    }\n\n    /**\n     * @dev Consumes a nonce.\n     *\n     * Returns the current value and increments nonce.\n     */\n    function _useNonce(address owner) internal virtual returns (uint256) {\n        NoncesStorage storage $ = _getNoncesStorage();\n        // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be\n        // decremented or reset. This guarantees that the nonce never overflows.\n        unchecked {\n            // It is important to do x++ and not ++x here.\n            return $._nonces[owner]++;\n        }\n    }\n\n    /**\n     * @dev Same as {_useNonce} but checking that `nonce` is the next valid for `owner`.\n     */\n    function _useCheckedNonce(address owner, uint256 nonce) internal virtual {\n        uint256 current = _useNonce(owner);\n        if (nonce != current) {\n            revert InvalidAccountNonce(owner, current);\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.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 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/cryptography/EIP712Upgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.20;\n\nimport {MessageHashUtils} from \"@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol\";\nimport {IERC5267} from \"@openzeppelin/contracts/interfaces/IERC5267.sol\";\nimport {Initializable} from \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose\n * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract\n * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to\n * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain\n * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the\n * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.\n */\nabstract contract EIP712Upgradeable is Initializable, IERC5267 {\n    bytes32 private constant TYPE_HASH =\n        keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n\n    /// @custom:storage-location erc7201:openzeppelin.storage.EIP712\n    struct EIP712Storage {\n        /// @custom:oz-renamed-from _HASHED_NAME\n        bytes32 _hashedName;\n        /// @custom:oz-renamed-from _HASHED_VERSION\n        bytes32 _hashedVersion;\n\n        string _name;\n        string _version;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.EIP712\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant EIP712StorageLocation = 0xa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100;\n\n    function _getEIP712Storage() private pure returns (EIP712Storage storage $) {\n        assembly {\n            $.slot := EIP712StorageLocation\n        }\n    }\n\n    /**\n     * @dev Initializes the domain separator and parameter caches.\n     *\n     * The meaning of `name` and `version` is specified in\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n     *\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n     * - `version`: the current major version of the signing domain.\n     *\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n     * contract upgrade].\n     */\n    function __EIP712_init(string memory name, string memory version) internal onlyInitializing {\n        __EIP712_init_unchained(name, version);\n    }\n\n    function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing {\n        EIP712Storage storage $ = _getEIP712Storage();\n        $._name = name;\n        $._version = version;\n\n        // Reset prior values in storage if upgrading\n        $._hashedName = 0;\n        $._hashedVersion = 0;\n    }\n\n    /**\n     * @dev Returns the domain separator for the current chain.\n     */\n    function _domainSeparatorV4() internal view returns (bytes32) {\n        return _buildDomainSeparator();\n    }\n\n    function _buildDomainSeparator() private view returns (bytes32) {\n        return keccak256(abi.encode(TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash(), block.chainid, address(this)));\n    }\n\n    /**\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n     * function returns the hash of the fully encoded EIP712 message for this domain.\n     *\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n     *\n     * ```solidity\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n     *     keccak256(\"Mail(address to,string contents)\"),\n     *     mailTo,\n     *     keccak256(bytes(mailContents))\n     * )));\n     * address signer = ECDSA.recover(digest, signature);\n     * ```\n     */\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n        return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash);\n    }\n\n    /**\n     * @dev See {IERC-5267}.\n     */\n    function eip712Domain()\n        public\n        view\n        virtual\n        returns (\n            bytes1 fields,\n            string memory name,\n            string memory version,\n            uint256 chainId,\n            address verifyingContract,\n            bytes32 salt,\n            uint256[] memory extensions\n        )\n    {\n        EIP712Storage storage $ = _getEIP712Storage();\n        // If the hashed name and version in storage are non-zero, the contract hasn't been properly initialized\n        // and the EIP712 domain is not reliable, as it will be missing name and version.\n        require($._hashedName == 0 && $._hashedVersion == 0, \"EIP712: Uninitialized\");\n\n        return (\n            hex\"0f\", // 01111\n            _EIP712Name(),\n            _EIP712Version(),\n            block.chainid,\n            address(this),\n            bytes32(0),\n            new uint256[](0)\n        );\n    }\n\n    /**\n     * @dev The name parameter for the EIP712 domain.\n     *\n     * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n     * are a concern.\n     */\n    function _EIP712Name() internal view virtual returns (string memory) {\n        EIP712Storage storage $ = _getEIP712Storage();\n        return $._name;\n    }\n\n    /**\n     * @dev The version parameter for the EIP712 domain.\n     *\n     * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n     * are a concern.\n     */\n    function _EIP712Version() internal view virtual returns (string memory) {\n        EIP712Storage storage $ = _getEIP712Storage();\n        return $._version;\n    }\n\n    /**\n     * @dev The hash of the name parameter for the EIP712 domain.\n     *\n     * NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Name` instead.\n     */\n    function _EIP712NameHash() internal view returns (bytes32) {\n        EIP712Storage storage $ = _getEIP712Storage();\n        string memory name = _EIP712Name();\n        if (bytes(name).length > 0) {\n            return keccak256(bytes(name));\n        } else {\n            // If the name is empty, the contract may have been upgraded without initializing the new storage.\n            // We return the name hash in storage if non-zero, otherwise we assume the name is empty by design.\n            bytes32 hashedName = $._hashedName;\n            if (hashedName != 0) {\n                return hashedName;\n            } else {\n                return keccak256(\"\");\n            }\n        }\n    }\n\n    /**\n     * @dev The hash of the version parameter for the EIP712 domain.\n     *\n     * NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Version` instead.\n     */\n    function _EIP712VersionHash() internal view returns (bytes32) {\n        EIP712Storage storage $ = _getEIP712Storage();\n        string memory version = _EIP712Version();\n        if (bytes(version).length > 0) {\n            return keccak256(bytes(version));\n        } else {\n            // If the version is empty, the contract may have been upgraded without initializing the new storage.\n            // We return the version hash in storage if non-zero, otherwise we assume the version is empty by design.\n            bytes32 hashedVersion = $._hashedVersion;\n            if (hashedVersion != 0) {\n                return hashedVersion;\n            } else {\n                return keccak256(\"\");\n            }\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.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 ERC165 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    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\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.0.0) (access/IAccessControl.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 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 signaling 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, an admin role\n     * bearer except when using {AccessControl-_setupRole}.\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/IERC4626.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC4626.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\nimport {IERC20Metadata} from \"../token/ERC20/extensions/IERC20Metadata.sol\";\n\n/**\n * @dev Interface of the ERC4626 \"Tokenized Vault Standard\", as defined in\n * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].\n */\ninterface IERC4626 is IERC20, IERC20Metadata {\n    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);\n\n    event Withdraw(\n        address indexed sender,\n        address indexed receiver,\n        address indexed owner,\n        uint256 assets,\n        uint256 shares\n    );\n\n    /**\n     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.\n     *\n     * - MUST be an ERC-20 token contract.\n     * - MUST NOT revert.\n     */\n    function asset() external view returns (address assetTokenAddress);\n\n    /**\n     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.\n     *\n     * - SHOULD include any compounding that occurs from yield.\n     * - MUST be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT revert.\n     */\n    function totalAssets() external view returns (uint256 totalManagedAssets);\n\n    /**\n     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal\n     * scenario where all the conditions are met.\n     *\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT show any variations depending on the caller.\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n     * - MUST NOT revert.\n     *\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n     * from.\n     */\n    function convertToShares(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal\n     * scenario where all the conditions are met.\n     *\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT show any variations depending on the caller.\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n     * - MUST NOT revert.\n     *\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n     * from.\n     */\n    function convertToAssets(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,\n     * through a deposit call.\n     *\n     * - MUST return a limited value if receiver is subject to some deposit limit.\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.\n     * - MUST NOT revert.\n     */\n    function maxDeposit(address receiver) external view returns (uint256 maxAssets);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given\n     * current on-chain conditions.\n     *\n     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit\n     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called\n     *   in the same transaction.\n     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the\n     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n     */\n    function previewDeposit(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.\n     *\n     * - MUST emit the Deposit event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   deposit execution, and are accounted for during deposit.\n     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not\n     *   approving enough underlying tokens to the Vault contract, etc).\n     *\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n     */\n    function deposit(uint256 assets, address receiver) external returns (uint256 shares);\n\n    /**\n     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.\n     * - MUST return a limited value if receiver is subject to some mint limit.\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.\n     * - MUST NOT revert.\n     */\n    function maxMint(address receiver) external view returns (uint256 maxShares);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given\n     * current on-chain conditions.\n     *\n     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call\n     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the\n     *   same transaction.\n     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint\n     *   would be accepted, regardless if the user has enough tokens approved, etc.\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by minting.\n     */\n    function previewMint(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.\n     *\n     * - MUST emit the Deposit event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint\n     *   execution, and are accounted for during mint.\n     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not\n     *   approving enough underlying tokens to the Vault contract, etc).\n     *\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n     */\n    function mint(uint256 shares, address receiver) external returns (uint256 assets);\n\n    /**\n     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the\n     * Vault, through a withdraw call.\n     *\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n     * - MUST NOT revert.\n     */\n    function maxWithdraw(address owner) external view returns (uint256 maxAssets);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,\n     * given current on-chain conditions.\n     *\n     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw\n     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if\n     *   called\n     *   in the same transaction.\n     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though\n     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n     */\n    function previewWithdraw(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.\n     *\n     * - MUST emit the Withdraw event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   withdraw execution, and are accounted for during withdraw.\n     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner\n     *   not having enough shares, etc).\n     *\n     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n     * Those methods should be performed separately.\n     */\n    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);\n\n    /**\n     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,\n     * through a redeem call.\n     *\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.\n     * - MUST NOT revert.\n     */\n    function maxRedeem(address owner) external view returns (uint256 maxShares);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,\n     * given current on-chain conditions.\n     *\n     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call\n     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the\n     *   same transaction.\n     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the\n     *   redemption would be accepted, regardless if the user has enough shares, etc.\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.\n     */\n    function previewRedeem(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.\n     *\n     * - MUST emit the Withdraw event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   redeem execution, and are accounted for during redeem.\n     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner\n     *   not having enough shares, etc).\n     *\n     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n     * Those methods should be performed separately.\n     */\n    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);\n}\n"},{"file_path":"@openzeppelin/contracts/interfaces/IERC5267.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)\n\npragma solidity ^0.8.20;\n\ninterface IERC5267 {\n    /**\n     * @dev MAY be emitted to signal that the domain could have changed.\n     */\n    event EIP712DomainChanged();\n\n    /**\n     * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712\n     * signature.\n     */\n    function eip712Domain()\n        external\n        view\n        returns (\n            bytes1 fields,\n            string memory name,\n            string memory version,\n            uint256 chainId,\n            address verifyingContract,\n            bytes32 salt,\n            uint256[] memory extensions\n        );\n}\n"},{"file_path":"@openzeppelin/contracts/interfaces/draft-IERC6093.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard ERC20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 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 ERC721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 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 EIP-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 ERC1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 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.0.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\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.0.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 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/extensions/IERC20Permit.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n *     doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n *     token.safeTransferFrom(msg.sender, address(this), value);\n *     ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     *\n     * CAUTION: See Security Considerations above.\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC20Permit} from \"../extensions/IERC20Permit.sol\";\nimport {Address} from \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 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    using Address for address;\n\n    /**\n     * @dev An operation with an ERC20 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 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    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    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    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 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    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data);\n        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {\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 silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Address.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev The ETH balance of the account is not enough to perform the operation.\n     */\n    error AddressInsufficientBalance(address account);\n\n    /**\n     * @dev There's no code at `target` (it is not a contract).\n     */\n    error AddressEmptyCode(address target);\n\n    /**\n     * @dev A call to an address target failed. The target may have reverted.\n     */\n    error FailedInnerCall();\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        if (address(this).balance < amount) {\n            revert AddressInsufficientBalance(address(this));\n        }\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        if (!success) {\n            revert FailedInnerCall();\n        }\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason or custom error, it is bubbled\n     * up by this function (like regular Solidity function calls). However, if\n     * the call reverted with no returned reason, this function reverts with a\n     * {FailedInnerCall} error.\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        if (address(this).balance < value) {\n            revert AddressInsufficientBalance(address(this));\n        }\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an\n     * unsuccessful call.\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata\n    ) internal view returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            // only check if target is a contract if the call was successful and the return data is empty\n            // otherwise we already know that it was a contract\n            if (returndata.length == 0 && target.code.length == 0) {\n                revert AddressEmptyCode(target);\n            }\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n     * revert reason or with a default {FailedInnerCall} error.\n     */\n    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.\n     */\n    function _revert(bytes memory returndata) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert FailedInnerCall();\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Strings.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)\n\npragma solidity ^0.8.20;\n\nimport {Math} from \"./math/Math.sol\";\nimport {SignedMath} from \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant HEX_DIGITS = \"0123456789abcdef\";\n    uint8 private constant ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev The `value` string doesn't fit in the specified `length`.\n     */\n    error StringsInsufficientHexLength(uint256 value, uint256 length);\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\n     */\n    function toStringSigned(int256 value) internal pure returns (string memory) {\n        return string.concat(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value)));\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        uint256 localValue = value;\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = HEX_DIGITS[localValue & 0xf];\n            localValue >>= 4;\n        }\n        if (localValue != 0) {\n            revert StringsInsufficientHexLength(value, length);\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal\n     * representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);\n    }\n\n    /**\n     * @dev Returns true if the two strings are equal.\n     */\n    function equal(string memory a, string memory b) internal pure returns (bool) {\n        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/cryptography/ECDSA.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n    enum RecoverError {\n        NoError,\n        InvalidSignature,\n        InvalidSignatureLength,\n        InvalidSignatureS\n    }\n\n    /**\n     * @dev The signature derives the `address(0)`.\n     */\n    error ECDSAInvalidSignature();\n\n    /**\n     * @dev The signature has an invalid length.\n     */\n    error ECDSAInvalidSignatureLength(uint256 length);\n\n    /**\n     * @dev The signature has an S value that is in the upper half order.\n     */\n    error ECDSAInvalidSignatureS(bytes32 s);\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not\n     * return address(0) without also returning an error description. Errors are documented using an enum (error type)\n     * and a bytes32 providing additional information about the error.\n     *\n     * If no error is returned, then the address can be used for verification purposes.\n     *\n     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.\n     *\n     * Documentation for signature generation:\n     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n     */\n    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) {\n        if (signature.length == 65) {\n            bytes32 r;\n            bytes32 s;\n            uint8 v;\n            // ecrecover takes the signature parameters, and the only way to get them\n            // currently is to use assembly.\n            /// @solidity memory-safe-assembly\n            assembly {\n                r := mload(add(signature, 0x20))\n                s := mload(add(signature, 0x40))\n                v := byte(0, mload(add(signature, 0x60)))\n            }\n            return tryRecover(hash, v, r, s);\n        } else {\n            return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));\n        }\n    }\n\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature`. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.\n     */\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);\n        _throwError(error, errorArg);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n     *\n     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n     */\n    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) {\n        unchecked {\n            bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n            // We do not check for an overflow here since the shift operation results in 0 or 1.\n            uint8 v = uint8((uint256(vs) >> 255) + 27);\n            return tryRecover(hash, v, r, s);\n        }\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n     */\n    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);\n        _throwError(error, errorArg);\n        return recovered;\n    }\n\n    /**\n     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     */\n    function tryRecover(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (address, RecoverError, bytes32) {\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n        //\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n        // these malleable signatures as well.\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n            return (address(0), RecoverError.InvalidSignatureS, s);\n        }\n\n        // If the signature is valid (and not malleable), return the signer address\n        address signer = ecrecover(hash, v, r, s);\n        if (signer == address(0)) {\n            return (address(0), RecoverError.InvalidSignature, bytes32(0));\n        }\n\n        return (signer, RecoverError.NoError, bytes32(0));\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `v`,\n     * `r` and `s` signature fields separately.\n     */\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);\n        _throwError(error, errorArg);\n        return recovered;\n    }\n\n    /**\n     * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.\n     */\n    function _throwError(RecoverError error, bytes32 errorArg) private pure {\n        if (error == RecoverError.NoError) {\n            return; // no error: do nothing\n        } else if (error == RecoverError.InvalidSignature) {\n            revert ECDSAInvalidSignature();\n        } else if (error == RecoverError.InvalidSignatureLength) {\n            revert ECDSAInvalidSignatureLength(uint256(errorArg));\n        } else if (error == RecoverError.InvalidSignatureS) {\n            revert ECDSAInvalidSignatureS(errorArg);\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol)\n\npragma solidity ^0.8.20;\n\nimport {Strings} from \"../Strings.sol\";\n\n/**\n * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.\n *\n * The library provides methods for generating a hash of a message that conforms to the\n * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]\n * specifications.\n */\nlibrary MessageHashUtils {\n    /**\n     * @dev Returns the keccak256 digest of an EIP-191 signed data with version\n     * `0x45` (`personal_sign` messages).\n     *\n     * The digest is calculated by prefixing a bytes32 `messageHash` with\n     * `\"\\x19Ethereum Signed Message:\\n32\"` and hashing the result. It corresponds with the\n     * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.\n     *\n     * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with\n     * keccak256, although any bytes32 value can be safely used because the final digest will\n     * be re-hashed.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\") // 32 is the bytes-length of messageHash\n            mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix\n            digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)\n        }\n    }\n\n    /**\n     * @dev Returns the keccak256 digest of an EIP-191 signed data with version\n     * `0x45` (`personal_sign` messages).\n     *\n     * The digest is calculated by prefixing an arbitrary `message` with\n     * `\"\\x19Ethereum Signed Message:\\n\" + len(message)` and hashing the result. It corresponds with the\n     * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {\n        return\n            keccak256(bytes.concat(\"\\x19Ethereum Signed Message:\\n\", bytes(Strings.toString(message.length)), message));\n    }\n\n    /**\n     * @dev Returns the keccak256 digest of an EIP-191 signed data with version\n     * `0x00` (data with intended validator).\n     *\n     * The digest is calculated by prefixing an arbitrary `data` with `\"\\x19\\x00\"` and the intended\n     * `validator` address. Then hashing the result.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(hex\"19_00\", validator, data));\n    }\n\n    /**\n     * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`).\n     *\n     * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with\n     * `\\x19\\x01` and hashing the result. It corresponds to the hash signed by the\n     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.\n     *\n     * See {ECDSA-recover}.\n     */\n    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let ptr := mload(0x40)\n            mstore(ptr, hex\"19_01\")\n            mstore(add(ptr, 0x02), domainSeparator)\n            mstore(add(ptr, 0x22), structHash)\n            digest := keccak256(ptr, 0x42)\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/introspection/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\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[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},{"file_path":"@openzeppelin/contracts/utils/math/Math.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    /**\n     * @dev Muldiv operation overflow.\n     */\n    error MathOverflowedMulDiv();\n\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            uint256 c = a + b;\n            if (c < a) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b > a) return (false, 0);\n            return (true, a - b);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n            // benefit is lost if 'b' is also tested.\n            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n            if (a == 0) return (true, 0);\n            uint256 c = a * b;\n            if (c / a != b) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a / b);\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a % b);\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            return a / b;\n        }\n\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n     * denominator == 0.\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0 = x * y; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            if (denominator <= prod1) {\n                revert MathOverflowedMulDiv();\n            }\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n            // works in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n     * towards zero.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/math/SignedMath.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n    /**\n     * @dev Returns the largest of two signed numbers.\n     */\n    function max(int256 a, int256 b) internal pure returns (int256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two signed numbers.\n     */\n    function min(int256 a, int256 b) internal pure returns (int256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two signed numbers without overflow.\n     * The result is rounded towards zero.\n     */\n    function average(int256 a, int256 b) internal pure returns (int256) {\n        // Formula from the book \"Hacker's Delight\"\n        int256 x = (a & b) + ((a ^ b) >> 1);\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\n    }\n\n    /**\n     * @dev Returns the absolute unsigned value of a signed value.\n     */\n    function abs(int256 n) internal pure returns (uint256) {\n        unchecked {\n            // must be unchecked in order to support `n = type(int256).min`\n            return uint256(n >= 0 ? n : -n);\n        }\n    }\n}\n"},{"file_path":"contracts/interfaces/IYUSD.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\";\n\ninterface IYUSD is IERC20Permit, IERC20Metadata {\n  function mint(address account, uint256 value) external;\n\n  function mint(address account, uint256 value, bytes calldata data) external;\n\n  function burn(uint256 _amount) external;\n\n  function burnFrom(address account, uint256 amount) external;\n\n  function setMinter(address newMinter) external;\n}\n\ninterface IYUSDErrors {\n  error ZeroAddress();\n  error OnlyMinter();\n  error Blacklisted(address _user);\n}\n"},{"file_path":"contracts/sYUSDSilo.sol","source_code":"// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.26;\n\n/* solhint-disable var-name-mixedcase  */\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @title YUSDSilo\n * @notice The Silo allows to store YUSD during the stake cooldown process.\n */\ncontract sYUSDSilo {\n  address immutable _STAKING_VAULT;\n  IERC20 immutable _YUSD;\n\n  error OnlyStakingVault();\n\n  constructor(address stakingVault, address yusd) {\n    _STAKING_VAULT = stakingVault;\n    _YUSD = IERC20(yusd);\n  }\n\n  modifier onlyStakingVault() {\n    if (msg.sender != _STAKING_VAULT) revert OnlyStakingVault();\n    _;\n  }\n\n  function withdraw(address to, uint256 amount) external onlyStakingVault {\n    _YUSD.transfer(to, amount);\n  }\n\n  function getYUSD() external view returns (address) {\n    return address(_YUSD);\n  }\n\n  function getStakingVault() external view returns (address) {\n    return _STAKING_VAULT;\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":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"CooldownNotEnded","type":"error"},{"inputs":[],"name":"DurationExceedsMax","type":"error"},{"inputs":[],"name":"DurationNotChanged","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"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":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ERC2612ExpiredSignature","type":"error"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC2612InvalidSigner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"ERC4626ExceededMaxDeposit","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"ERC4626ExceededMaxMint","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"ERC4626ExceededMaxRedeem","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"ERC4626ExceededMaxWithdraw","type":"error"},{"inputs":[],"name":"ExpectedCooldownOff","type":"error"},{"inputs":[],"name":"ExpectedCooldownOn","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"FeeNotChanged","type":"error"},{"inputs":[{"internalType":"uint256","name":"requested","type":"uint256"},{"internalType":"uint256","name":"available","type":"uint256"}],"name":"InsufficientShares","type":"error"},{"inputs":[],"name":"InsuranceFundNotChanged","type":"error"},{"inputs":[],"name":"InsuranceFundNotSet","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidAccountNonce","type":"error"},{"inputs":[],"name":"InvalidFee","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"MathOverflowedMulDiv","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"string","name":"paramName","type":"string"}],"name":"ZeroAddress","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":false,"internalType":"uint24","name":"previousDuration","type":"uint24"},{"indexed":false,"internalType":"uint24","name":"newDuration","type":"uint24"}],"name":"CooldownDurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cooldownEnd","type":"uint256"}],"name":"CooldownStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"InstantUnstaking","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"previousFee","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"newFee","type":"uint16"}],"name":"InstantUnstakingFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousFund","type":"address"},{"indexed":false,"internalType":"address","name":"newFund","type":"address"}],"name":"InsuranceFundUpdated","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":"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":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"Unstaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Withdraw","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":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INSTANT_UNSTAKING_FEE","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INSURANCE_FUND","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_COOLDOWN_DURATION","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","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":[],"name":"asset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"cooldownAssets","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cooldownDuration","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"cooldownShares","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"cooldowns","outputs":[{"internalType":"uint104","name":"cooldownEnd","type":"uint104"},{"internalType":"uint152","name":"underlyingAmount","type":"uint152"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","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":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserCooldownStatus","outputs":[{"internalType":"uint256","name":"cooldownEnd","type":"uint256"},{"internalType":"uint256","name":"underlyingAmount","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":"address","name":"_yusd","type":"address"},{"internalType":"address","name":"admin","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"initialFee","type":"uint16"},{"internalType":"address","name":"initialInsuranceFund","type":"address"}],"name":"initializeV2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"rescueTokens","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":"uint24","name":"newDuration","type":"uint24"}],"name":"setCooldownDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"newFee","type":"uint16"}],"name":"setInstantUnstakingFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newInsuranceFund","type":"address"}],"name":"setInsuranceFund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"silo","outputs":[{"internalType":"contract sYUSDSilo","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":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[{"internalType":"address","name":"receiver","type":"address"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":true,"constructor_args":null}