{"file_path":"contracts/IdleCDOEpochVariant.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.10;\n\nimport {IdleCDOCreditVault} from \"./IdleCDOCreditVault.sol\";\nimport {IKeyring} from \"./interfaces/keyring/IKeyring.sol\";\nimport {IProgrammableBorrower} from \"./interfaces/IProgrammableBorrower.sol\";\nimport {IdleCreditVault} from \"./strategies/idle/IdleCreditVault.sol\";\nimport {IERC20Detailed} from \"./interfaces/IERC20Detailed.sol\";\nimport {SafeERC20Upgradeable} from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\nerror NotAllowed();\n\n/// @title IdleCDO variant that supports epochs. \n/// @dev When epoch is running no deposits or withdrawals are allowed. When epoch ends \n/// lenders can request withdrawals, that will be fullfilled by the end of the next epoch.\n/// If the apr for the new epoch is lower than the last one, lenders can request 'instant' \n/// withdrawals that will be fullfilled when the epoch starts and after instantWithdrawDelay (3 days).\n/// Funds for instant and normal withdrawals are sent to the strategy contract (IdleCreditVault)\n/// @custom:oz-upgrades-unsafe-allow missing-initializer\ncontract IdleCDOEpochVariant is IdleCDOCreditVault {\n  using SafeERC20Upgradeable for IERC20Detailed;\n\n  /// @notice flag to check if epoch is running\n  bool public isEpochRunning;\n  /// @notice flag to allow AA withdraw requests\n  bool public allowAAWithdrawRequest;\n  /// @notice flag to allow BB withdraw requests\n  bool public allowBBWithdrawRequest;\n  /// @notice duration of the epoch\n  uint256 public epochDuration;\n  /// @notice delay to allow instant withdraw requests after next epoch starts\n  uint256 public instantWithdrawDelay;\n  /// @notice expected interest for the current epoch\n  uint256 public expectedEpochInterest;\n  /// @notice end date of the current epoch\n  uint256 public epochEndDate;\n  /// @notice deadline to allow instant withdraw requests\n  uint256 public instantWithdrawDeadline;\n  /// @notice apr of the last epoch, unscaled\n  uint256 public lastEpochApr;\n  /// @notice min apr change to trigger instant withdraw\n  uint256 public instantWithdrawAprDelta;\n  /// @notice fees from pending withdraw request for the curr epoch\n  uint256 public pendingWithdrawFees;\n  /// @notice net underlyings gained last epoch\n  uint256 public lastEpochInterest;\n  /// @notice flag to allow instant withdraws\n  bool public allowInstantWithdraw;\n  /// @notice flag to completely disable instant withdraw\n  bool public disableInstantWithdraw;\n  /// @notice flag to check if borrower defaulted\n  bool public defaulted;\n  /// @notice Keyring wallet checker address\n  address public keyring;\n  /// @notice keyring policyId\n  uint256 public keyringPolicyId;\n  /// @notice time between 2 epochs, can be set to 0 to start the next epoch without waiting a specified time\n  uint256 public bufferPeriod;\n  /// @dev Deprecated storage slot. Do not remove: kept to preserve the upgradeable storage layout.\n  bool internal keyringAllowWithdraw;\n  /// @notice amount of over/under performance that withdrawal requests will cause\n  int256 internal interestForOverUnderPerformance;\n  /// @notice flag to disable deposits during an epoch\n  bool public isDepositDuringEpochDisabled;\n  /// @notice flag to mint interest as strategy tokens without moving underlyings\n  bool public isInterestMinted;\n\n  event AccrueInterest(uint256 interest, uint256 fees);\n  event BorrowerDefault(uint256 funds);\n\n  function _additionalInit() internal virtual override {\n    // Set the contract with monotranche as default (can still be changed if needed)\n    // losses are split according to tvl, senior has no priority\n    lossToleranceBps = FULL_ALLOC;\n    // all yield to senior\n    isAYSActive = false;\n\n    // set epoch params\n    epochDuration = 30 days;\n    bufferPeriod = 5 days;\n    // we set epochEndDate to avoid issues with the first epoch, so we set\n    // it to current time minus bufferPeriod so that the first epoch can start right away\n    epochEndDate = block.timestamp - 5 days;\n\n    // allow requests for withdrawals\n    allowAAWithdrawRequest = true;\n    allowBBWithdrawRequest = true;\n\n    // default no instant withdraw allowed\n    disableInstantWithdraw = true;\n\n    // by default deposits during an epoch are disabled\n    isDepositDuringEpochDisabled = true;\n\n    // scale the apr to include the buffer period\n    _setScaledApr(_getStrategyApr());\n  }\n\n  /// @notice Check if msg sender is owner or manager\n  function _checkOnlyOwnerOrManager() internal view {\n    _checkNotAllowed(msg.sender != owner() && msg.sender != IdleCreditVault(strategy).manager());\n  }\n\n  /// @notice Revert if condition is true\n  /// @param _revertCondition condition to check\n  function _checkNotAllowed(bool _revertCondition) internal pure {\n    if (_revertCondition) revert NotAllowed();\n  }\n\n  /// @notice Ensure programmable borrowers are only used with minted-interest accounting.\n  /// @dev Programmable borrower stop flows assume the CDO fronts interest by minting strategy tokens.\n  function _checkProgrammableBorrowerMode() internal view {\n    _checkNotAllowed(isProgrammableBorrower && !isInterestMinted);\n  }\n\n  ///\n  /// Only owner or manager methods \n  ///\n\n  /// @notice update epoch duration\n  /// @dev IMPORTANT: bufferPeriod should not be changed once set otherwise interest calculations will be wrong\n  /// @param _epochDuration duration in seconds\n  /// @param _bufferPeriod time between 2 epochs\n  function setEpochParams(uint256 _epochDuration, uint256 _bufferPeriod) public {\n    _checkOnlyOwnerOrManager();\n    // cannot set epoch params if epoch is running\n    // cannot set epochDuration to 0 as it's reserved for closing the pool\n    // and cannot set epochDuration if previously was set to 0 as borrower repaid all funds\n    _checkNotAllowed(isEpochRunning || _epochDuration == 0 || epochDuration == 0);\n    epochDuration = _epochDuration;\n    bufferPeriod = _bufferPeriod;\n  }\n\n  /// @notice update instant withdraw params\n  /// @param _delay delay in seconds\n  /// @param _aprDelta min apr delta to trigger instant withdraw\n  /// @param _disable flag to disable instant withdraw\n  function setInstantWithdrawParams(uint256 _delay, uint256 _aprDelta, bool _disable) external {\n    _checkOnlyOwnerOrManager();\n    _checkNotAllowed(isEpochRunning);\n    instantWithdrawDelay = _delay;\n    instantWithdrawAprDelta = _aprDelta;\n    disableInstantWithdraw = _disable;\n  }\n\n  /// @notice update keyring address\n  /// @param _keyring address of the keyring contract\n  /// @param _keyringPolicyId policyId to check for wallet\n  function setKeyringParams(address _keyring, uint256 _keyringPolicyId) external {\n    _checkOnlyOwnerOrManager();\n    keyring = _keyring;\n    keyringPolicyId = _keyringPolicyId;\n  }\n\n  /// @notice set flag to disable deposits during an epoch\n  /// @param _isDisabled true to disable deposits during an epoch\n  function setIsDepositDuringEpochDisabled(bool _isDisabled) external {\n    _checkOnlyOwnerOrManager();\n    isDepositDuringEpochDisabled = _isDisabled;\n  }\n\n  /// @notice Skim raw donated underlyings before forcing accounting.\n  /// @dev Prevents unsolicited transfers from being crystallized as tranche gains by manual accounting.\n  function updateAccounting() external override {\n    _checkOnlyOwnerOrGuardian();\n    _skimDonatedAssets();\n    _forceUpdateAccounting();\n  }\n\n  /// @notice set flag to mint interest as strategy tokens without moving underlyings\n  /// @dev Programmable borrowers always require minted-interest accounting.\n  /// @param _isMinted true to mint interest instead of transferring underlyings\n  function setIsInterestMinted(bool _isMinted) external {\n    _checkOnlyOwner();\n    _checkNotAllowed(!_isMinted && isProgrammableBorrower);\n    isInterestMinted = _isMinted;\n  }\n\n  /// @notice Set whether the current strategy borrower should be treated as programmable.\n  /// @dev This is configured explicitly instead of inferring from code size so contract borrowers\n  /// such as Safe wallets are not misclassified. The flag cannot be changed while an epoch is live.\n  /// @param _isProgrammable true to enable programmable-borrower hooks and accounting\n  function setIsProgrammableBorrower(bool _isProgrammable) external {\n    _checkOnlyOwner();\n    _checkNotAllowed(isEpochRunning);\n    isProgrammableBorrower = _isProgrammable;\n  }\n\n  /// @notice Start the epoch. No deposits or withdrawals are allowed after this.\n  /// @dev We calculate the total funds that the borrower should return at the end of the epoch\n  /// ie interests + fees from normal withdraw requests. We send to the borrower underlyings amounts ie interests + \n  /// new deposits - instant withdraw requests if any. If funds are not enough to satisfy all requests\n  /// then borrower should return the difference before instantWithdrawDeadline. After epoch start there\n  /// should be no underlyings in this contract\n  function startEpoch() external {\n    _checkOnlyOwnerOrManager();\n\n    // Check that buffer period passed (and epoch is not running as epochEndDate is set)\n    // and that the pool is not closed (ie epochDuration == 0)\n    uint256 _epochDuration = epochDuration; \n    _checkNotAllowed(block.timestamp < (epochEndDate + bufferPeriod) || _epochDuration == 0);\n    _checkProgrammableBorrowerMode();\n    // Remove raw donated underlyings before calculating epoch interest or borrower transfer amounts.\n    _skimDonatedAssets();\n\n    isEpochRunning = true;\n    // prevent deposits\n    _pause();\n\n    // prevent withdrawals requests\n    allowAAWithdrawRequest = false;\n    allowBBWithdrawRequest = false;\n\n    IdleCreditVault _strategy = IdleCreditVault(strategy);\n\n    // calculate expected interest \n    // NOTE: all withdrawal requests, burn tranche tokens and decrease getContractValue,\n    // this can be done only prior to the start of the epoch so getContractValue() is the total amount net\n    // of all withdrawal requests. We add the fee that we should get for normal pending withdraws\n    // we also add/remove the over/under performance cause by withdraw requests\n    expectedEpochInterest = uint256(int256(_calcInterest(getContractValue())) + int256(pendingWithdrawFees) + interestForOverUnderPerformance);\n    interestForOverUnderPerformance = 0;\n\n    // set expected epoch end date\n    epochEndDate = block.timestamp + _epochDuration;\n    // set instant withdraw deadline\n    instantWithdrawDeadline = block.timestamp + instantWithdrawDelay;\n\n    // transfer in this contract funds from interest payment (if any) and buffer deposits sent to the strategy\n    uint256 _totEpochDeposits = _strategy.totEpochDeposits();\n    // If interest is minted we do not transfer interest to the strategy\n    uint256 _toSend = isInterestMinted ? _totEpochDeposits : lastEpochInterest + _totEpochDeposits;\n    if (_toSend != 0) {\n      _strategy.sendInterestAndDeposits(_toSend);\n    }\n\n    // we should first check if there are *instant* redeem requests pending \n    // and if yes we should send as much underlyings as possible to the IdleCreditVault contract\n    // if there is any surplus then we send those to the borrower\n    uint256 pendingInstant = _pendingInstant();\n    uint256 totUnderlyings = _contractTokenBalance(token);\n    uint256 _pendingWithdraws = _strategy.pendingWithdraws();\n\n    // if there are more requests than the current underlyings we simply send all underlyings\n    // to the IdleCreditVault contract\n    if (pendingInstant > totUnderlyings) {\n      // transfer funds to strategy\n      _strategy.collectInstantWithdrawFunds(totUnderlyings);\n      // if borrower is programmable, notify epoch start even if no funds were sent\n      _startEpochProgrammableBorrower(_pendingWithdraws);\n      return;\n    }\n    // otherwise we send the amount needed to satisfy the requests to the strategy \n    _strategy.collectInstantWithdrawFunds(pendingInstant);\n    // allow instant withdraws right away without waiting for the deadline\n    allowInstantWithdraw = true;\n    // and transfer the surplus to the borrower\n    uint256 _toBorrower = totUnderlyings - pendingInstant;\n    try this.sendFundsToBorrower(_toBorrower) {\n      // funds transferred correctly\n      _startEpochProgrammableBorrower(_pendingWithdraws);\n    } catch {\n      // The borrower did not receive the funds, so keep the strategy-token backing in the strategy.\n      _transferUnderlyings(address(_strategy), _toBorrower);\n      _handleBorrowerDefault(_toBorrower);\n    }\n  }\n\n  /// @notice workaround to have safeTransfer to borrower as external and use it in a try/catch block\n  /// @param _amount Amount of underlyings to transfer\n  function sendFundsToBorrower(uint256 _amount) external {\n    _checkNotAllowed(msg.sender != address(this));\n    _transferUnderlyings(_borrower(), _amount);\n  }\n\n  /// @notice Stop epoch, accrue interest to the vault and get funds to fullfill normal\n  /// (ie non-instant) withdraw requests from the prev epoch.\n  /// @param _newApr New apr to set for the next epoch\n  /// @param _interest Interest gained in the epoch. This will overwrite the expected interest\n  /// must be 0 if there is no need to overwrite the expected interest and if > 0 then it should\n  /// be greater than the pending withdraw fees and newApr must be 0. If `_interest` is 1 then\n  /// it is interpreted as a special case where we request everything back from the borrower.\n  /// Programmable borrowers only support `_interest` values `0` and `1`.\n  /// @dev Only owner or manager can call this function. Borrower MUST approve this contract\n  function stopEpoch(uint256 _newApr, uint256 _interest) public {\n    _beforeStopEpoch();\n    _checkOnlyOwnerOrManager();\n    _checkProgrammableBorrowerMode();\n\n    IdleCreditVault _strategy = IdleCreditVault(strategy);\n    uint256 _pendingWithdrawFees = pendingWithdrawFees;\n\n    _checkNotAllowed(\n      // Check that epoch is running\n      !isEpochRunning || \n      // Check that end date is passed\n      block.timestamp < epochEndDate || \n      // Check that there are no pending instant withdraws, ie `getInstantWithdrawFunds` was called\n      // before closing the epoch\n      _pendingInstant() != 0 ||\n      // Check that overridden interest, if passed (ie > 1), is greater than pending withdraw fees and the apr is 0 \n      // otherwise withdrawal requests may not be fullfilled as they consider also the interest gained in the next epoch \n      (_interest > 1 && (_interest < _pendingWithdrawFees || _newApr != 0))\n    );\n\n    // we check if there are donated assets to the pool and transfer them to the feeReceiver if any\n    _skimDonatedAssets();\n\n    bool _isRequestingAllFunds = _interest == 1;\n    _interest = _resolveStopEpochInterest(_interest);\n\n    // Base interest for stopEpoch: explicit override (>1) or precomputed expected epoch interest.\n    uint256 _expectedInterest;\n    // Strategy finalizes APR0 bucket state and returns adjusted stopEpoch values.\n    (_expectedInterest, _pendingWithdrawFees) = _strategy.prepareStopEpochWithApr0(_interest);\n    // Pending withdraws may be increased during APR0 settlement, so read after prepareStopEpochWithApr0.\n    uint256 _pendingWithdraws = _strategy.pendingWithdraws();\n\n    uint256 _totBorrowed;\n    // special case where we get everything back from the borrower\n    if (_isRequestingAllFunds) {\n      // do not consider underlyings already in this contract\n      _totBorrowed = getContractValue() - _contractTokenBalance(token);\n      _expectedInterest += _totBorrowed;\n    }\n    uint256 _grossInterest = _isRequestingAllFunds ? _expectedInterest - _totBorrowed : _expectedInterest;\n    bool _mintInterest = isInterestMinted && !_isRequestingAllFunds;\n    // In minted mode IdleCDO only needs cash for withdraw requests, not for epoch interest itself.\n    uint256 _amountToPullFromBorrower = _mintInterest ? 0 : _expectedInterest;\n    if (_mintInterest && _interest > 1) {\n      uint256 _maxApr = _strategy.maxApr();\n      _checkNotAllowed(_maxApr != 0 && _grossInterest > _calcInterestWithApr(getContractValue(), _maxApr) + _pendingWithdrawFees);\n    }\n\n    uint256 _amountRequired = _amountToPullFromBorrower + _pendingWithdraws;\n    if (isProgrammableBorrower) {\n      // Ask the programmable borrower to recall ERC4626 liquidity before IdleCDO pulls funds.\n      // Hook reverts bubble so transient ERC4626 liquidity failures can be retried.\n      if (!IProgrammableBorrower(_borrower()).onStopEpoch(_amountRequired, _isRequestingAllFunds)) {\n        allowInstantWithdraw = true;\n        _handleBorrowerDefault(_amountRequired);\n        return;\n      }\n    }\n\n    // Checkpoint management fees before borrower funds are pulled in so the elapsed-period\n    // accrual applies only to the pre-stop live NAV, not to newly received epoch interest.\n    _accrueManagementFee();\n\n    // accrue interest to idleCDO, this will increase tranche prices.\n    // Send also tot withdraw requests amount to the IdleCreditVault contract\n    try this.getFundsFromBorrower(_amountToPullFromBorrower, _pendingWithdraws, 0) {\n      // transfer in strategy and decrease pendingWithdraws\n      if (_pendingWithdraws != 0) {\n        _strategy.collectWithdrawFunds(_pendingWithdraws);\n      }\n      // Only settle borrower interest when CDO is fronting it (minted mode, not closing pool).\n      // When requesting all funds (_interest == 1) the CDO pulls cash directly, no fronting.\n      if (_mintInterest && isProgrammableBorrower) {\n        IProgrammableBorrower(_borrower()).settleBorrowerInterest();\n      }\n      // Split pending withdraw fees before update accounting\n      // NOTE: Fees are sent with 2 different transfer calls, here and after updateAccounting, to avoid complicated calculations\n      if (!_mintInterest) {\n        _transferFeeUnderlyings(_pendingWithdrawFees);\n      }\n\n      if (_isRequestingAllFunds) {\n        // we already have strategyTokens equal to _totBorrowed in this contract\n        // so we transfer _totBorrowed to the strategy to avoid double counting for getContractValue\n        _transferUnderlyings(address(_strategy), _totBorrowed);\n      }\n\n      if (_mintInterest) {\n        // if interest is not transferred we mint strategy tokens equal to the full epoch interest\n        if (_grossInterest != 0) _strategy.mintStrategyTokens(_grossInterest);\n        // and increase unclaimedFees by pending withdraw fees before _updateAccounting\n        unclaimedFees += _pendingWithdrawFees;\n      }\n\n      // update tranche prices and unclaimed fees\n      _updateAccounting();\n\n      // transfer fees\n      uint256 _fees = unclaimedFees;\n      if (_mintInterest) {\n        // If interest is minted then we mint new shares for fee receivers instead of transferring underlyings\n        if (_fees != 0) {\n          uint256 feeReceiverAmount = _feeReceiverAmount(_fees);\n          if (feeReceiverAmount != 0) {\n            _mintSharesAtCurrPrice(feeReceiverAmount, feeReceiver, AATranche);\n          }\n          _mintSharesAtCurrPrice(_fees - feeReceiverAmount, owner(), AATranche);\n          _updateSplitRatio(_getAARatio(true));\n        }\n      } else {\n        // Cash-funded fees can only use gross interest not already owed to pending withdrawals.\n        uint256 _availableForFees = _grossInterest > _pendingWithdrawFees ? _grossInterest - _pendingWithdrawFees : 0;\n        if (_fees > _availableForFees) {\n          _fees = _availableForFees;\n        }\n        _transferFeeUnderlyings(_fees);\n      }\n      // Any fee that cannot be paid in cash remains accrued and continues reducing NAV.\n      unclaimedFees -= _fees;\n\n      uint256 _totalFees = _fees + (_mintInterest ? 0 : _pendingWithdrawFees);\n      // save net gain (this does not include interest gained for pending withdrawals)\n      uint256 netInterest = _grossInterest > _totalFees ? _grossInterest - _totalFees : 0;\n      lastEpochInterest = netInterest;\n      // mint strategyTokens equal to interest and send underlying to strategy to avoid double counting for NAV\n      _strategy.deposit(_mintInterest ? 0 : netInterest);\n\n      // save last apr, unscaled\n      lastEpochApr = _strategy.unscaledApr();\n      // set apr for next epoch\n      _setScaledApr(_newApr);\n\n      // stop epoch\n      isEpochRunning = false;\n      expectedEpochInterest = 0;\n      pendingWithdrawFees = 0;\n\n      // allow deposits\n      _unpause();\n      // allow withdrawals requests\n      allowAAWithdrawRequest = true;\n      allowBBWithdrawRequest = true;\n      // block instant withdraws claims as these can be done only after the deadline\n      // or only if borrower is repaying all funds\n      allowInstantWithdraw = _isRequestingAllFunds;\n\n      if (_isRequestingAllFunds) {\n        // user will request only normal withdraw and can claim right after\n        disableInstantWithdraw = true;\n        epochDuration = 0;\n        epochEndDate = 0;\n      }\n\n      emit AccrueInterest(_expectedInterest - _totBorrowed, _totalFees);\n    } catch {\n      // if borrower defaults, prev instant withdraw requests can still be withdrawn\n      // as were already fullfilled prior to the default (all funds already sent to the strategy)\n      allowInstantWithdraw = true;\n      _handleBorrowerDefault(_expectedInterest + _pendingWithdraws);\n    }\n  }\n\n  /// @notice Stop epoch and set new duration\n  /// @dev see stopEpoch and setEpochParams for more details, bufferPeriod is not modified\n  /// Loss accounting policy for `_lossAmount`:\n  /// - loss is applied only after `stopEpoch` finishes funding normal withdraw receipts\n  /// - as a consequence, already-minted pending withdraw receipts are not haircut by `_lossAmount`\n  /// - if `stopEpoch` defaults (`defaulted = true`), the post-stop loss burn is skipped\n  /// @param _newApr New apr to set for the next epoch\n  /// @param _interest Interest gained in the epoch\n  /// @param _duration New epoch duration\n  /// @param _lossAmount Amount of strategy tokens to burn as realized loss\n  function stopEpochWithDuration(uint256 _newApr, uint256 _interest, uint256 _duration, uint256 _lossAmount) public {\n    // stop epoch checks that msg.sender is allowed\n    stopEpoch(_newApr, _interest);\n    if (_lossAmount != 0 && !defaulted) {\n      IdleCreditVault(strategy).burnStrategyTokens(_lossAmount);\n      // realize the loss right away and update stored tranche prices/NAV\n      _forceUpdateAccounting();\n    }\n    // buffer period is not changed\n    setEpochParams(_duration, bufferPeriod);\n\n    // scale the apr with the new durantion and buffer\n    _setScaledApr(_newApr);\n    _afterStopEpochWithDuration();\n  }\n\n  /// @notice internal function called in stop epoch before doing anything else\n  function _beforeStopEpoch() internal virtual {}\n\n  /// @notice internal function called in stop epoch with duration after doing anything else\n  function _afterStopEpochWithDuration() internal virtual {}\n\n  /// @notice Set the scaled apr for the next epoch\n  /// @param _newApr New apr to set for the next epoch\n  function _setScaledApr(uint256 _newApr) internal {\n    uint256 _duration = epochDuration;\n    IdleCreditVault(strategy).setAprs(\n      _newApr,\n      // The apr should be increased by an amount proportional to the buffer period in this\n      // way during a buffer period lenders will still get interest. Eg if epoch is 30 days and buffer\n      // is 5 days and the apr lenders should receive is 10% then _newApr should be 10% * 35/30 = 11.67%.\n      _duration == 0 ? _newApr : _newApr * (_duration + bufferPeriod) / _duration\n    );\n  }\n\n  /// @dev Get interest and funds for fullfill withdraw requests (normal and instant) from borrower,\n  /// method is external so it can be used in the try/catch blocks\n  /// @param _amount Amount of interest to transfer\n  /// @param _withdrawRequests Total withdraw requests\n  /// @param _instantWithdrawRequests Total instant withdraw requests\n  function getFundsFromBorrower(uint256 _amount, uint256 _withdrawRequests, uint256 _instantWithdrawRequests) external {\n    _checkNotAllowed(msg.sender != address(this));\n    _transferUnderlyingsFrom(_borrower(), address(this), _amount + _withdrawRequests + _instantWithdrawRequests);\n  }\n\n  /// @notice Get funds from borrower to fullfill instant withdraw requests\n  /// Manager should call this method after instantWithdrawDeadline (when epoch is running)\n  /// @dev Instant withdrawals are not supported when a programmable borrower is configured.\n  function getInstantWithdrawFunds() external {\n    _checkOnlyOwnerOrManager();\n    // Check that programmable mode is disabled, the epoch is running and the deadline passed.\n    _checkNotAllowed(isProgrammableBorrower || !isEpochRunning || block.timestamp < instantWithdrawDeadline);\n\n    IdleCreditVault _strategy = IdleCreditVault(strategy);\n    uint256 _instantWithdraws = _pendingInstant();\n    // transfer funds for instant withdraw to this contract\n    try this.getFundsFromBorrower(0, 0, _instantWithdraws) {\n      // transfer funds to IdleCreditVault and decrease pendingInstantWithdraws\n      if (_instantWithdraws != 0) {\n        _strategy.collectInstantWithdrawFunds(_instantWithdraws);\n      }\n      // allow instant withdraws\n      allowInstantWithdraw = true;\n    } catch {\n      _handleBorrowerDefault(_instantWithdraws);\n    }\n  }\n\n  /// @notice Handle borrower default\n  function _handleBorrowerDefault(uint256 funds) internal {\n    defaulted = true;\n\n    if (isProgrammableBorrower) {\n      IProgrammableBorrower(_borrower()).onDefault();\n    }\n\n    // deposits should be already prevented\n    if (!paused()) {\n      _pause();\n    }\n\n    // stop the current epoch\n    isEpochRunning = false;\n\n    // prevent withdrawals requests\n    allowAAWithdrawRequest = false;\n    allowBBWithdrawRequest = false;\n\n    emit BorrowerDefault(funds);\n  }\n\n  /// @notice Prevent deposits and redeems for all classes of tranches\n  function _emergencyShutdown(bool isAAWithdrawAllowed) internal override {\n    // prevent deposits\n    if (!paused()) {\n      _pause();\n    }\n    // allow only AA withdrawal requests when requested by parent loss handling\n    allowAAWithdrawRequest = isAAWithdrawAllowed;\n    allowBBWithdrawRequest = false;\n    // Allow deposits/withdraws (once selectively re-enabled, eg for AA holders)\n    // without checking for lending protocol default\n    skipDefaultCheck = true;\n  }\n\n  /// @notice allow deposits and redeems for all classes of tranches\n  /// @dev can be called by the owner only\n  function restoreOperations() external override {\n    _checkOnlyOwner();\n    // Check if the pool was defaulted\n    _checkNotAllowed(defaulted);\n    // restore deposits\n    if (paused()) {\n      _unpause();\n    }\n    // restore withdraws\n    allowAAWithdrawRequest = true;\n    allowBBWithdrawRequest = true;\n    // Allow deposits/withdraws but checks for lending protocol default\n    skipDefaultCheck = false;\n  }\n\n  /// \n  /// User methods\n  ///\n\n  /// @notice Deposit funds in the vault. Overrides the parent method and adds a check for wallet \n  function _deposit(uint256 _amount, address _tranche) internal override whenNotPaused returns (uint256) {\n    _checkNotAllowed(!isWalletAllowed(msg.sender));\n    // we check if there are donated assets to the pool and transfer them to the feeReceiver if any\n    _skimDonatedAssets();\n    // do the inherited deposit flow\n    return super._deposit(_amount, _tranche);\n  }\n\n  /// @notice Deposit during an active epoch with prorated interest\n  /// @param _amount Amount of underlyings\n  /// @param _tranche Tranche to deposit into\n  /// @return _minted Amount of tranche tokens minted\n  function depositDuringEpoch(uint256 _amount, address _tranche) external virtual returns (uint256 _minted) {\n    _checkNotAllowed(\n      isDepositDuringEpochDisabled ||\n      // programmable borrowers use APR=0 so mid-epoch deposits would dilute existing depositors\n      isProgrammableBorrower ||\n      // check if AYS is active as we don't support deposits during epoch in that case\n      isAYSActive ||\n      // check if epoch is still running even if not manually stopped yet\n      !isEpochRunning || block.timestamp >= epochEndDate ||\n      // check if _tranche is valid and if user is allowed\n      !(_tranche == AATranche || _tranche == BBTranche) || !isWalletAllowed(msg.sender)\n    );\n\n    if (_amount == 0) {\n      return _minted;\n    }\n\n    uint256 _trancheTotSupply = _trancheSupply(_tranche);\n    // Avoid pricing discontinuities for the first mid-epoch deposit in a tranche\n    _checkNotAllowed(_trancheTotSupply == 0);\n\n    _skimDonatedAssets();\n    // Check that limit is not exceeded after removing skimmable raw donations.\n    _guarded(_amount);\n    _updateAccounting();\n\n    // Get underlyings from user\n    _transferUnderlyingsFrom(msg.sender, address(this), _amount);\n\n    // interest for the remaining epoch plus the full buffer period\n    // NOTE: _calcInterest already gives full‑epoch + full‑buffer interest for the whole epoch\n    //   So when a user joins mid‑epoch, we take the fraction of that full‑period interest \n    //   that matches the time they actually remain plus the entire buffer\n    uint256 buffer = bufferPeriod;\n    uint256 remaining = epochEndDate - block.timestamp;\n    uint256 interest = _calcInterest(_amount) *\n      // the time the depositor actually participates (remaining epoch + full buffer)\n      (remaining + buffer) /\n      // the total time baked into the scaled APR (epoch + buffer).\n      (epochDuration + buffer);\n\n    uint256 expectedInt = expectedEpochInterest;\n    uint256 pendingFees = pendingWithdrawFees;\n    uint256 trancheExpected;\n    // existing holders' share of net expected interest for the epoch (pre-deposit)\n    // (exclude pendingWithdrawFees since they go to fee receivers, not tranche holders)\n    if (expectedInt > pendingFees) {\n      trancheExpected = _calcTrancheInterestShare(\n        _netGainAfterFees(expectedInt - pendingFees, _calculateManagementFee(lastNAVAA + lastNAVBB, remaining)),\n        _tranche\n      );\n    }\n    // interest this deposit will earn for the tranche over the remaining time (net of fees)\n    uint256 trancheInterest = _calcTrancheInterestShare(\n      _netGainAfterFees(interest, _calculateManagementFee(_amount, remaining)),\n      _tranche\n    );\n    // pre-deposit expected final NAV for existing holders.\n    // This won't ever be zero as we checked _trancheTotSupply and we seed initial NAV at tranche creation\n    uint256 expectedFinal = _lastSavedNAV(_tranche) + trancheExpected;\n\n    // mint at a discounted price so depositor gets principal + its prorated interest at epoch end\n    // A mid‑epoch depositor should get _amount + trancheInterest at epoch end.\n    // So they need minted = (amount + trancheInterest) / priceEnd.\n    // priceEnd = expectedFinal / _trancheTotSupply\n    // so minted = (amount + trancheInterest) * _trancheTotSupply / expectedFinal\n    _minted = (_amount + trancheInterest) * _trancheTotSupply / expectedFinal;\n    _mintShares(_tranche, msg.sender, _minted, _amount);\n\n    // update expected epoch interest\n    expectedEpochInterest += interest;\n    // mint strategy tokens to this contract\n    IdleCreditVault(strategy).mintStrategyTokens(_amount);\n    // transfer underlyings to the borrower\n    _transferUnderlyings(_borrower(), _amount);\n  }\n\n  /// @notice Request a withdraw from the vault\n  /// @param _amount Amount of tranche tokens \n  /// @param _tranche Tranche to withdraw from\n  /// @return _underlyings Amount of underlyings requested\n  function requestWithdraw(uint256 _amount, address _tranche) external returns (uint256 _underlyings) {\n    // check if _tranche is valid and if withdraws for that tranche are allowed and if user is allowed\n    _checkNotAllowed((_tranche != AATranche && _tranche != BBTranche) || \n      (!allowAAWithdrawRequest && _tranche == AATranche) || \n      (!allowBBWithdrawRequest && _tranche == BBTranche) ||\n      !isWalletAllowed(msg.sender)\n    );\n  \n    // we check if there are donated assets to the pool and transfer them to the feeReceiver if any\n    _skimDonatedAssets();\n\n    // we trigger an update accounting to check for eventual losses\n    _updateAccounting();\n\n    IdleCreditVault creditVault = IdleCreditVault(strategy);\n    if (_amount == 0) {\n      _amount = _userTrancheBal(msg.sender, _tranche);\n    }\n    _underlyings = _trancheToUnderlyings(_amount, _tranche);\n\n    // Programmable borrower deployments do not support instant withdrawals.\n    // If apr decresed wrt last epoch, request instant withdraw and burn tranche tokens directly\n    // we compare unscaled aprs\n    if (!disableInstantWithdraw && !isProgrammableBorrower) {\n      if (lastEpochApr > (creditVault.unscaledApr() + instantWithdrawAprDelta)) {\n        // burn strategy tokens from cdo and mint an equal amount to msg.sender as receipt\n        creditVault.requestInstantWithdraw(_underlyings, msg.sender);\n        // burn tranche tokens and decrease NAV\n        _withdrawOps(_amount, _underlyings, _tranche);\n        return _underlyings;\n      }\n    }\n\n    uint256 principal = _underlyings;\n    (uint256 interest, int256 diff) = _calcInterestWithdrawRequest(_underlyings, _tranche);\n    uint256 totalFees = _totalWithdrawFees(principal, interest);\n    // user is requesting principal + interest minus upfront management fee and net performance fee\n    _underlyings = principal + interest - totalFees;\n    // add expected fees to pending withdraw fees counter\n    pendingWithdrawFees += totalFees;\n\n    /// if there is an AA withdrawal the overperformance that the amount withdrawed would have generated for BB tranches\n    /// is saved in interestForOverUnderPerformance. This is used to calculate the interest that should be added to the\n    /// expectedEpochInterest at the startEpoch.\n    /// If there is a BB withdrawal this amount is subtracted from the expectedEpochInterest\n    interestForOverUnderPerformance += diff;\n\n    // The receipt is fixed now and leaves live NAV. Charge management fees upfront\n    // for the time it waits outside live NAV: remaining buffer plus the next epoch.\n    creditVault.requestWithdraw(_underlyings, msg.sender, principal);\n    // burn tranche tokens and decrease NAV without interest for the next epoch as it was not yet counted in NAV\n    _withdrawOps(_amount, principal, _tranche);\n  }\n\n  /// @notice Transfer donated assets to the feeReceiver\n  function _skimDonatedAssets() internal {\n    _transferUnderlyings(feeReceiver, _contractTokenBalance(token));\n  }\n\n  /// @notice Calculate the interest of an epoch for the given amount\n  /// @param _amount Amount of underlyings\n  function _calcInterest(uint256 _amount) internal view returns (uint256) {\n    return _calcInterestWithApr(_amount, _getStrategyApr());\n  }\n\n  /// @notice Calculate the interest of an epoch for the given amount and apr\n  /// @param _amount Amount of underlyings\n  /// @param _apr Apr used for the calculation\n  function _calcInterestWithApr(uint256 _amount, uint256 _apr) internal view returns (uint256) {\n    return _amount * (_apr / 100) * epochDuration / (365 days * ONE_TRANCHE_TOKEN);\n  }\n\n  /// @notice Get current tranches value\n  /// @param _amount Amount of tranche tokens\n  /// @param _tranche Tranche to get the value for\n  /// @return Value of the tranche tokens in underlyings\n  function _trancheToUnderlyings(uint256 _amount, address _tranche) internal view returns (uint256) {\n    return _amount * _tranchePrice(_tranche) / ONE_TRANCHE_TOKEN;\n  }\n\n  /// @notice Get borrower address from strategy.\n  /// @return borrower address\n  function _borrower() internal view returns (address) {\n    return IdleCreditVault(strategy).borrower();\n  }\n\n  /// @notice Get pending instant withdraws from strategy.\n  /// @return pending instant withdraws\n  function _pendingInstant() internal view returns (uint256) {\n    return IdleCreditVault(strategy).pendingInstantWithdraws();\n  }\n\n  /// @notice Calculate the interest of an epoch for a withdraw request\n  /// @dev to avoid having funds not getting interest during buffer period, the apr \n  /// set in the stopEpoch is higher than then intended one so it will cover also the buffer period\n  /// eg epoch = 30 days, buffer = 5 days, then if we want to give 10% apr for all the 35 days then\n  /// in stop epoch we set the apr to 10% * 35/30 = 11.67%. For this reason people who instead request\n  /// a withdraw should not get the additional interest for the buffer period because they can withdraw\n  /// a block after the buffer period starts. So we calculate the interest for the 30 days only,\n  /// eg. if apr is set to 11.67% and we want to calculate the interest for 30 days at 10% we need to do the \n  /// the opposite -> 11.67% * 30/35 = 10%\n  /// @param _amount Amount of underlyings\n  /// @param _tranche Tranche to withdraw from\n  /// @return _interest Interest for the given amount and given tranche\n  /// @return _diff over/under performance that this withdraw will cause to the other tranche\n  function _calcInterestWithdrawRequest(uint256 _amount, address _tranche) internal view returns (uint256 _interest, int256 _diff) {\n    uint256 _duration = epochDuration;\n    if (_duration == 0) {\n      return (_interest, _diff);\n    }\n\n    uint256 _buffer = bufferPeriod;\n    // calculate total vault interest (they don't get the interest for the buffer period for withdraw requests so \n    // we scale it back since _calcInterest is scaling the interest with tht buffer period),\n    uint256 totInterest = _calcInterest(_managedContractValue()) * _duration / (_duration + _buffer);\n    // calculate total tranche interest for the whole tranche supply\n    uint256 totTrancheInterest = _calcTrancheInterestShare(totInterest, _tranche);\n    // calculate interest for the given tranche and given amount\n    uint256 _trancheBal = _lastSavedNAV(_tranche);\n    _interest = _trancheBal == 0 ? 0 : _amount * totTrancheInterest / _trancheBal;\n    // calculate the interest that the _amount would have received if there was no split ratio (ie interest split based only on tvl).\n    // This is used to calculate the interest that should be added to the expectedEpochInterest when \n    // withdrawing an AA tranche or the interest that should be removed from expectedEpochInterest when\n    // withdrawing a BB tranche\n    uint256 interestWithoutSplitRatio = _calcInterest(_amount) * _duration / (_duration + _buffer);\n    // difference between total interest and tranche interest (positive for AA, negative for BB)\n    _diff = int256(interestWithoutSplitRatio) - int256(_interest);\n  }\n\n  /// @notice Calculate the tranche share of the total interest for the epoch\n  /// @param _totalInterest Total interest for the epoch (net of fees not meant for tranches)\n  /// @param _tranche Tranche to get the interest for\n  function _calcTrancheInterestShare(uint256 _totalInterest, address _tranche) internal view returns (uint256) {\n    uint256 ratio = trancheAPRSplitRatio;\n    return _totalInterest * (_tranche == AATranche ? ratio : FULL_ALLOC - ratio) / FULL_ALLOC;\n  }\n\n  /// @notice Apply projected management and performance fees to a positive gain.\n  function _netGainAfterFees(uint256 _gain, uint256 _managementFee) private view returns (uint256 netGain) {\n    if (_managementFee >= _gain) return netGain;\n    // remove mgmt fee and performance fee\n    _gain -= _managementFee;\n    return _gain - _gain * fee / FULL_ALLOC;\n  }\n\n  /// @notice Calculate total fees charged on a withdrawal request.\n  /// @param _principal Principal leaving live NAV.\n  /// @param _interest Projected interest for the requested principal.\n  /// @return Total management and performance fees to subtract from principal plus projected interest.\n  function _totalWithdrawFees(uint256 _principal, uint256 _interest) private view returns (uint256) {\n    uint256 _mgmtFee = _calculateManagementFee(_principal, _withdrawRequestManagementFeeDuration());\n    // When interest covers management fees, interest - netGain equals management fee plus performance fee.\n    return _mgmtFee >= _interest ?\n      _mgmtFee :\n      _interest - _netGainAfterFees(_interest, _mgmtFee);\n  }\n\n  /// @notice Get the max amount of underlyings that can be withdrawn by user\n  /// @param _user User address\n  /// @param _tranche Tranche to withdraw from\n  function maxWithdrawable(address _user, address _tranche) external view returns (uint256 currentUnderlyings) {\n    currentUnderlyings = _trancheToUnderlyings(_userTrancheBal(_user, _tranche), _tranche);\n    currentUnderlyings -= _calculateManagementFee(currentUnderlyings, block.timestamp - latestHarvestBlock);\n    // add interest for one epoch\n    (uint256 interest, ) = _calcInterestWithdrawRequest(currentUnderlyings, _tranche);\n    // remove upfront management fee and performance fee on the remaining projected interest\n    currentUnderlyings = currentUnderlyings + interest - _totalWithdrawFees(currentUnderlyings, interest);\n  }\n\n  /// @notice Get the duration used for upfront management fees on withdrawal receipts.\n  /// @dev Receipts leave live NAV at request time but can be claimed only after the\n  /// next epoch settles. Requests made during the buffer also pay for the remaining\n  /// buffer time before that next epoch can start.\n  /// @return _duration One epoch plus any remaining buffer before the next epoch.\n  function _withdrawRequestManagementFeeDuration() private view returns (uint256 _duration) {\n    uint256 bufferEnd = epochEndDate + bufferPeriod;\n    _duration = epochDuration;\n    if (block.timestamp < bufferEnd) {\n      _duration += bufferEnd - block.timestamp;\n    }\n  }\n\n  /// @notice Write off the deposit, this will be used if the borrower and a lender comes to an off-chain agreement\n  /// so here we burn tranche tokens, the equivalent amount of strategy tokens. Only the borrower can call this\n  /// @param _amount Amount of tranche tokens to write off\n  function writeOffDeposit(uint256 _amount, address _tranche) external {\n    // only borrower can call this method and only during an epoch, otherwise one should follow the traditional flow\n    _checkNotAllowed(_borrower() != msg.sender || !isEpochRunning);\n    // Remove raw donations so write-off interest math only sees accounted vault value.\n    _skimDonatedAssets();\n\n    // we don't check the _tranche address to be AATranche or BBTranche as this method can be called only by the borrower\n    // and borrower is trusted\n\n    // Calculate tranche tokens value with current tranche price\n    uint256 _underlyings = _trancheToUnderlyings(_amount, _tranche);\n    // We now calculate how much interest + fee the tranche would have generated in the current epoch\n    (uint256 interest, int256 diff) = _calcInterestWithdrawRequest(_underlyings, _tranche);\n    // given that _calcInterestWithdrawRequest returns an interest and diff value meant to be used in requestWithdraw\n    // it does not include the buffer period but given that the epoch is running expectedEpochInterest was\n    // calculated with the buffer period included, so we need to scale the interest\n    uint256 _epochDuration = epochDuration;\n\n    // (interest + diff) gives the interest based on tvl as write off debt won't follow senior/junior interest split ratio\n    // diff is positive for AA and negative for BB (in this case it won't be > of interest)\n    interest = uint256(int256(interest) + diff) * (_epochDuration + bufferPeriod) / _epochDuration;\n\n    // Burn tranche tokens and decrease lastNAV\n    _withdrawOps(_amount, _underlyings, _tranche);\n    // Burn strategy tokens and decrease NAV (1:1 with underlyings)\n    IdleCreditVault(strategy).burnStrategyTokens(_underlyings);\n\n    // remove the interest + fee from expectedEpochInterest\n    expectedEpochInterest -= interest;\n  }\n\n  /// @notice Claim a withdraw request from the vault. Can be done when at least 1 epoch passed\n  /// since last withdraw request\n  function claimWithdrawRequest() external {\n    // underlyings requested, here we check that user waited at least one epoch and that borrower\n    // did not default upon repayment (old requests can still be claimed)\n    IdleCreditVault(strategy).claimWithdrawRequest(msg.sender);\n  }\n\n  /// @notice Claim an instant withdraw request from the vault. Can be done when epoch is running\n  /// as funds will get transferred from borrower when epoch starts\n  function claimInstantWithdrawRequest() external {\n    // Check that instant withdraws are available\n    _checkNotAllowed(!allowInstantWithdraw);\n    IdleCreditVault(strategy).claimInstantWithdrawRequest(msg.sender);\n  }\n\n  /// @notice Check if wallet is allowed to interact with the contract\n  /// @param _user User address\n  /// @return true if wallet is allowed or keyring address is not set\n  function isWalletAllowed(address _user) public view returns (bool) {\n    address _keyring = keyring;\n    return _keyring == address(0) || IKeyring(_keyring).checkCredential(keyringPolicyId, _user);\n  }\n\n  /// @notice Notify a programmable borrower that a new epoch has started.\n  /// @param _pendingWithdraws Amount reserved for withdraw requests that mature at epoch stop.\n  function _startEpochProgrammableBorrower(uint256 _pendingWithdraws) internal {\n    if (isProgrammableBorrower) {\n      IProgrammableBorrower(_borrower()).onStartEpoch(_pendingWithdraws);\n    }\n  }\n\n  /// @notice Resolve the stop-epoch interest value, optionally sourcing it from a programmable borrower.\n  /// @dev Programmable borrowers are always the source of truth for epoch interest.\n  /// In that mode `_interest` values `0` and `1` both resolve to the realized epoch interest,\n  /// while `1` still separately signals the close-pool path to the caller.\n  function _resolveStopEpochInterest(uint256 _interest) internal view returns (uint256 _resolvedInterest) {\n    if (isProgrammableBorrower) {\n      _checkNotAllowed(_interest > 1);\n      return IProgrammableBorrower(_borrower()).totalInterestDueNow();\n    }\n\n    _resolvedInterest = _interest;\n  }\n}\n","deployed_bytecode":"0x60806040523480156200001157600080fd5b5060043610620004ba5760003560e01c806301d22ccd14620004bf5780630553c2e714620004eb57806306a9a8bf1462000505578063085a2b78146200050f578063088f4b7814620005195780631072cbea146200053257806312361ac214620005495780631441a5a914620005535780631533c31e146200056c5780631a7e0ce514620005835780632544e84114620005a257806325cdd86014620005ad57806329811ee514620005b75780632c2a7ca414620005ce5780632e02cd5e14620005d85780632e2452ab14620005ef57806333986ffa14620005fd57806333f0f80014620006075780633403c2fc1462000612578063387af1bd146200061c5780633f4ba83a1462000630578063400f7d32146200063a578063408f3a30146200064457806340a2029e146200065b57806340bd61091462000672578063435d44d9146200067c57806343848aed146200069357806344966ba0146200069e578063452a932014620006b2578063494347e714620006c65780634da4f60314620006d05780634ff0876a14620006e4578063514b6dbd14620006ef57806355c70701146200070657806358cdd22b146200071b5780635b4a3462146200072f5780635c975abb14620007465780635f0b472a146200075257806362adade514620007615780636373ea69146200076b578063655c9a5314620007755780636736d616146200078057806369e25ec114620007975780636bd7b30114620007ac5780636c4321eb14620007bb5780636d90a39c14620007d0578063715018a614620007de578063734d828714620007e8578063747efea114620007f257806375d1497b146200080657806381f5ae7e14620008115780638260dbba146200081b57806383975b6714620008265780638456cb5914620008305780638a0dac4a146200083a5780638da5cb5b146200085157806391b900ef146200085b5780639290d427146200087257806392b29be314620008895780639616423614620008935780639638529c14620008a7578063991052b714620008be5780639a4d360814620008c85780639d3ef4b214620008df5780639ed9de9414620008f4578063a219d2181462000910578063a2454e551462000927578063a27eccc1146200093e578063a2c8b1771462000948578063a4d66daf1462000952578063a6f7f5d6146200095c578063a8c62e761462000966578063b3f00674146200097a578063b450dfce146200098e578063b9ed206914620009a5578063bc063e1a14620009bc578063c5c7509814620009c6578063c61e3faa14620009d5578063c88e844714620009ec578063c9aba3561462000a03578063ccc143b81462000a13578063cfa565671462000a2a578063d48099ad1462000a34578063d636b05f1462000a4b578063dc82697c1462000a56578063ddca3f431462000a60578063dee7c2cb1462000a6a578063dfd5b1c91462000a81578063dfefc7f81462000a8c578063e2988e6e1462000a97578063e3e393681462000aa2578063e70875ad1462000ab6578063edd636fb1462000acd578063ef191b7f1462000ad7578063f2fde38b1462000aee578063fa69d1771462000b05578063fc0c546a1462000b1c578063fe81a0241462000b30575b600080fd5b60d254620004d3906001600160a01b031681565b604051620004e29190620048e9565b60405180910390f35b620004f661012a5481565b604051908152602001620004e2565b620004f660ed5481565b620004f660da5481565b620005306200052a3660046200490c565b62000b3a565b005b620005306200054336600462004942565b62000b57565b620004f660dc5481565b60e854620004d39061010090046001600160a01b031681565b620005306200057d36600462004971565b62000b81565b60ea54620005919060ff1681565b6040519015158152602001620004e2565b620004f66101245481565b620004f662000b90565b620004f6620005c83660046200498b565b62000ba3565b620004f660ec5481565b62000591620005e93660046200498b565b62000c55565b60f054620005919060ff1681565b6200053062000cf3565b620004f66101255481565b6200053062000d6e565b60ca54620004d3906001600160a01b031681565b6200053062000d86565b620004f660dd5481565b620005306200065536600462004971565b62000d9a565b620005306200066c366004620049ab565b62000da9565b620004f660ee5481565b620005306200068d36600462004971565b62000deb565b620004f66101275481565b60d654620004d3906001600160a01b031681565b60d054620004d3906001600160a01b031681565b6200053062000e0a565b61011e546200059190610100900460ff1681565b620004f661011f5481565b62000530620007003660046200490c565b62000e28565b60d3546200059190600160a01b900460ff1681565b610128546200059190610100900460ff1681565b62000530620007403660046200490c565b62000e57565b60335460ff1662000591565b61012d54620005919060ff1681565b620004f660de5481565b620004f660e95481565b620004f66101265481565b62000530620007913660046200490c565b62000e75565b61012854620005919062010000900460ff1681565b61012854620005919060ff1681565b61011e54620005919062010000900460ff1681565b60e854620005919060ff1681565b6200053062000eb5565b620004f660e15481565b60d554620004d3906001600160a01b031681565b620004f66101225481565b620004f660cc5481565b620004f66101205481565b6200053062000ecb565b6200053062000f24565b620005306200084b3660046200498b565b62000f38565b620004d362000f6c565b620005306200086c366004620049e7565b62000f7b565b620004f6620008833660046200498b565b62000ffe565b620004f660e25481565b61012d546200059190610100900460ff1681565b62000530620008b836600462004a25565b6200103c565b6200053062001494565b62000530620008d936600462004971565b6200150f565b60d3546200059190600160a81b900460ff1681565b61012854620004d390630100000090046001600160a01b031681565b620004f6620009213660046200498b565b62001532565b620005306200093836600462004942565b62001545565b620004f660d15481565b6200053062001581565b620004f660c95481565b620004f660f15481565b60d454620004d3906001600160a01b031681565b60e454620004d3906001600160a01b031681565b620004f66200099f36600462004971565b62001967565b62000530620009b636600462004ab4565b62001983565b620004f6614e2081565b61011e54620005919060ff1681565b620004f6620009e636600462004ae1565b620019c4565b62000530620009fd36600462004b14565b62001c71565b620004f6670de0b6b3a764000081565b620004f662000a2436600462004ae1565b62001d27565b620005306200201f565b6200053062000a4536600462004b47565b6200214f565b620004f66101295481565b620004f6620029e1565b620004f660e35481565b6200053062000a7b36600462004ae1565b62002a2e565b620004f6620186a081565b620004f66101235481565b620004f66101215481565b60d754620004d3906001600160a01b031681565b620004f662000ac736600462004971565b62002b59565b620004f660e65481565b620004f662000ae836600462004b6a565b62002b75565b6200053062000aff3660046200498b565b62002bee565b6200053062000b1636600462004b47565b62002c6a565b60cf54620004d3906001600160a01b031681565b620004f660df5481565b62000b4462002ca9565b60ea805460ff1916911515919091179055565b62000b6162002ca9565b60ca5462000b7d906001600160a01b0384811691168362002cc9565b5050565b62000b8b62002ca9565b60ee55565b600062000b9e600062002d23565b905090565b60008062000bb2600062002d23565b9050600062000bc062002dad565b90508162000bf05760d6546001600160a01b0385811691161462000be5578062000be8565b60005b949350505050565b60da5460d6546001600160a01b0386811691161462000c485762000c1883620186a062004bb3565b62000c2782620186a062004bb3565b62000c33908462004bcd565b62000c3f919062004c05565b95945050505050565b8262000c33828462004bcd565b61012854600090630100000090046001600160a01b031680158062000cec57506101295460405163043bb58960e51b81526001600160a01b03831691638776b1209162000ca89190879060040162004c1c565b602060405180830381865afa15801562000cc6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000cec919062004c33565b9392505050565b60d45460405163370a95eb60e21b81526001600160a01b039091169063dc2a57ac9062000d25903390600401620048e9565b6020604051808303816000875af115801562000d45573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000d6b919062004c53565b50565b62000d7862002e1e565b62000d84600062002e60565b565b62000d9062002e1e565b62000d8462002ead565b62000da462002ca9565b60c955565b62000db362002efd565b61011e5462000dc59060ff1662002fb8565b610120929092556101255561012880549115156101000261ff0019909216919091179055565b62000df562002ca9565b62000d6b620186a08260ec8190551162002fd8565b62000e1462002e1e565b62000e1e62002ff8565b62000d8462003021565b62000e3262002ca9565b61011e5462000e449060ff1662002fb8565b60f0805460ff1916911515919091179055565b62000e6162002efd565b61012d805460ff1916911515919091179055565b62000e7f62002ca9565b62000e9a8115801562000e94575060f05460ff165b62002fb8565b61012d80549115156101000261ff0019909216919091179055565b62000ebf6200304d565b62000d846000620030b0565b62000ed562002ca9565b6101285462000eed9062010000900460ff1662002fb8565b60335460ff161562000f035762000f0362002ead565b61011e805462ffff0019166201010017905560d3805460ff60b81b19169055565b62000f2e62002e1e565b62000d8462003102565b62000f4262002ca9565b60d080546001600160a01b0319166001600160a01b03831690811790915562000d6b901562003142565b6065546001600160a01b031690565b62000f8562002ca9565b62000fbb614e2084118062000f9c5750620186a083115b8062000fb5575062000fb2600a614e2062004c05565b82115b62002fd8565b60e480546001600160a01b0319166001600160a01b03861690811790915562000fe5901562003142565b62000fef62003162565b60e39290925560e95560f15550565b600062001035826200100f6200319d565b60df5460de5462001021919062004c6d565b6200102c86620031e2565b60da546200320c565b5092915050565b600054610100900460ff16158080156200105d5750600054600160ff909116105b806200108257506200106f306200347d565b15801562001082575060005460ff166001145b620010eb5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156200110f576000805461ff0019166101001790555b60cf546001600160a01b031615620011395760405162dc149f60e41b815260040160405180910390fd5b620011616001600160a01b03841615806200115b57506001600160a01b038816155b62003142565b62001171620186a0831162002fd8565b6200117b6200348c565b62001188888787620034c0565b6000836001600160a01b031663747efea16040518163ffffffff1660e01b8152600401602060405180830381865afa158015620011c9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011ef919062004c88565b90506000816001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001232573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200125c919081019062004ced565b9050620012a36040518060400160405280600781526020016602830b932ba37960cd1b815250604051806040016040528060018152602001600760fc1b8152508362003526565b60d660006101000a8154816001600160a01b0302191690836001600160a01b03160217905550620013146040518060400160405280600a81526020016902830b932ba37902121160b51b815250604051806040016040528060048152602001637042425f60e01b8152508362003526565b60d780546001600160a01b03199081166001600160a01b039384161790915560cf805482168c841690811790915560d48054831689851617905560d5805490921692851692909217905560da8590556040805163313ce56760e01b815290516000929163313ce5679160048083019260209291908290030181865afa158015620013a2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620013c8919062004c53565b620013d590600a62004e97565b60d181905560dc81905560dd8190559050620013f28a8762003581565b620013fe838762003581565b60d080546001600160a01b0319166001600160a01b038a1617905560ea805460ff1916600117905561c35060ec554260cc5561138860ed556200144062003599565b50505080156200148a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b61012854620014a79060ff161562002fb8565b60d4546040516347e9887560e11b81526001600160a01b0390911690638fd310ea90620014d9903390600401620048e9565b600060405180830381600087803b158015620014f457600080fd5b505af115801562001509573d6000803e3d6000fd5b50505050565b6200151d3330141562002fb8565b62000d6b6200152b62003612565b8262003683565b60006200153f82620036a6565b92915050565b6200154f62002efd565b61012880546001600160a01b039093166301000000026301000000600160b81b03199093169290921790915561012955565b6200158b62002efd565b61011f5461012a5461012254620015b891620015a79162004c6d565b42108062000e945750811562002fb8565b620015c2620036e7565b620015cc62002ff8565b61011e805460ff19166001179055620015e462003102565b61011e805462ffff001916905560d45461012c54610126546001600160a01b03909216916200161c62001616620029e1565b6200370d565b62001628919062004ea5565b62001634919062004ea5565b61012155600061012c556200164a824262004c6d565b61012255610120546200165e904262004c6d565b610123819055506000816001600160a01b031663efda7e076040518163ffffffff1660e01b8152600401602060405180830381865afa158015620016a6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620016cc919062004c53565b61012d54909150600090610100900460ff16620016fa578161012754620016f4919062004c6d565b620016fc565b815b9050801562001765576040516001625a42ed60e11b03198152600481018290526001600160a01b0384169063ff4b7a2690602401600060405180830381600087803b1580156200174b57600080fd5b505af115801562001760573d6000803e3d6000fd5b505050505b60006200177162003724565b60cf549091506000906200178e906001600160a01b03166200376f565b90506000856001600160a01b031663a9a949686040518163ffffffff1660e01b8152600401602060405180830381865afa158015620017d1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620017f7919062004c53565b90508183111562001872576040516303c96c4560e61b8152600481018390526001600160a01b0387169063f25b114090602401600060405180830381600087803b1580156200184557600080fd5b505af11580156200185a573d6000803e3d6000fd5b505050506200186981620037e4565b50505050505050565b6040516303c96c4560e61b8152600481018490526001600160a01b0387169063f25b114090602401600060405180830381600087803b158015620018b557600080fd5b505af1158015620018ca573d6000803e3d6000fd5b5050610128805460ff191660011790555060009050620018eb848462004bb3565b604051631349a6c160e31b8152600481018290529091503090639a4d360890602401600060405180830381600087803b1580156200192857600080fd5b505af19250505080156200193a575060015b6200195c576200194b878262003683565b62001956816200385f565b6200148a565b6200148a82620037e4565b60d6546000906200153f9083906001600160a01b031662003934565b620019913330141562002fb8565b620019bf6200199f62003612565b3083620019ad868862004c6d565b620019b9919062004c6d565b62003965565b505050565b61012d5460009062001a5a9060ff1680620019e1575060f05460ff165b80620019ef575060ea5460ff165b80620019ff575061011e5460ff16155b8062001a0e5750610122544210155b8062001a41575060d6546001600160a01b038481169116148062001a3f575060d7546001600160a01b038481169116145b155b8062000e94575062001a533362000c55565b1562002fb8565b8262001a66576200153f565b600062001a73836200398a565b905062001a81811562002fb8565b62001a8b62002ff8565b62001a9684620039cb565b62001aa062003a0d565b62001aad33308662003965565b61012a546101225460009062001ac590429062004bb3565b905060008261011f5462001ada919062004c6d565b62001ae6848462004c6d565b62001af1896200370d565b62001afd919062004bcd565b62001b09919062004c05565b61012154610126549192509060008183111562001b615762001b5e62001b5762001b34848662004bb3565b62001b5160df5460de5462001b4a919062004c6d565b8962003b6b565b62003b9d565b8a62003be7565b90505b600062001b7f62001b788662001b518e8a62003b6b565b8b62003be7565b905060008262001b8f8c620031e2565b62001b9b919062004c6d565b9050808962001bab848f62004c6d565b62001bb7919062004bcd565b62001bc3919062004c05565b995062001bd38b338c8f62003c38565b85610121600082825462001be8919062004c6d565b909155505060d454604051633ec701eb60e01b8152600481018e90526001600160a01b0390911690633ec701eb90602401600060405180830381600087803b15801562001c3457600080fd5b505af115801562001c49573d6000803e3d6000fd5b5050505062001c6262001c5b62003612565b8d62003683565b50505050505050505092915050565b62001c7d84846200214f565b801580159062001c9757506101285462010000900460ff16155b1562001d075760d454604051633e81a73360e01b8152600481018390526001600160a01b0390911690633e81a73390602401600060405180830381600087803b15801562001ce457600080fd5b505af115801562001cf9573d6000803e3d6000fd5b5050505062001d0762003021565b62001d168261012a5462002c6a565b62001d218462003cf4565b62001509565b60d65460009062001dca906001600160a01b0384811691161480159062001d5c575060d7546001600160a01b03848116911614155b8062001d8a575061011e54610100900460ff1615801562001d8a575060d6546001600160a01b038481169116145b8062001a41575061011e5462010000900460ff1615801562001a41575060d7546001600160a01b038481169116148062000e94575062001a533362000c55565b62001dd462002ff8565b62001dde62003a0d565b60d4546001600160a01b03168362001dff5762001dfc338462003d9f565b93505b62001e0b848462003e14565b61012854909250610100900460ff1615801562001e2b575060f05460ff16155b1562001f295761012554816001600160a01b031663d7bff5386040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001e74573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001e9a919062004c53565b62001ea6919062004c6d565b61012454111562001f2957604051630a198c7f60e21b81526001600160a01b0382169063286631fc9062001ee1908590339060040162004c1c565b600060405180830381600087803b15801562001efc57600080fd5b505af115801562001f11573d6000803e3d6000fd5b5050505062001f2284838562003e36565b506200153f565b8160008062001f39838762003efd565b91509150600062001f4b848462003fe8565b90508062001f5a848662004c6d565b62001f66919062004bb3565b955080610126600082825462001f7d919062004c6d565b925050819055508161012c600082825462001f99919062004ea5565b909155505060405163f16c6bf160e01b815260048101879052336024820152604481018590526001600160a01b0386169063f16c6bf190606401600060405180830381600087803b15801562001fee57600080fd5b505af115801562002003573d6000803e3d6000fd5b505050506200201488858962003e36565b505050505092915050565b6200202962002efd565b60f054620020579060ff168062002044575061011e5460ff16155b8062000e94575061012354421062002fb8565b60d4546001600160a01b031660006200206f62003724565b60405163b9ed206960e01b8152909150309063b9ed2069906200209c906000908190869060040162004eec565b600060405180830381600087803b158015620020b757600080fd5b505af1925050508015620020c9575060015b620020d95762000b7d816200385f565b80156200213d576040516303c96c4560e61b8152600481018290526001600160a01b0383169063f25b114090602401600060405180830381600087803b1580156200212357600080fd5b505af115801562002138573d6000803e3d6000fd5b505050505b610128805460ff191660011790555050565b6200215962002efd565b62002163620036e7565b60d4546101265461011e546001600160a01b0390921691620021cb9060ff1615806200219157506101225442105b80620021a55750620021a262003724565b15155b8062000e94575060018411801562000e9457508184108062000e94575084151562002fb8565b620021d562002ff8565b60018314620021e48462004023565b60405163bb42b77360e01b8152600481018290529094506000906001600160a01b0385169063bb42b7739060240160408051808303816000875af115801562002231573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002257919062004f02565b80945081925050506000846001600160a01b031663a9a949686040518163ffffffff1660e01b8152600401602060405180830381865afa158015620022a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620022c6919062004c53565b9050600083156200230f5760cf54620022e8906001600160a01b03166200376f565b620022f2620029e1565b620022fe919062004bb3565b90506200230c818462004c6d565b92505b6000846200231e57836200232a565b6200232a828562004bb3565b61012d54909150600090610100900460ff16801562002347575085155b90506000816200235857856200235b565b60005b90508180156200236b575060018a115b1562002415576000896001600160a01b03166392093b366040518163ffffffff1660e01b8152600401602060405180830381865afa158015620023b2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620023d8919062004c53565b905062002413811580159062000e94575089620023ff620023f8620029e1565b846200408c565b6200240b919062004c6d565b851162002fb8565b505b600062002423868362004c6d565b60f05490915060ff1615620024e0576200243c62003612565b604051639b8e712b60e01b81526004810183905289151560248201526001600160a01b039190911690639b8e712b906044016020604051808303816000875af11580156200248e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620024b4919062004c33565b620024e057610128805460ff19166001179055620024d2816200385f565b505050505050505050505050565b620024ea62003162565b60405163b9ed206960e01b8152309063b9ed206990620025149085908a9060009060040162004eec565b600060405180830381600087803b1580156200252f57600080fd5b505af192505050801562002541575060015b6200257057610128805460ff191660011790556200256a62002564878962004c6d565b6200385f565b620024d2565b8515620025d457604051638b80c89d60e01b8152600481018790526001600160a01b038b1690638b80c89d90602401600060405180830381600087803b158015620025ba57600080fd5b505af1158015620025cf573d6000803e3d6000fd5b505050505b828015620025e4575060f05460ff165b156200264957620025f462003612565b6001600160a01b0316632512529b6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156200262f57600080fd5b505af115801562002644573d6000803e3d6000fd5b505050505b826200265a576200265a89620040c3565b87156200266d576200266d8a8662003683565b8215620026f2578315620026d857604051633ec701eb60e01b8152600481018590526001600160a01b038b1690633ec701eb90602401600060405180830381600087803b158015620026be57600080fd5b505af1158015620026d3573d6000803e3d6000fd5b505050505b8860e16000828254620026ec919062004c6d565b90915550505b620026fc62003a0d565b60e1548315620027905780156200278a5760006200271a8262004105565b90508015620027455760e45460d654620027439183916001600160a01b03918216911662004141565b505b6200277162002755828462004bb3565b6200275f62000f6c565b60d6546001600160a01b031662004141565b506200278862002782600162002d23565b6200417e565b505b620027ca565b60008a8611620027a2576000620027ae565b620027ae8b8762004bb3565b905080821115620027bd578091505b620027c882620040c3565b505b8060e16000828254620027de919062004bb3565b909155506000905084620027f3578a620027f6565b60005b62002802908362004c6d565b905060008187116200281657600062002822565b62002822828862004bb3565b61012781905590506001600160a01b038d1663b6b55f258762002846578262002849565b60005b6040518263ffffffff1660e01b81526004016200286891815260200190565b6020604051808303816000875af115801562002888573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620028ae919062004c53565b508c6001600160a01b031663d7bff5386040518163ffffffff1660e01b8152600401602060405180830381865afa158015620028ee573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002914919062004c53565b61012455620029238f62003cf4565b61011e805460ff191690556000610121819055610126556200294462002ead565b61011e805462ffff00191662010100179055610128805460ff19168c158015919091179091556200298c57610128805461ff001916610100179055600061011f819055610122555b7ff66f28b40975dbb933913542c7e6a0f50a1d0f20aa74ea6e0efe65ab616323ec620029b9898c62004bb3565b60408051918252602082018590520160405180910390a1505050505050505050505050505050565b60e15460cf5460009190620029ff906001600160a01b03166200376f565b60d55462002a16906001600160a01b03166200376f565b62002a22919062004c6d565b62000b9e919062004bb3565b62002a5d3362002a3d62003612565b6001600160a01b031614158062000e94575061011e5460ff161562002fb8565b62002a6762002ff8565b600062002a75838362003e14565b905060008062002a86838562003efd565b91509150600061011f5490508061012a548262002aa4919062004c6d565b62002ab0848662004ea5565b62002abc919062004bcd565b62002ac8919062004c05565b925062002ad786858762003e36565b60d454604051633e81a73360e01b8152600481018690526001600160a01b0390911690633e81a73390602401600060405180830381600087803b15801562002b1e57600080fd5b505af115801562002b33573d6000803e3d6000fd5b5050505082610121600082825462002b4c919062004bb3565b9091555050505050505050565b60d7546000906200153f9083906001600160a01b031662003934565b600062002b8e62002b87848462003d9f565b8362003e14565b905062002bab8160cc544262002ba5919062004bb3565b62003b6b565b62002bb7908262004bb3565b9050600062002bc7828462003efd565b50905062002bd6828262003fe8565b62002be2828462004c6d565b62000be8919062004bb3565b62002bf86200304d565b6001600160a01b03811662002c5f5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620010e2565b62000d6b81620030b0565b62002c7462002efd565b61011e5462002c9c9060ff168062002c8a575082155b8062000e94575061011f541562002fb8565b61011f9190915561012a55565b62000d843362002cb862000f6c565b6001600160a01b0316141562004209565b620019bf8363a9059cbb60e01b848460405160240162002ceb92919062004f27565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915262004229565b6000620048d18262002d39576200430562002d3e565b620043325b60d65490915060009062002d5e906001600160a01b031663ffffffff8416565b60d75490915060009062002d7e906001600160a01b031663ffffffff8516565b62002d8a908362004c6d565b90508062002d9d57506000949350505050565b8062000c33620186a08462004bcd565b60d45460408051632116f20160e21b815290516000926001600160a01b03169163845bc8049160048083019260209291908290030181865afa15801562002df8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000b9e919062004c53565b60d05462000d84906001600160a01b0316331480159062002e5a575062002e4462000f6c565b6001600160a01b0316336001600160a01b031614155b62004209565b60335460ff1662002e755762002e7562003102565b61011e805462ff000019921515610100029290921662ffff001990921691909117905560d3805460ff60b81b1916600160b81b179055565b62002eb762004348565b6033805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405162002ef39190620048e9565b60405180910390a1565b62000d8462002f0b62000f6c565b6001600160a01b0316336001600160a01b03161415801562000e94575060d460009054906101000a90046001600160a01b03166001600160a01b031663481c6a756040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002f7c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002fa2919062004c88565b6001600160a01b0316336001600160a01b031614155b801562000d6b57604051631eb49d6d60e11b815260040160405180910390fd5b801562000d6b5760405163fd7850ad60e01b815260040160405180910390fd5b60e45460cf5462000d84916001600160a01b03908116916200301b91166200376f565b62003683565b60d3805460ff60b81b1916600160b81b1790556200303e62003a0d565b60d3805460ff60b81b19169055565b336200305862000f6c565b6001600160a01b03161462000d845760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620010e2565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6200310c62004393565b6033805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25862002ee43390565b801562000d6b576040516321e7594160e21b815260040160405180910390fd5b6200317f620031706200319d565b60cc5462002ba5904262004bb3565b60e1600082825462003192919062004c6d565b90915550504260cc55565b60d5546000908190620031b9906001600160a01b03166200376f565b60e154909150808211620031cf576000620031db565b620031db818362004bb3565b9250505090565b60d6546000906001600160a01b03838116911614620032045760df546200153f565b505060de5490565b60008060006200321c886200398a565b90508515806200322a575080155b156200323f57505060d1549050600062003473565b60006200324d878962004f40565b9050806200326e576200326089620036a6565b600093509350505062003473565b6000811315620032a757620186a060e354826200328c919062004f85565b62003298919062005016565b620032a4908262004f40565b90505b60d65460d7546001600160a01b0391821691908116908b168214620032d981620032d257836200398a565b826200398a565b620032e7578395506200343d565b60008413156200333f576000620186a0620033038a8262004bb3565b6200330f908762004f85565b6200331b919062005016565b9050816200332a578062003336565b62003336818662004f40565b9650506200343d565b620186a08a60ee5462003353919062004bcd565b6200335f919062004c05565b6200336a856200504a565b11620033c35760df5460de546000906200338690839062004c6d565b62003392838862004f85565b6200339e919062005016565b905082620033ad5780620033b9565b620033b9818762004f40565b975050506200343d565b600081620033d25789620033de565b620033de8a8c62004bb3565b90506000620033ee868362004ea5565b905060008113156200341257826200340757856200340a565b60005b97506200343a565b826200343657600062003425836200504a565b985098505050505050505062003473565b8097505b50505b84670de0b6b3a764000062003453888c62004ea5565b6200345f919062004bcd565b6200346b919062004c05565b965050505050505b9550959350505050565b6001600160a01b03163b151590565b600054610100900460ff16620034b65760405162461bcd60e51b8152600401620010e2906200506a565b62000d84620043db565b620034e76001600160a01b03831615806200115b57506001600160a01b0382161562003142565b620034f162004411565b620034fb62004445565b60c983905560ca80546001600160a01b0319166001600160a01b038416179055620019bf8162002bee565b600062003534848362004479565b62003540848462004479565b6040516200354e90620048db565b6200355b929190620050e3565b604051809103906000f08015801562003578573d6000803e3d6000fd5b50949350505050565b62000b7d6001600160a01b03831682600019620044a7565b620186a060ee5560ea805460ff1916905562278d0061011f556206978061012a819055620035c8904262004bb3565b6101225561011e80546201010062ffff0019909116179055610128805461ff00191661010017905561012d805460ff1916600117905562000d846200360c62002dad565b62003cf4565b60d45460408051637df1f1b960e01b815290516000926001600160a01b031691637df1f1b99160048083019260209291908290030181865afa1580156200365d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000b9e919062004c88565b806200368d575050565b60cf5462000b7d906001600160a01b0316838362002cc9565b6000620036b3826200398a565b620036c057505060d15490565b60d6546001600160a01b03838116911614620036df5760dd546200153f565b505060dc5490565b60f05462000d849060ff16801562000e94575061012d54610100900460ff161562002fb8565b60006200153f826200371e62002dad565b6200408c565b60d45460408051631e2af12360e31b815290516000926001600160a01b03169163f15789189160048083019260209291908290030181865afa15801562002df8573d6000803e3d6000fd5b6040516370a0823160e01b81526000906001600160a01b038316906370a0823190620037a0903090600401620048e9565b602060405180830381865afa158015620037be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200153f919062004c53565b60f05460ff161562000d6b57620037fa62003612565b6001600160a01b0316631d859d73826040518263ffffffff1660e01b81526004016200382891815260200190565b600060405180830381600087803b1580156200384357600080fd5b505af115801562003858573d6000803e3d6000fd5b5050505050565b610128805462ff000019166201000017905560f05460ff1615620038dc576200388762003612565b6001600160a01b0316636febd5436040518163ffffffff1660e01b8152600401600060405180830381600087803b158015620038c257600080fd5b505af1158015620038d7573d6000803e3d6000fd5b505050505b60335460ff16620038f157620038f162003102565b61011e805462ffffff191690556040518181527fddeda4ec7ef5a5761f0a329088482bf17d717987d67aaad5a3c4535ab7da29099060200160405180910390a150565b60006200394062004393565b6200394f62001a533362000c55565b6200395962002ff8565b62000cec83836200454d565b806200397057505050565b60cf54620019bf906001600160a01b031684848462004653565b6000816001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620037be573d6000803e3d6000fd5b60c954801562000b7d578082620039e1620029e1565b620039ed919062004c6d565b111562000b7d57604051630d45dcb760e11b815260040160405180910390fd5b62003a1762003162565b60de5460df54600062003a2b828462004c6d565b9050600062003a39620029e1565b60da549091508282111562003a8d5760e354620186a09062003a5c858562004bb3565b62003a68919062004bcd565b62003a74919062004c05565b60e1600082825462003a87919062004c6d565b90915550505b60d654600090819062003aad906001600160a01b031685878a876200320c565b60d7549193509150600090819062003ad2906001600160a01b031687898b896200320c565b909250905062003ae3838a62004ea5565b60de5560008112801562003b0157508762003afe826200504a565b12155b1562003b495760d354600160b81b900460ff1662003b325760405163064e30f160e51b815260040160405180910390fd5b600060df5562003b43600162002e60565b62003b59565b62003b55818962004ea5565b60df555b5060dc929092555060dd555050505050565b60006502de413530008260f1548562003b85919062004bcd565b62003b91919062004bcd565b62000cec919062004c05565b600082821062003bad576200153f565b62003bb9828462004bb3565b9250620186a060e3548462003bcf919062004bcd565b62003bdb919062004c05565b62000cec908462004bb3565b60da5460d65460009190620186a0906001600160a01b0385811691161462003c1e5762003c1882620186a062004bb3565b62003c20565b815b62003c2c908662004bcd565b62000be8919062004c05565b6040516340c10f1960e01b81526001600160a01b038516906340c10f199062003c68908690869060040162004f27565b600060405180830381600087803b15801562003c8357600080fd5b505af115801562003c98573d6000803e3d6000fd5b505060d6546001600160a01b0387811691161415915062003cd59050578060de600082825462003cc9919062004c6d565b90915550620015099050565b8060df600082825462003ce9919062004c6d565b909155505050505050565b61011f5460d4546001600160a01b0316635a4f7c5383831562003d41578361012a548562003d23919062004c6d565b62003d2f908762004bcd565b62003d3b919062004c05565b62003d43565b845b6040516001600160e01b031960e085901b16815260048101929092526024820152604401600060405180830381600087803b15801562003d8257600080fd5b505af115801562003d97573d6000803e3d6000fd5b505050505050565b6040516370a0823160e01b81526000906001600160a01b038316906370a082319062003dd0908690600401620048e9565b602060405180830381865afa15801562003dee573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000cec919062004c53565b6000670de0b6b3a764000062003e2a83620036a6565b62003b91908562004bcd565b604051632770a7eb60e21b81526001600160a01b03821690639dc29fac9062003e66903390879060040162004f27565b600060405180830381600087803b15801562003e8157600080fd5b505af115801562003e96573d6000803e3d6000fd5b505060d6546001600160a01b0384811691161415915062003ed39050578160de600082825462003ec7919062004bb3565b9091555062003eed9050565b8160df600082825462003ee7919062004bb3565b90915550505b620019bf62002782600162002d23565b61011f5460009081908062003f13575062003fe1565b61012a54600062003f25828462004c6d565b8362003f34620016166200319d565b62003f40919062004bcd565b62003f4c919062004c05565b9050600062003f5c828862003be7565b9050600062003f6b88620031e2565b9050801562003f93578062003f81838b62004bcd565b62003f8d919062004c05565b62003f96565b60005b9650600062003fa6858762004c6d565b8662003fb28c6200370d565b62003fbe919062004bcd565b62003fca919062004c05565b905062003fd8888262004f40565b96505050505050505b9250929050565b60008062003ffa8462002ba56200468d565b90508281101562000cec5762004011838262003b9d565b6200401d908462004bb3565b62000be8565b60f05460009060ff16156200408857620040406001831162002fb8565b6200404a62003612565b6001600160a01b0316630ceff3da6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620037be573d6000803e3d6000fd5b5090565b6000620040a6670de0b6b3a76400006301e1338062004bcd565b61011f54620040b760648562004c05565b62003b85908662004bcd565b6000620040d08262004105565b60e454909150620040eb906001600160a01b03168262003683565b62000b7d620040f962000f6c565b6200301b838562004bb3565b60e4546000906001600160a01b03166200412157506000919050565b620186a060e9548362004135919062004bcd565b6200153f919062004c05565b60006200414e82620036a6565b62004162670de0b6b3a76400008662004bcd565b6200416e919062004c05565b905062000cec8284838762003c38565b60ec5480156200418f578062004193565b61c3505b60ea5490915060ff161562000b7d576000620182b88310620041d157620186a08314620041c457620182b8620041c9565b620186a05b9050620041e5565b81831115620041e2575081620041e5565b50805b620186a0620041f5848362004bcd565b62004201919062004c05565b60da55505050565b801562000d6b5760405163ea8e4eb560e01b815260040160405180910390fd5b600062004280826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620046d39092919063ffffffff16565b9050805160001480620042a4575080806020019051810190620042a4919062004c33565b620019bf5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401620010e2565b6000670de0b6b3a76400006200431b8362000ffe565b62004326846200398a565b62004135919062004bcd565b6000670de0b6b3a76400006200431b83620036a6565b60335460ff1662000d845760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401620010e2565b60335460ff161562000d845760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401620010e2565b600054610100900460ff16620044055760405162461bcd60e51b8152600401620010e2906200506a565b6033805460ff19169055565b600054610100900460ff166200443b5760405162461bcd60e51b8152600401620010e2906200506a565b62000d84620046e4565b600054610100900460ff166200446f5760405162461bcd60e51b8152600401620010e2906200506a565b62000d8462004719565b60608282604051602001620044909291906200510c565b604051602081830303815290604052905092915050565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015620044f8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200451e919062004c53565b9050620015098463095ea7b360e01b856200453a868662004c6d565b60405160240162002ceb92919062004f27565b60006200455962004393565b8262004565576200153f565b6200457083620039cb565b6200457a62003a0d565b60cf546001600160a01b0316600062004593826200376f565b9050620045a233308762003965565b620045c681620045b2846200376f565b620045be919062004bb3565b338662004141565b9250620045d862002782600162002d23565b60d45460405163b6b55f2560e01b8152600481018790526001600160a01b039091169063b6b55f25906024016020604051808303816000875af115801562004624573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200464a919062004c53565b50505092915050565b6040516001600160a01b0380851660248301528316604482015260648101829052620015099085906323b872dd60e01b9060840162002ceb565b60008061012a5461012254620046a4919062004c6d565b905061011f549150804210156200408857620046c1428262004bb3565b620046cd908362004c6d565b91505090565b606062000be884846000856200474a565b600054610100900460ff166200470e5760405162461bcd60e51b8152600401620010e2906200506a565b62000d8433620030b0565b600054610100900460ff16620047435760405162461bcd60e51b8152600401620010e2906200506a565b6001609755565b606082471015620047ad5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401620010e2565b600080866001600160a01b03168587604051620047cb91906200513f565b60006040518083038185875af1925050503d80600081146200480a576040519150601f19603f3d011682016040523d82523d6000602084013e6200480f565b606091505b509150915062004822878383876200482d565b979650505050505050565b606083156200489e578251620048965762004848856200347d565b620048965760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620010e2565b508162000be8565b62000be88383815115620048b55781518083602001fd5b8060405162461bcd60e51b8152600401620010e291906200515d565b62000d8462005172565b610e0d806200518983390190565b6001600160a01b0391909116815260200190565b801515811462000d6b57600080fd5b6000602082840312156200491f57600080fd5b813562000cec81620048fd565b6001600160a01b038116811462000d6b57600080fd5b600080604083850312156200495657600080fd5b823562004963816200492c565b946020939093013593505050565b6000602082840312156200498457600080fd5b5035919050565b6000602082840312156200499e57600080fd5b813562000cec816200492c565b600080600060608486031215620049c157600080fd5b83359250602084013591506040840135620049dc81620048fd565b809150509250925092565b60008060008060808587031215620049fe57600080fd5b843562004a0b816200492c565b966020860135965060408601359560600135945092505050565b600080600080600080600060e0888a03121562004a4157600080fd5b87359650602088013562004a55816200492c565b9550604088013562004a67816200492c565b9450606088013562004a79816200492c565b9350608088013562004a8b816200492c565b925060a088013562004a9d816200492c565b8092505060c0880135905092959891949750929550565b60008060006060848603121562004aca57600080fd5b505081359360208301359350604090920135919050565b6000806040838503121562004af557600080fd5b82359150602083013562004b09816200492c565b809150509250929050565b6000806000806080858703121562004b2b57600080fd5b5050823594602084013594506040840135936060013592509050565b6000806040838503121562004b5b57600080fd5b50508035926020909101359150565b6000806040838503121562004b7e57600080fd5b823562004b8b816200492c565b9150602083013562004b09816200492c565b634e487b7160e01b600052601160045260246000fd5b60008282101562004bc85762004bc862004b9d565b500390565b600081600019048311821515161562004bea5762004bea62004b9d565b500290565b634e487b7160e01b600052601260045260246000fd5b60008262004c175762004c1762004bef565b500490565b9182526001600160a01b0316602082015260400190565b60006020828403121562004c4657600080fd5b815162000cec81620048fd565b60006020828403121562004c6657600080fd5b5051919050565b6000821982111562004c835762004c8362004b9d565b500190565b60006020828403121562004c9b57600080fd5b815162000cec816200492c565b634e487b7160e01b600052604160045260246000fd5b60005b8381101562004cdb57818101518382015260200162004cc1565b83811115620015095750506000910152565b60006020828403121562004d0057600080fd5b81516001600160401b038082111562004d1857600080fd5b818401915084601f83011262004d2d57600080fd5b81518181111562004d425762004d4262004ca8565b604051601f8201601f19908116603f0116810190838211818310171562004d6d5762004d6d62004ca8565b8160405282815287602084870101111562004d8757600080fd5b6200482283602083016020880162004cbe565b600181815b8085111562004ddb57816000190482111562004dbf5762004dbf62004b9d565b8085161562004dcd57918102915b93841c939080029062004d9f565b509250929050565b60008262004df4575060016200153f565b8162004e03575060006200153f565b816001811462004e1c576002811462004e275762004e47565b60019150506200153f565b60ff84111562004e3b5762004e3b62004b9d565b50506001821b6200153f565b5060208310610133831016604e8410600b841016171562004e6c575081810a6200153f565b62004e78838362004d9a565b806000190482111562004e8f5762004e8f62004b9d565b029392505050565b600062000cec838362004de3565b600080821280156001600160ff1b038490038513161562004eca5762004eca62004b9d565b600160ff1b839003841281161562004ee65762004ee662004b9d565b50500190565b9283526020830191909152604082015260600190565b6000806040838503121562004f1657600080fd5b505080516020909101519092909150565b6001600160a01b03929092168252602082015260400190565b60008083128015600160ff1b85018412161562004f615762004f6162004b9d565b6001600160ff1b038401831381161562004f7f5762004f7f62004b9d565b50500390565b60006001600160ff1b038184138284138082168684048611161562004fae5762004fae62004b9d565b600160ff1b600087128281168783058912161562004fd05762004fd062004b9d565b6000871292508782058712848416161562004fef5762004fef62004b9d565b8785058712818416161562005008576200500862004b9d565b505050929093029392505050565b60008262005028576200502862004bef565b600160ff1b82146000198414161562005045576200504562004b9d565b500590565b6000600160ff1b82141562005063576200506362004b9d565b5060000390565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452620050cf81602086016020860162004cbe565b601f01601f19169290920160200192915050565b604081526000620050f86040830185620050b5565b828103602084015262000c3f8185620050b5565b600083516200512081846020880162004cbe565b8351908301906200513681836020880162004cbe565b01949350505050565b600082516200515381846020870162004cbe565b9190910192915050565b60208152600062000cec6020830184620050b5565b634e487b7160e01b600052605160045260246000fdfe60806040523480156200001157600080fd5b5060405162000e0d38038062000e0d8339810160408190526200003491620001f4565b8151829082906200004d90600390602085019062000081565b5080516200006390600490602084019062000081565b5050600580546001600160a01b03191633179055506200029b915050565b8280546200008f906200025e565b90600052602060002090601f016020900481019282620000b35760008555620000fe565b82601f10620000ce57805160ff1916838001178555620000fe565b82800160010185558215620000fe579182015b82811115620000fe578251825591602001919060010190620000e1565b506200010c92915062000110565b5090565b5b808211156200010c576000815560010162000111565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014f57600080fd5b81516001600160401b03808211156200016c576200016c62000127565b604051601f8301601f19908116603f0116810190828211818310171562000197576200019762000127565b81604052838152602092508683858801011115620001b457600080fd5b600091505b83821015620001d85785820183015181830184015290820190620001b9565b83821115620001ea5760008385830101525b9695505050505050565b600080604083850312156200020857600080fd5b82516001600160401b03808211156200022057600080fd5b6200022e868387016200013d565b935060208501519150808211156200024557600080fd5b5062000254858286016200013d565b9150509250929050565b600181811c908216806200027357607f821691505b602082108114156200029557634e487b7160e01b600052602260045260246000fd5b50919050565b610b6280620002ab6000396000f3fe608060405234801561001057600080fd5b50600436106100ba5760003560e01c806306fdde03146100bf57806307546172146100dd578063095ea7b31461010857806318160ddd1461012b57806323b872dd1461013d578063313ce56714610150578063395093511461015f57806340c10f191461017257806370a082311461018757806395d89b41146101b05780639dc29fac146101b8578063a457c2d7146101cb578063a9059cbb146101de578063dd62ed3e146101f1575b600080fd5b6100c7610204565b6040516100d49190610945565b60405180910390f35b6005546100f0906001600160a01b031681565b6040516001600160a01b0390911681526020016100d4565b61011b6101163660046109b6565b610296565b60405190151581526020016100d4565b6002545b6040519081526020016100d4565b61011b61014b3660046109e0565b6102ae565b604051601281526020016100d4565b61011b61016d3660046109b6565b6102d2565b6101856101803660046109b6565b6102f4565b005b61012f610195366004610a1c565b6001600160a01b031660009081526020819052604090205490565b6100c7610358565b6101856101c63660046109b6565b610367565b61011b6101d93660046109b6565b61039b565b61011b6101ec3660046109b6565b610416565b61012f6101ff366004610a3e565b610424565b60606003805461021390610a71565b80601f016020809104026020016040519081016040528092919081815260200182805461023f90610a71565b801561028c5780601f106102615761010080835404028352916020019161028c565b820191906000526020600020905b81548152906001019060200180831161026f57829003601f168201915b5050505050905090565b6000336102a481858561044f565b5060019392505050565b6000336102bc858285610574565b6102c78585856105ee565b506001949350505050565b6000336102a48185856102e58383610424565b6102ef9190610ac2565b61044f565b6005546001600160a01b031633146103275760405162461bcd60e51b815260040161031e90610ada565b60405180910390fd5b60025461034a5761033b60016103e8610780565b6103476103e882610af5565b90505b6103548282610780565b5050565b60606004805461021390610a71565b6005546001600160a01b031633146103915760405162461bcd60e51b815260040161031e90610ada565b610354828261082d565b600033816103a98286610424565b9050838110156104095760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161031e565b6102c7828686840361044f565b6000336102a48185856105ee565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104b15760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161031e565b6001600160a01b0382166105125760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161031e565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60006105808484610424565b905060001981146105e857818110156105db5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161031e565b6105e8848484840361044f565b50505050565b6001600160a01b0383166106525760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161031e565b6001600160a01b0382166106b45760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161031e565b6001600160a01b0383166000908152602081905260409020548181101561072c5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161031e565b6001600160a01b0384811660008181526020818152604080832087870390559387168083529184902080548701905592518581529092600080516020610b0d833981519152910160405180910390a36105e8565b6001600160a01b0382166107d65760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161031e565b80600260008282546107e89190610ac2565b90915550506001600160a01b03821660008181526020818152604080832080548601905551848152600080516020610b0d833981519152910160405180910390a35050565b6001600160a01b03821661088d5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161031e565b6001600160a01b038216600090815260208190526040902054818110156109015760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161031e565b6001600160a01b038316600081815260208181526040808320868603905560028054879003905551858152919291600080516020610b0d8339815191529101610567565b600060208083528351808285015260005b8181101561097257858101830151858201604001528201610956565b81811115610984576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146109b157600080fd5b919050565b600080604083850312156109c957600080fd5b6109d28361099a565b946020939093013593505050565b6000806000606084860312156109f557600080fd5b6109fe8461099a565b9250610a0c6020850161099a565b9150604084013590509250925092565b600060208284031215610a2e57600080fd5b610a378261099a565b9392505050565b60008060408385031215610a5157600080fd5b610a5a8361099a565b9150610a686020840161099a565b90509250929050565b600181811c90821680610a8557607f821691505b60208210811415610aa657634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610ad557610ad5610aac565b500190565b6020808252600190820152601b60f91b604082015260600190565b600082821015610b0757610b07610aac565b50039056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122016ad045cd256bbeefe5c1c4ac397061aa6870f2735b3206f6890eabe4f7c209a64736f6c634300080a0033a2646970667358221220c383643f2b5941805ca3369f969c41f5f2a8a77a118ab47dafc363d19833b8e064736f6c634300080a0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"libraries":{},"optimizer":{"enabled":true,"runs":1},"outputSelection":{"*":{"":["*"],"*":["*"]}}},"optimization_runs":1,"sourcify_repo_url":null,"decoded_constructor_args":null,"compiler_version":"v0.8.10+commit.fc410830","is_verified_via_verifier_alliance":false,"verified_at":"2026-06-24T13:57:41.670428Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x608060405234801561001057600080fd5b5060cf80546001600160a01b0319166001179055615fcb80620000346000396000f3fe60806040523480156200001157600080fd5b5060043610620004ba5760003560e01c806301d22ccd14620004bf5780630553c2e714620004eb57806306a9a8bf1462000505578063085a2b78146200050f578063088f4b7814620005195780631072cbea146200053257806312361ac214620005495780631441a5a914620005535780631533c31e146200056c5780631a7e0ce514620005835780632544e84114620005a257806325cdd86014620005ad57806329811ee514620005b75780632c2a7ca414620005ce5780632e02cd5e14620005d85780632e2452ab14620005ef57806333986ffa14620005fd57806333f0f80014620006075780633403c2fc1462000612578063387af1bd146200061c5780633f4ba83a1462000630578063400f7d32146200063a578063408f3a30146200064457806340a2029e146200065b57806340bd61091462000672578063435d44d9146200067c57806343848aed146200069357806344966ba0146200069e578063452a932014620006b2578063494347e714620006c65780634da4f60314620006d05780634ff0876a14620006e4578063514b6dbd14620006ef57806355c70701146200070657806358cdd22b146200071b5780635b4a3462146200072f5780635c975abb14620007465780635f0b472a146200075257806362adade514620007615780636373ea69146200076b578063655c9a5314620007755780636736d616146200078057806369e25ec114620007975780636bd7b30114620007ac5780636c4321eb14620007bb5780636d90a39c14620007d0578063715018a614620007de578063734d828714620007e8578063747efea114620007f257806375d1497b146200080657806381f5ae7e14620008115780638260dbba146200081b57806383975b6714620008265780638456cb5914620008305780638a0dac4a146200083a5780638da5cb5b146200085157806391b900ef146200085b5780639290d427146200087257806392b29be314620008895780639616423614620008935780639638529c14620008a7578063991052b714620008be5780639a4d360814620008c85780639d3ef4b214620008df5780639ed9de9414620008f4578063a219d2181462000910578063a2454e551462000927578063a27eccc1146200093e578063a2c8b1771462000948578063a4d66daf1462000952578063a6f7f5d6146200095c578063a8c62e761462000966578063b3f00674146200097a578063b450dfce146200098e578063b9ed206914620009a5578063bc063e1a14620009bc578063c5c7509814620009c6578063c61e3faa14620009d5578063c88e844714620009ec578063c9aba3561462000a03578063ccc143b81462000a13578063cfa565671462000a2a578063d48099ad1462000a34578063d636b05f1462000a4b578063dc82697c1462000a56578063ddca3f431462000a60578063dee7c2cb1462000a6a578063dfd5b1c91462000a81578063dfefc7f81462000a8c578063e2988e6e1462000a97578063e3e393681462000aa2578063e70875ad1462000ab6578063edd636fb1462000acd578063ef191b7f1462000ad7578063f2fde38b1462000aee578063fa69d1771462000b05578063fc0c546a1462000b1c578063fe81a0241462000b30575b600080fd5b60d254620004d3906001600160a01b031681565b604051620004e29190620048e9565b60405180910390f35b620004f661012a5481565b604051908152602001620004e2565b620004f660ed5481565b620004f660da5481565b620005306200052a3660046200490c565b62000b3a565b005b620005306200054336600462004942565b62000b57565b620004f660dc5481565b60e854620004d39061010090046001600160a01b031681565b620005306200057d36600462004971565b62000b81565b60ea54620005919060ff1681565b6040519015158152602001620004e2565b620004f66101245481565b620004f662000b90565b620004f6620005c83660046200498b565b62000ba3565b620004f660ec5481565b62000591620005e93660046200498b565b62000c55565b60f054620005919060ff1681565b6200053062000cf3565b620004f66101255481565b6200053062000d6e565b60ca54620004d3906001600160a01b031681565b6200053062000d86565b620004f660dd5481565b620005306200065536600462004971565b62000d9a565b620005306200066c366004620049ab565b62000da9565b620004f660ee5481565b620005306200068d36600462004971565b62000deb565b620004f66101275481565b60d654620004d3906001600160a01b031681565b60d054620004d3906001600160a01b031681565b6200053062000e0a565b61011e546200059190610100900460ff1681565b620004f661011f5481565b62000530620007003660046200490c565b62000e28565b60d3546200059190600160a01b900460ff1681565b610128546200059190610100900460ff1681565b62000530620007403660046200490c565b62000e57565b60335460ff1662000591565b61012d54620005919060ff1681565b620004f660de5481565b620004f660e95481565b620004f66101265481565b62000530620007913660046200490c565b62000e75565b61012854620005919062010000900460ff1681565b61012854620005919060ff1681565b61011e54620005919062010000900460ff1681565b60e854620005919060ff1681565b6200053062000eb5565b620004f660e15481565b60d554620004d3906001600160a01b031681565b620004f66101225481565b620004f660cc5481565b620004f66101205481565b6200053062000ecb565b6200053062000f24565b620005306200084b3660046200498b565b62000f38565b620004d362000f6c565b620005306200086c366004620049e7565b62000f7b565b620004f6620008833660046200498b565b62000ffe565b620004f660e25481565b61012d546200059190610100900460ff1681565b62000530620008b836600462004a25565b6200103c565b6200053062001494565b62000530620008d936600462004971565b6200150f565b60d3546200059190600160a81b900460ff1681565b61012854620004d390630100000090046001600160a01b031681565b620004f6620009213660046200498b565b62001532565b620005306200093836600462004942565b62001545565b620004f660d15481565b6200053062001581565b620004f660c95481565b620004f660f15481565b60d454620004d3906001600160a01b031681565b60e454620004d3906001600160a01b031681565b620004f66200099f36600462004971565b62001967565b62000530620009b636600462004ab4565b62001983565b620004f6614e2081565b61011e54620005919060ff1681565b620004f6620009e636600462004ae1565b620019c4565b62000530620009fd36600462004b14565b62001c71565b620004f6670de0b6b3a764000081565b620004f662000a2436600462004ae1565b62001d27565b620005306200201f565b6200053062000a4536600462004b47565b6200214f565b620004f66101295481565b620004f6620029e1565b620004f660e35481565b6200053062000a7b36600462004ae1565b62002a2e565b620004f6620186a081565b620004f66101235481565b620004f66101215481565b60d754620004d3906001600160a01b031681565b620004f662000ac736600462004971565b62002b59565b620004f660e65481565b620004f662000ae836600462004b6a565b62002b75565b6200053062000aff3660046200498b565b62002bee565b6200053062000b1636600462004b47565b62002c6a565b60cf54620004d3906001600160a01b031681565b620004f660df5481565b62000b4462002ca9565b60ea805460ff1916911515919091179055565b62000b6162002ca9565b60ca5462000b7d906001600160a01b0384811691168362002cc9565b5050565b62000b8b62002ca9565b60ee55565b600062000b9e600062002d23565b905090565b60008062000bb2600062002d23565b9050600062000bc062002dad565b90508162000bf05760d6546001600160a01b0385811691161462000be5578062000be8565b60005b949350505050565b60da5460d6546001600160a01b0386811691161462000c485762000c1883620186a062004bb3565b62000c2782620186a062004bb3565b62000c33908462004bcd565b62000c3f919062004c05565b95945050505050565b8262000c33828462004bcd565b61012854600090630100000090046001600160a01b031680158062000cec57506101295460405163043bb58960e51b81526001600160a01b03831691638776b1209162000ca89190879060040162004c1c565b602060405180830381865afa15801562000cc6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000cec919062004c33565b9392505050565b60d45460405163370a95eb60e21b81526001600160a01b039091169063dc2a57ac9062000d25903390600401620048e9565b6020604051808303816000875af115801562000d45573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000d6b919062004c53565b50565b62000d7862002e1e565b62000d84600062002e60565b565b62000d9062002e1e565b62000d8462002ead565b62000da462002ca9565b60c955565b62000db362002efd565b61011e5462000dc59060ff1662002fb8565b610120929092556101255561012880549115156101000261ff0019909216919091179055565b62000df562002ca9565b62000d6b620186a08260ec8190551162002fd8565b62000e1462002e1e565b62000e1e62002ff8565b62000d8462003021565b62000e3262002ca9565b61011e5462000e449060ff1662002fb8565b60f0805460ff1916911515919091179055565b62000e6162002efd565b61012d805460ff1916911515919091179055565b62000e7f62002ca9565b62000e9a8115801562000e94575060f05460ff165b62002fb8565b61012d80549115156101000261ff0019909216919091179055565b62000ebf6200304d565b62000d846000620030b0565b62000ed562002ca9565b6101285462000eed9062010000900460ff1662002fb8565b60335460ff161562000f035762000f0362002ead565b61011e805462ffff0019166201010017905560d3805460ff60b81b19169055565b62000f2e62002e1e565b62000d8462003102565b62000f4262002ca9565b60d080546001600160a01b0319166001600160a01b03831690811790915562000d6b901562003142565b6065546001600160a01b031690565b62000f8562002ca9565b62000fbb614e2084118062000f9c5750620186a083115b8062000fb5575062000fb2600a614e2062004c05565b82115b62002fd8565b60e480546001600160a01b0319166001600160a01b03861690811790915562000fe5901562003142565b62000fef62003162565b60e39290925560e95560f15550565b600062001035826200100f6200319d565b60df5460de5462001021919062004c6d565b6200102c86620031e2565b60da546200320c565b5092915050565b600054610100900460ff16158080156200105d5750600054600160ff909116105b806200108257506200106f306200347d565b15801562001082575060005460ff166001145b620010eb5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156200110f576000805461ff0019166101001790555b60cf546001600160a01b031615620011395760405162dc149f60e41b815260040160405180910390fd5b620011616001600160a01b03841615806200115b57506001600160a01b038816155b62003142565b62001171620186a0831162002fd8565b6200117b6200348c565b62001188888787620034c0565b6000836001600160a01b031663747efea16040518163ffffffff1660e01b8152600401602060405180830381865afa158015620011c9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011ef919062004c88565b90506000816001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001232573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200125c919081019062004ced565b9050620012a36040518060400160405280600781526020016602830b932ba37960cd1b815250604051806040016040528060018152602001600760fc1b8152508362003526565b60d660006101000a8154816001600160a01b0302191690836001600160a01b03160217905550620013146040518060400160405280600a81526020016902830b932ba37902121160b51b815250604051806040016040528060048152602001637042425f60e01b8152508362003526565b60d780546001600160a01b03199081166001600160a01b039384161790915560cf805482168c841690811790915560d48054831689851617905560d5805490921692851692909217905560da8590556040805163313ce56760e01b815290516000929163313ce5679160048083019260209291908290030181865afa158015620013a2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620013c8919062004c53565b620013d590600a62004e97565b60d181905560dc81905560dd8190559050620013f28a8762003581565b620013fe838762003581565b60d080546001600160a01b0319166001600160a01b038a1617905560ea805460ff1916600117905561c35060ec554260cc5561138860ed556200144062003599565b50505080156200148a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b61012854620014a79060ff161562002fb8565b60d4546040516347e9887560e11b81526001600160a01b0390911690638fd310ea90620014d9903390600401620048e9565b600060405180830381600087803b158015620014f457600080fd5b505af115801562001509573d6000803e3d6000fd5b50505050565b6200151d3330141562002fb8565b62000d6b6200152b62003612565b8262003683565b60006200153f82620036a6565b92915050565b6200154f62002efd565b61012880546001600160a01b039093166301000000026301000000600160b81b03199093169290921790915561012955565b6200158b62002efd565b61011f5461012a5461012254620015b891620015a79162004c6d565b42108062000e945750811562002fb8565b620015c2620036e7565b620015cc62002ff8565b61011e805460ff19166001179055620015e462003102565b61011e805462ffff001916905560d45461012c54610126546001600160a01b03909216916200161c62001616620029e1565b6200370d565b62001628919062004ea5565b62001634919062004ea5565b61012155600061012c556200164a824262004c6d565b61012255610120546200165e904262004c6d565b610123819055506000816001600160a01b031663efda7e076040518163ffffffff1660e01b8152600401602060405180830381865afa158015620016a6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620016cc919062004c53565b61012d54909150600090610100900460ff16620016fa578161012754620016f4919062004c6d565b620016fc565b815b9050801562001765576040516001625a42ed60e11b03198152600481018290526001600160a01b0384169063ff4b7a2690602401600060405180830381600087803b1580156200174b57600080fd5b505af115801562001760573d6000803e3d6000fd5b505050505b60006200177162003724565b60cf549091506000906200178e906001600160a01b03166200376f565b90506000856001600160a01b031663a9a949686040518163ffffffff1660e01b8152600401602060405180830381865afa158015620017d1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620017f7919062004c53565b90508183111562001872576040516303c96c4560e61b8152600481018390526001600160a01b0387169063f25b114090602401600060405180830381600087803b1580156200184557600080fd5b505af11580156200185a573d6000803e3d6000fd5b505050506200186981620037e4565b50505050505050565b6040516303c96c4560e61b8152600481018490526001600160a01b0387169063f25b114090602401600060405180830381600087803b158015620018b557600080fd5b505af1158015620018ca573d6000803e3d6000fd5b5050610128805460ff191660011790555060009050620018eb848462004bb3565b604051631349a6c160e31b8152600481018290529091503090639a4d360890602401600060405180830381600087803b1580156200192857600080fd5b505af19250505080156200193a575060015b6200195c576200194b878262003683565b62001956816200385f565b6200148a565b6200148a82620037e4565b60d6546000906200153f9083906001600160a01b031662003934565b620019913330141562002fb8565b620019bf6200199f62003612565b3083620019ad868862004c6d565b620019b9919062004c6d565b62003965565b505050565b61012d5460009062001a5a9060ff1680620019e1575060f05460ff165b80620019ef575060ea5460ff165b80620019ff575061011e5460ff16155b8062001a0e5750610122544210155b8062001a41575060d6546001600160a01b038481169116148062001a3f575060d7546001600160a01b038481169116145b155b8062000e94575062001a533362000c55565b1562002fb8565b8262001a66576200153f565b600062001a73836200398a565b905062001a81811562002fb8565b62001a8b62002ff8565b62001a9684620039cb565b62001aa062003a0d565b62001aad33308662003965565b61012a546101225460009062001ac590429062004bb3565b905060008261011f5462001ada919062004c6d565b62001ae6848462004c6d565b62001af1896200370d565b62001afd919062004bcd565b62001b09919062004c05565b61012154610126549192509060008183111562001b615762001b5e62001b5762001b34848662004bb3565b62001b5160df5460de5462001b4a919062004c6d565b8962003b6b565b62003b9d565b8a62003be7565b90505b600062001b7f62001b788662001b518e8a62003b6b565b8b62003be7565b905060008262001b8f8c620031e2565b62001b9b919062004c6d565b9050808962001bab848f62004c6d565b62001bb7919062004bcd565b62001bc3919062004c05565b995062001bd38b338c8f62003c38565b85610121600082825462001be8919062004c6d565b909155505060d454604051633ec701eb60e01b8152600481018e90526001600160a01b0390911690633ec701eb90602401600060405180830381600087803b15801562001c3457600080fd5b505af115801562001c49573d6000803e3d6000fd5b5050505062001c6262001c5b62003612565b8d62003683565b50505050505050505092915050565b62001c7d84846200214f565b801580159062001c9757506101285462010000900460ff16155b1562001d075760d454604051633e81a73360e01b8152600481018390526001600160a01b0390911690633e81a73390602401600060405180830381600087803b15801562001ce457600080fd5b505af115801562001cf9573d6000803e3d6000fd5b5050505062001d0762003021565b62001d168261012a5462002c6a565b62001d218462003cf4565b62001509565b60d65460009062001dca906001600160a01b0384811691161480159062001d5c575060d7546001600160a01b03848116911614155b8062001d8a575061011e54610100900460ff1615801562001d8a575060d6546001600160a01b038481169116145b8062001a41575061011e5462010000900460ff1615801562001a41575060d7546001600160a01b038481169116148062000e94575062001a533362000c55565b62001dd462002ff8565b62001dde62003a0d565b60d4546001600160a01b03168362001dff5762001dfc338462003d9f565b93505b62001e0b848462003e14565b61012854909250610100900460ff1615801562001e2b575060f05460ff16155b1562001f295761012554816001600160a01b031663d7bff5386040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001e74573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001e9a919062004c53565b62001ea6919062004c6d565b61012454111562001f2957604051630a198c7f60e21b81526001600160a01b0382169063286631fc9062001ee1908590339060040162004c1c565b600060405180830381600087803b15801562001efc57600080fd5b505af115801562001f11573d6000803e3d6000fd5b5050505062001f2284838562003e36565b506200153f565b8160008062001f39838762003efd565b91509150600062001f4b848462003fe8565b90508062001f5a848662004c6d565b62001f66919062004bb3565b955080610126600082825462001f7d919062004c6d565b925050819055508161012c600082825462001f99919062004ea5565b909155505060405163f16c6bf160e01b815260048101879052336024820152604481018590526001600160a01b0386169063f16c6bf190606401600060405180830381600087803b15801562001fee57600080fd5b505af115801562002003573d6000803e3d6000fd5b505050506200201488858962003e36565b505050505092915050565b6200202962002efd565b60f054620020579060ff168062002044575061011e5460ff16155b8062000e94575061012354421062002fb8565b60d4546001600160a01b031660006200206f62003724565b60405163b9ed206960e01b8152909150309063b9ed2069906200209c906000908190869060040162004eec565b600060405180830381600087803b158015620020b757600080fd5b505af1925050508015620020c9575060015b620020d95762000b7d816200385f565b80156200213d576040516303c96c4560e61b8152600481018290526001600160a01b0383169063f25b114090602401600060405180830381600087803b1580156200212357600080fd5b505af115801562002138573d6000803e3d6000fd5b505050505b610128805460ff191660011790555050565b6200215962002efd565b62002163620036e7565b60d4546101265461011e546001600160a01b0390921691620021cb9060ff1615806200219157506101225442105b80620021a55750620021a262003724565b15155b8062000e94575060018411801562000e9457508184108062000e94575084151562002fb8565b620021d562002ff8565b60018314620021e48462004023565b60405163bb42b77360e01b8152600481018290529094506000906001600160a01b0385169063bb42b7739060240160408051808303816000875af115801562002231573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002257919062004f02565b80945081925050506000846001600160a01b031663a9a949686040518163ffffffff1660e01b8152600401602060405180830381865afa158015620022a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620022c6919062004c53565b9050600083156200230f5760cf54620022e8906001600160a01b03166200376f565b620022f2620029e1565b620022fe919062004bb3565b90506200230c818462004c6d565b92505b6000846200231e57836200232a565b6200232a828562004bb3565b61012d54909150600090610100900460ff16801562002347575085155b90506000816200235857856200235b565b60005b90508180156200236b575060018a115b1562002415576000896001600160a01b03166392093b366040518163ffffffff1660e01b8152600401602060405180830381865afa158015620023b2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620023d8919062004c53565b905062002413811580159062000e94575089620023ff620023f8620029e1565b846200408c565b6200240b919062004c6d565b851162002fb8565b505b600062002423868362004c6d565b60f05490915060ff1615620024e0576200243c62003612565b604051639b8e712b60e01b81526004810183905289151560248201526001600160a01b039190911690639b8e712b906044016020604051808303816000875af11580156200248e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620024b4919062004c33565b620024e057610128805460ff19166001179055620024d2816200385f565b505050505050505050505050565b620024ea62003162565b60405163b9ed206960e01b8152309063b9ed206990620025149085908a9060009060040162004eec565b600060405180830381600087803b1580156200252f57600080fd5b505af192505050801562002541575060015b6200257057610128805460ff191660011790556200256a62002564878962004c6d565b6200385f565b620024d2565b8515620025d457604051638b80c89d60e01b8152600481018790526001600160a01b038b1690638b80c89d90602401600060405180830381600087803b158015620025ba57600080fd5b505af1158015620025cf573d6000803e3d6000fd5b505050505b828015620025e4575060f05460ff165b156200264957620025f462003612565b6001600160a01b0316632512529b6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156200262f57600080fd5b505af115801562002644573d6000803e3d6000fd5b505050505b826200265a576200265a89620040c3565b87156200266d576200266d8a8662003683565b8215620026f2578315620026d857604051633ec701eb60e01b8152600481018590526001600160a01b038b1690633ec701eb90602401600060405180830381600087803b158015620026be57600080fd5b505af1158015620026d3573d6000803e3d6000fd5b505050505b8860e16000828254620026ec919062004c6d565b90915550505b620026fc62003a0d565b60e1548315620027905780156200278a5760006200271a8262004105565b90508015620027455760e45460d654620027439183916001600160a01b03918216911662004141565b505b6200277162002755828462004bb3565b6200275f62000f6c565b60d6546001600160a01b031662004141565b506200278862002782600162002d23565b6200417e565b505b620027ca565b60008a8611620027a2576000620027ae565b620027ae8b8762004bb3565b905080821115620027bd578091505b620027c882620040c3565b505b8060e16000828254620027de919062004bb3565b909155506000905084620027f3578a620027f6565b60005b62002802908362004c6d565b905060008187116200281657600062002822565b62002822828862004bb3565b61012781905590506001600160a01b038d1663b6b55f258762002846578262002849565b60005b6040518263ffffffff1660e01b81526004016200286891815260200190565b6020604051808303816000875af115801562002888573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620028ae919062004c53565b508c6001600160a01b031663d7bff5386040518163ffffffff1660e01b8152600401602060405180830381865afa158015620028ee573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002914919062004c53565b61012455620029238f62003cf4565b61011e805460ff191690556000610121819055610126556200294462002ead565b61011e805462ffff00191662010100179055610128805460ff19168c158015919091179091556200298c57610128805461ff001916610100179055600061011f819055610122555b7ff66f28b40975dbb933913542c7e6a0f50a1d0f20aa74ea6e0efe65ab616323ec620029b9898c62004bb3565b60408051918252602082018590520160405180910390a1505050505050505050505050505050565b60e15460cf5460009190620029ff906001600160a01b03166200376f565b60d55462002a16906001600160a01b03166200376f565b62002a22919062004c6d565b62000b9e919062004bb3565b62002a5d3362002a3d62003612565b6001600160a01b031614158062000e94575061011e5460ff161562002fb8565b62002a6762002ff8565b600062002a75838362003e14565b905060008062002a86838562003efd565b91509150600061011f5490508061012a548262002aa4919062004c6d565b62002ab0848662004ea5565b62002abc919062004bcd565b62002ac8919062004c05565b925062002ad786858762003e36565b60d454604051633e81a73360e01b8152600481018690526001600160a01b0390911690633e81a73390602401600060405180830381600087803b15801562002b1e57600080fd5b505af115801562002b33573d6000803e3d6000fd5b5050505082610121600082825462002b4c919062004bb3565b9091555050505050505050565b60d7546000906200153f9083906001600160a01b031662003934565b600062002b8e62002b87848462003d9f565b8362003e14565b905062002bab8160cc544262002ba5919062004bb3565b62003b6b565b62002bb7908262004bb3565b9050600062002bc7828462003efd565b50905062002bd6828262003fe8565b62002be2828462004c6d565b62000be8919062004bb3565b62002bf86200304d565b6001600160a01b03811662002c5f5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620010e2565b62000d6b81620030b0565b62002c7462002efd565b61011e5462002c9c9060ff168062002c8a575082155b8062000e94575061011f541562002fb8565b61011f9190915561012a55565b62000d843362002cb862000f6c565b6001600160a01b0316141562004209565b620019bf8363a9059cbb60e01b848460405160240162002ceb92919062004f27565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915262004229565b6000620048d18262002d39576200430562002d3e565b620043325b60d65490915060009062002d5e906001600160a01b031663ffffffff8416565b60d75490915060009062002d7e906001600160a01b031663ffffffff8516565b62002d8a908362004c6d565b90508062002d9d57506000949350505050565b8062000c33620186a08462004bcd565b60d45460408051632116f20160e21b815290516000926001600160a01b03169163845bc8049160048083019260209291908290030181865afa15801562002df8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000b9e919062004c53565b60d05462000d84906001600160a01b0316331480159062002e5a575062002e4462000f6c565b6001600160a01b0316336001600160a01b031614155b62004209565b60335460ff1662002e755762002e7562003102565b61011e805462ff000019921515610100029290921662ffff001990921691909117905560d3805460ff60b81b1916600160b81b179055565b62002eb762004348565b6033805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405162002ef39190620048e9565b60405180910390a1565b62000d8462002f0b62000f6c565b6001600160a01b0316336001600160a01b03161415801562000e94575060d460009054906101000a90046001600160a01b03166001600160a01b031663481c6a756040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002f7c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002fa2919062004c88565b6001600160a01b0316336001600160a01b031614155b801562000d6b57604051631eb49d6d60e11b815260040160405180910390fd5b801562000d6b5760405163fd7850ad60e01b815260040160405180910390fd5b60e45460cf5462000d84916001600160a01b03908116916200301b91166200376f565b62003683565b60d3805460ff60b81b1916600160b81b1790556200303e62003a0d565b60d3805460ff60b81b19169055565b336200305862000f6c565b6001600160a01b03161462000d845760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620010e2565b606580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6200310c62004393565b6033805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25862002ee43390565b801562000d6b576040516321e7594160e21b815260040160405180910390fd5b6200317f620031706200319d565b60cc5462002ba5904262004bb3565b60e1600082825462003192919062004c6d565b90915550504260cc55565b60d5546000908190620031b9906001600160a01b03166200376f565b60e154909150808211620031cf576000620031db565b620031db818362004bb3565b9250505090565b60d6546000906001600160a01b03838116911614620032045760df546200153f565b505060de5490565b60008060006200321c886200398a565b90508515806200322a575080155b156200323f57505060d1549050600062003473565b60006200324d878962004f40565b9050806200326e576200326089620036a6565b600093509350505062003473565b6000811315620032a757620186a060e354826200328c919062004f85565b62003298919062005016565b620032a4908262004f40565b90505b60d65460d7546001600160a01b0391821691908116908b168214620032d981620032d257836200398a565b826200398a565b620032e7578395506200343d565b60008413156200333f576000620186a0620033038a8262004bb3565b6200330f908762004f85565b6200331b919062005016565b9050816200332a578062003336565b62003336818662004f40565b9650506200343d565b620186a08a60ee5462003353919062004bcd565b6200335f919062004c05565b6200336a856200504a565b11620033c35760df5460de546000906200338690839062004c6d565b62003392838862004f85565b6200339e919062005016565b905082620033ad5780620033b9565b620033b9818762004f40565b975050506200343d565b600081620033d25789620033de565b620033de8a8c62004bb3565b90506000620033ee868362004ea5565b905060008113156200341257826200340757856200340a565b60005b97506200343a565b826200343657600062003425836200504a565b985098505050505050505062003473565b8097505b50505b84670de0b6b3a764000062003453888c62004ea5565b6200345f919062004bcd565b6200346b919062004c05565b965050505050505b9550959350505050565b6001600160a01b03163b151590565b600054610100900460ff16620034b65760405162461bcd60e51b8152600401620010e2906200506a565b62000d84620043db565b620034e76001600160a01b03831615806200115b57506001600160a01b0382161562003142565b620034f162004411565b620034fb62004445565b60c983905560ca80546001600160a01b0319166001600160a01b038416179055620019bf8162002bee565b600062003534848362004479565b62003540848462004479565b6040516200354e90620048db565b6200355b929190620050e3565b604051809103906000f08015801562003578573d6000803e3d6000fd5b50949350505050565b62000b7d6001600160a01b03831682600019620044a7565b620186a060ee5560ea805460ff1916905562278d0061011f556206978061012a819055620035c8904262004bb3565b6101225561011e80546201010062ffff0019909116179055610128805461ff00191661010017905561012d805460ff1916600117905562000d846200360c62002dad565b62003cf4565b60d45460408051637df1f1b960e01b815290516000926001600160a01b031691637df1f1b99160048083019260209291908290030181865afa1580156200365d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000b9e919062004c88565b806200368d575050565b60cf5462000b7d906001600160a01b0316838362002cc9565b6000620036b3826200398a565b620036c057505060d15490565b60d6546001600160a01b03838116911614620036df5760dd546200153f565b505060dc5490565b60f05462000d849060ff16801562000e94575061012d54610100900460ff161562002fb8565b60006200153f826200371e62002dad565b6200408c565b60d45460408051631e2af12360e31b815290516000926001600160a01b03169163f15789189160048083019260209291908290030181865afa15801562002df8573d6000803e3d6000fd5b6040516370a0823160e01b81526000906001600160a01b038316906370a0823190620037a0903090600401620048e9565b602060405180830381865afa158015620037be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200153f919062004c53565b60f05460ff161562000d6b57620037fa62003612565b6001600160a01b0316631d859d73826040518263ffffffff1660e01b81526004016200382891815260200190565b600060405180830381600087803b1580156200384357600080fd5b505af115801562003858573d6000803e3d6000fd5b5050505050565b610128805462ff000019166201000017905560f05460ff1615620038dc576200388762003612565b6001600160a01b0316636febd5436040518163ffffffff1660e01b8152600401600060405180830381600087803b158015620038c257600080fd5b505af1158015620038d7573d6000803e3d6000fd5b505050505b60335460ff16620038f157620038f162003102565b61011e805462ffffff191690556040518181527fddeda4ec7ef5a5761f0a329088482bf17d717987d67aaad5a3c4535ab7da29099060200160405180910390a150565b60006200394062004393565b6200394f62001a533362000c55565b6200395962002ff8565b62000cec83836200454d565b806200397057505050565b60cf54620019bf906001600160a01b031684848462004653565b6000816001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620037be573d6000803e3d6000fd5b60c954801562000b7d578082620039e1620029e1565b620039ed919062004c6d565b111562000b7d57604051630d45dcb760e11b815260040160405180910390fd5b62003a1762003162565b60de5460df54600062003a2b828462004c6d565b9050600062003a39620029e1565b60da549091508282111562003a8d5760e354620186a09062003a5c858562004bb3565b62003a68919062004bcd565b62003a74919062004c05565b60e1600082825462003a87919062004c6d565b90915550505b60d654600090819062003aad906001600160a01b031685878a876200320c565b60d7549193509150600090819062003ad2906001600160a01b031687898b896200320c565b909250905062003ae3838a62004ea5565b60de5560008112801562003b0157508762003afe826200504a565b12155b1562003b495760d354600160b81b900460ff1662003b325760405163064e30f160e51b815260040160405180910390fd5b600060df5562003b43600162002e60565b62003b59565b62003b55818962004ea5565b60df555b5060dc929092555060dd555050505050565b60006502de413530008260f1548562003b85919062004bcd565b62003b91919062004bcd565b62000cec919062004c05565b600082821062003bad576200153f565b62003bb9828462004bb3565b9250620186a060e3548462003bcf919062004bcd565b62003bdb919062004c05565b62000cec908462004bb3565b60da5460d65460009190620186a0906001600160a01b0385811691161462003c1e5762003c1882620186a062004bb3565b62003c20565b815b62003c2c908662004bcd565b62000be8919062004c05565b6040516340c10f1960e01b81526001600160a01b038516906340c10f199062003c68908690869060040162004f27565b600060405180830381600087803b15801562003c8357600080fd5b505af115801562003c98573d6000803e3d6000fd5b505060d6546001600160a01b0387811691161415915062003cd59050578060de600082825462003cc9919062004c6d565b90915550620015099050565b8060df600082825462003ce9919062004c6d565b909155505050505050565b61011f5460d4546001600160a01b0316635a4f7c5383831562003d41578361012a548562003d23919062004c6d565b62003d2f908762004bcd565b62003d3b919062004c05565b62003d43565b845b6040516001600160e01b031960e085901b16815260048101929092526024820152604401600060405180830381600087803b15801562003d8257600080fd5b505af115801562003d97573d6000803e3d6000fd5b505050505050565b6040516370a0823160e01b81526000906001600160a01b038316906370a082319062003dd0908690600401620048e9565b602060405180830381865afa15801562003dee573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000cec919062004c53565b6000670de0b6b3a764000062003e2a83620036a6565b62003b91908562004bcd565b604051632770a7eb60e21b81526001600160a01b03821690639dc29fac9062003e66903390879060040162004f27565b600060405180830381600087803b15801562003e8157600080fd5b505af115801562003e96573d6000803e3d6000fd5b505060d6546001600160a01b0384811691161415915062003ed39050578160de600082825462003ec7919062004bb3565b9091555062003eed9050565b8160df600082825462003ee7919062004bb3565b90915550505b620019bf62002782600162002d23565b61011f5460009081908062003f13575062003fe1565b61012a54600062003f25828462004c6d565b8362003f34620016166200319d565b62003f40919062004bcd565b62003f4c919062004c05565b9050600062003f5c828862003be7565b9050600062003f6b88620031e2565b9050801562003f93578062003f81838b62004bcd565b62003f8d919062004c05565b62003f96565b60005b9650600062003fa6858762004c6d565b8662003fb28c6200370d565b62003fbe919062004bcd565b62003fca919062004c05565b905062003fd8888262004f40565b96505050505050505b9250929050565b60008062003ffa8462002ba56200468d565b90508281101562000cec5762004011838262003b9d565b6200401d908462004bb3565b62000be8565b60f05460009060ff16156200408857620040406001831162002fb8565b6200404a62003612565b6001600160a01b0316630ceff3da6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620037be573d6000803e3d6000fd5b5090565b6000620040a6670de0b6b3a76400006301e1338062004bcd565b61011f54620040b760648562004c05565b62003b85908662004bcd565b6000620040d08262004105565b60e454909150620040eb906001600160a01b03168262003683565b62000b7d620040f962000f6c565b6200301b838562004bb3565b60e4546000906001600160a01b03166200412157506000919050565b620186a060e9548362004135919062004bcd565b6200153f919062004c05565b60006200414e82620036a6565b62004162670de0b6b3a76400008662004bcd565b6200416e919062004c05565b905062000cec8284838762003c38565b60ec5480156200418f578062004193565b61c3505b60ea5490915060ff161562000b7d576000620182b88310620041d157620186a08314620041c457620182b8620041c9565b620186a05b9050620041e5565b81831115620041e2575081620041e5565b50805b620186a0620041f5848362004bcd565b62004201919062004c05565b60da55505050565b801562000d6b5760405163ea8e4eb560e01b815260040160405180910390fd5b600062004280826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620046d39092919063ffffffff16565b9050805160001480620042a4575080806020019051810190620042a4919062004c33565b620019bf5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401620010e2565b6000670de0b6b3a76400006200431b8362000ffe565b62004326846200398a565b62004135919062004bcd565b6000670de0b6b3a76400006200431b83620036a6565b60335460ff1662000d845760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401620010e2565b60335460ff161562000d845760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401620010e2565b600054610100900460ff16620044055760405162461bcd60e51b8152600401620010e2906200506a565b6033805460ff19169055565b600054610100900460ff166200443b5760405162461bcd60e51b8152600401620010e2906200506a565b62000d84620046e4565b600054610100900460ff166200446f5760405162461bcd60e51b8152600401620010e2906200506a565b62000d8462004719565b60608282604051602001620044909291906200510c565b604051602081830303815290604052905092915050565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015620044f8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200451e919062004c53565b9050620015098463095ea7b360e01b856200453a868662004c6d565b60405160240162002ceb92919062004f27565b60006200455962004393565b8262004565576200153f565b6200457083620039cb565b6200457a62003a0d565b60cf546001600160a01b0316600062004593826200376f565b9050620045a233308762003965565b620045c681620045b2846200376f565b620045be919062004bb3565b338662004141565b9250620045d862002782600162002d23565b60d45460405163b6b55f2560e01b8152600481018790526001600160a01b039091169063b6b55f25906024016020604051808303816000875af115801562004624573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200464a919062004c53565b50505092915050565b6040516001600160a01b0380851660248301528316604482015260648101829052620015099085906323b872dd60e01b9060840162002ceb565b60008061012a5461012254620046a4919062004c6d565b905061011f549150804210156200408857620046c1428262004bb3565b620046cd908362004c6d565b91505090565b606062000be884846000856200474a565b600054610100900460ff166200470e5760405162461bcd60e51b8152600401620010e2906200506a565b62000d8433620030b0565b600054610100900460ff16620047435760405162461bcd60e51b8152600401620010e2906200506a565b6001609755565b606082471015620047ad5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401620010e2565b600080866001600160a01b03168587604051620047cb91906200513f565b60006040518083038185875af1925050503d80600081146200480a576040519150601f19603f3d011682016040523d82523d6000602084013e6200480f565b606091505b509150915062004822878383876200482d565b979650505050505050565b606083156200489e578251620048965762004848856200347d565b620048965760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620010e2565b508162000be8565b62000be88383815115620048b55781518083602001fd5b8060405162461bcd60e51b8152600401620010e291906200515d565b62000d8462005172565b610e0d806200518983390190565b6001600160a01b0391909116815260200190565b801515811462000d6b57600080fd5b6000602082840312156200491f57600080fd5b813562000cec81620048fd565b6001600160a01b038116811462000d6b57600080fd5b600080604083850312156200495657600080fd5b823562004963816200492c565b946020939093013593505050565b6000602082840312156200498457600080fd5b5035919050565b6000602082840312156200499e57600080fd5b813562000cec816200492c565b600080600060608486031215620049c157600080fd5b83359250602084013591506040840135620049dc81620048fd565b809150509250925092565b60008060008060808587031215620049fe57600080fd5b843562004a0b816200492c565b966020860135965060408601359560600135945092505050565b600080600080600080600060e0888a03121562004a4157600080fd5b87359650602088013562004a55816200492c565b9550604088013562004a67816200492c565b9450606088013562004a79816200492c565b9350608088013562004a8b816200492c565b925060a088013562004a9d816200492c565b8092505060c0880135905092959891949750929550565b60008060006060848603121562004aca57600080fd5b505081359360208301359350604090920135919050565b6000806040838503121562004af557600080fd5b82359150602083013562004b09816200492c565b809150509250929050565b6000806000806080858703121562004b2b57600080fd5b5050823594602084013594506040840135936060013592509050565b6000806040838503121562004b5b57600080fd5b50508035926020909101359150565b6000806040838503121562004b7e57600080fd5b823562004b8b816200492c565b9150602083013562004b09816200492c565b634e487b7160e01b600052601160045260246000fd5b60008282101562004bc85762004bc862004b9d565b500390565b600081600019048311821515161562004bea5762004bea62004b9d565b500290565b634e487b7160e01b600052601260045260246000fd5b60008262004c175762004c1762004bef565b500490565b9182526001600160a01b0316602082015260400190565b60006020828403121562004c4657600080fd5b815162000cec81620048fd565b60006020828403121562004c6657600080fd5b5051919050565b6000821982111562004c835762004c8362004b9d565b500190565b60006020828403121562004c9b57600080fd5b815162000cec816200492c565b634e487b7160e01b600052604160045260246000fd5b60005b8381101562004cdb57818101518382015260200162004cc1565b83811115620015095750506000910152565b60006020828403121562004d0057600080fd5b81516001600160401b038082111562004d1857600080fd5b818401915084601f83011262004d2d57600080fd5b81518181111562004d425762004d4262004ca8565b604051601f8201601f19908116603f0116810190838211818310171562004d6d5762004d6d62004ca8565b8160405282815287602084870101111562004d8757600080fd5b6200482283602083016020880162004cbe565b600181815b8085111562004ddb57816000190482111562004dbf5762004dbf62004b9d565b8085161562004dcd57918102915b93841c939080029062004d9f565b509250929050565b60008262004df4575060016200153f565b8162004e03575060006200153f565b816001811462004e1c576002811462004e275762004e47565b60019150506200153f565b60ff84111562004e3b5762004e3b62004b9d565b50506001821b6200153f565b5060208310610133831016604e8410600b841016171562004e6c575081810a6200153f565b62004e78838362004d9a565b806000190482111562004e8f5762004e8f62004b9d565b029392505050565b600062000cec838362004de3565b600080821280156001600160ff1b038490038513161562004eca5762004eca62004b9d565b600160ff1b839003841281161562004ee65762004ee662004b9d565b50500190565b9283526020830191909152604082015260600190565b6000806040838503121562004f1657600080fd5b505080516020909101519092909150565b6001600160a01b03929092168252602082015260400190565b60008083128015600160ff1b85018412161562004f615762004f6162004b9d565b6001600160ff1b038401831381161562004f7f5762004f7f62004b9d565b50500390565b60006001600160ff1b038184138284138082168684048611161562004fae5762004fae62004b9d565b600160ff1b600087128281168783058912161562004fd05762004fd062004b9d565b6000871292508782058712848416161562004fef5762004fef62004b9d565b8785058712818416161562005008576200500862004b9d565b505050929093029392505050565b60008262005028576200502862004bef565b600160ff1b82146000198414161562005045576200504562004b9d565b500590565b6000600160ff1b82141562005063576200506362004b9d565b5060000390565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452620050cf81602086016020860162004cbe565b601f01601f19169290920160200192915050565b604081526000620050f86040830185620050b5565b828103602084015262000c3f8185620050b5565b600083516200512081846020880162004cbe565b8351908301906200513681836020880162004cbe565b01949350505050565b600082516200515381846020870162004cbe565b9190910192915050565b60208152600062000cec6020830184620050b5565b634e487b7160e01b600052605160045260246000fdfe60806040523480156200001157600080fd5b5060405162000e0d38038062000e0d8339810160408190526200003491620001f4565b8151829082906200004d90600390602085019062000081565b5080516200006390600490602084019062000081565b5050600580546001600160a01b03191633179055506200029b915050565b8280546200008f906200025e565b90600052602060002090601f016020900481019282620000b35760008555620000fe565b82601f10620000ce57805160ff1916838001178555620000fe565b82800160010185558215620000fe579182015b82811115620000fe578251825591602001919060010190620000e1565b506200010c92915062000110565b5090565b5b808211156200010c576000815560010162000111565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200014f57600080fd5b81516001600160401b03808211156200016c576200016c62000127565b604051601f8301601f19908116603f0116810190828211818310171562000197576200019762000127565b81604052838152602092508683858801011115620001b457600080fd5b600091505b83821015620001d85785820183015181830184015290820190620001b9565b83821115620001ea5760008385830101525b9695505050505050565b600080604083850312156200020857600080fd5b82516001600160401b03808211156200022057600080fd5b6200022e868387016200013d565b935060208501519150808211156200024557600080fd5b5062000254858286016200013d565b9150509250929050565b600181811c908216806200027357607f821691505b602082108114156200029557634e487b7160e01b600052602260045260246000fd5b50919050565b610b6280620002ab6000396000f3fe608060405234801561001057600080fd5b50600436106100ba5760003560e01c806306fdde03146100bf57806307546172146100dd578063095ea7b31461010857806318160ddd1461012b57806323b872dd1461013d578063313ce56714610150578063395093511461015f57806340c10f191461017257806370a082311461018757806395d89b41146101b05780639dc29fac146101b8578063a457c2d7146101cb578063a9059cbb146101de578063dd62ed3e146101f1575b600080fd5b6100c7610204565b6040516100d49190610945565b60405180910390f35b6005546100f0906001600160a01b031681565b6040516001600160a01b0390911681526020016100d4565b61011b6101163660046109b6565b610296565b60405190151581526020016100d4565b6002545b6040519081526020016100d4565b61011b61014b3660046109e0565b6102ae565b604051601281526020016100d4565b61011b61016d3660046109b6565b6102d2565b6101856101803660046109b6565b6102f4565b005b61012f610195366004610a1c565b6001600160a01b031660009081526020819052604090205490565b6100c7610358565b6101856101c63660046109b6565b610367565b61011b6101d93660046109b6565b61039b565b61011b6101ec3660046109b6565b610416565b61012f6101ff366004610a3e565b610424565b60606003805461021390610a71565b80601f016020809104026020016040519081016040528092919081815260200182805461023f90610a71565b801561028c5780601f106102615761010080835404028352916020019161028c565b820191906000526020600020905b81548152906001019060200180831161026f57829003601f168201915b5050505050905090565b6000336102a481858561044f565b5060019392505050565b6000336102bc858285610574565b6102c78585856105ee565b506001949350505050565b6000336102a48185856102e58383610424565b6102ef9190610ac2565b61044f565b6005546001600160a01b031633146103275760405162461bcd60e51b815260040161031e90610ada565b60405180910390fd5b60025461034a5761033b60016103e8610780565b6103476103e882610af5565b90505b6103548282610780565b5050565b60606004805461021390610a71565b6005546001600160a01b031633146103915760405162461bcd60e51b815260040161031e90610ada565b610354828261082d565b600033816103a98286610424565b9050838110156104095760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161031e565b6102c7828686840361044f565b6000336102a48185856105ee565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166104b15760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161031e565b6001600160a01b0382166105125760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161031e565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60006105808484610424565b905060001981146105e857818110156105db5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161031e565b6105e8848484840361044f565b50505050565b6001600160a01b0383166106525760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161031e565b6001600160a01b0382166106b45760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161031e565b6001600160a01b0383166000908152602081905260409020548181101561072c5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161031e565b6001600160a01b0384811660008181526020818152604080832087870390559387168083529184902080548701905592518581529092600080516020610b0d833981519152910160405180910390a36105e8565b6001600160a01b0382166107d65760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161031e565b80600260008282546107e89190610ac2565b90915550506001600160a01b03821660008181526020818152604080832080548601905551848152600080516020610b0d833981519152910160405180910390a35050565b6001600160a01b03821661088d5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161031e565b6001600160a01b038216600090815260208190526040902054818110156109015760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b606482015260840161031e565b6001600160a01b038316600081815260208181526040808320868603905560028054879003905551858152919291600080516020610b0d8339815191529101610567565b600060208083528351808285015260005b8181101561097257858101830151858201604001528201610956565b81811115610984576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146109b157600080fd5b919050565b600080604083850312156109c957600080fd5b6109d28361099a565b946020939093013593505050565b6000806000606084860312156109f557600080fd5b6109fe8461099a565b9250610a0c6020850161099a565b9150604084013590509250925092565b600060208284031215610a2e57600080fd5b610a378261099a565b9392505050565b60008060408385031215610a5157600080fd5b610a5a8361099a565b9150610a686020840161099a565b90509250929050565b600181811c90821680610a8557607f821691505b60208210811415610aa657634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610ad557610ad5610aac565b500190565b6020808252600190820152601b60f91b604082015260600190565b600082821015610b0757610b07610aac565b50039056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122016ad045cd256bbeefe5c1c4ac397061aa6870f2735b3206f6890eabe4f7c209a64736f6c634300080a0033a2646970667358221220c383643f2b5941805ca3369f969c41f5f2a8a77a118ab47dafc363d19833b8e064736f6c634300080a0033","name":"IdleCDOEpochVariant","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":false,"language":"solidity","evm_version":"default","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"@openzeppelin/contracts/token/ERC20/ERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.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 * For a generic mechanism see {ERC20PresetMinterPauser}.\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 *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n    mapping(address => uint256) private _balances;\n\n    mapping(address => mapping(address => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * All two of these values are immutable: they can only be set once during\n     * construction.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the default value returned by this function, unless\n     * it's overridden.\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual override returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual override returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - the caller must have a balance of at least `amount`.\n     */\n    function transfer(address to, uint256 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _transfer(owner, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `amount` 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 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, amount);\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 `amount`.\n     * - the caller must have allowance for ``from``'s tokens of at least\n     * `amount`.\n     */\n    function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(from, spender, amount);\n        _transfer(from, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, allowance(owner, spender) + addedValue);\n        return true;\n    }\n\n    /**\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `spender` must have allowance for the caller of at least\n     * `subtractedValue`.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        uint256 currentAllowance = allowance(owner, spender);\n        require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n        unchecked {\n            _approve(owner, spender, currentAllowance - subtractedValue);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Moves `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     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `from` must have a balance of at least `amount`.\n     */\n    function _transfer(address from, address to, uint256 amount) internal virtual {\n        require(from != address(0), \"ERC20: transfer from the zero address\");\n        require(to != address(0), \"ERC20: transfer to the zero address\");\n\n        _beforeTokenTransfer(from, to, amount);\n\n        uint256 fromBalance = _balances[from];\n        require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n        unchecked {\n            _balances[from] = fromBalance - amount;\n            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n            // decrementing then incrementing.\n            _balances[to] += amount;\n        }\n\n        emit Transfer(from, to, amount);\n\n        _afterTokenTransfer(from, to, amount);\n    }\n\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function _mint(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: mint to the zero address\");\n\n        _beforeTokenTransfer(address(0), account, amount);\n\n        _totalSupply += amount;\n        unchecked {\n            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n            _balances[account] += amount;\n        }\n        emit Transfer(address(0), account, amount);\n\n        _afterTokenTransfer(address(0), account, amount);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, reducing the\n     * total supply.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens.\n     */\n    function _burn(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: burn from the zero address\");\n\n        _beforeTokenTransfer(account, address(0), amount);\n\n        uint256 accountBalance = _balances[account];\n        require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n        unchecked {\n            _balances[account] = accountBalance - amount;\n            // Overflow not possible: amount <= accountBalance <= totalSupply.\n            _totalSupply -= amount;\n        }\n\n        emit Transfer(account, address(0), amount);\n\n        _afterTokenTransfer(account, address(0), amount);\n    }\n\n    /**\n     * @dev Sets `amount` 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    function _approve(address owner, address spender, uint256 amount) internal virtual {\n        require(owner != address(0), \"ERC20: approve from the zero address\");\n        require(spender != address(0), \"ERC20: approve to the zero address\");\n\n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    /**\n     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n     *\n     * Does not update the allowance amount in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Might emit an {Approval} event.\n     */\n    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance != type(uint256).max) {\n            require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n            unchecked {\n                _approve(owner, spender, currentAllowance - amount);\n            }\n        }\n    }\n\n    /**\n     * @dev Hook that is called before any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * will be transferred to `to`.\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n    /**\n     * @dev Hook that is called after any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * has been transferred to `to`.\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\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 Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 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 functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n            \"Initializable: contract is already initialized\"\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 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\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        require(_initializing, \"Initializable: contract is not initializing\");\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        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _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 _initializing;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    bool private _paused;\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    function __Pausable_init() internal onlyInitializing {\n        __Pausable_init_unchained();\n    }\n\n    function __Pausable_init_unchained() internal onlyInitializing {\n        _paused = false;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        require(!paused(), \"Pausable: paused\");\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        require(paused(), \"Pausable: not paused\");\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\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    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20Upgradeable.sol\";\nimport \"./extensions/IERC20MetadataUpgradeable.sol\";\nimport \"../../utils/ContextUpgradeable.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 * For a generic mechanism see {ERC20PresetMinterPauser}.\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 *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {\n    mapping(address => uint256) private _balances;\n\n    mapping(address => mapping(address => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * 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        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the default value returned by this function, unless\n     * it's overridden.\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual override returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual override returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - the caller must have a balance of at least `amount`.\n     */\n    function transfer(address to, uint256 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _transfer(owner, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `amount` 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 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, amount);\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 `amount`.\n     * - the caller must have allowance for ``from``'s tokens of at least\n     * `amount`.\n     */\n    function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(from, spender, amount);\n        _transfer(from, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, allowance(owner, spender) + addedValue);\n        return true;\n    }\n\n    /**\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `spender` must have allowance for the caller of at least\n     * `subtractedValue`.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        uint256 currentAllowance = allowance(owner, spender);\n        require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n        unchecked {\n            _approve(owner, spender, currentAllowance - subtractedValue);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Moves `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     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `from` must have a balance of at least `amount`.\n     */\n    function _transfer(address from, address to, uint256 amount) internal virtual {\n        require(from != address(0), \"ERC20: transfer from the zero address\");\n        require(to != address(0), \"ERC20: transfer to the zero address\");\n\n        _beforeTokenTransfer(from, to, amount);\n\n        uint256 fromBalance = _balances[from];\n        require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n        unchecked {\n            _balances[from] = fromBalance - amount;\n            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n            // decrementing then incrementing.\n            _balances[to] += amount;\n        }\n\n        emit Transfer(from, to, amount);\n\n        _afterTokenTransfer(from, to, amount);\n    }\n\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function _mint(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: mint to the zero address\");\n\n        _beforeTokenTransfer(address(0), account, amount);\n\n        _totalSupply += amount;\n        unchecked {\n            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n            _balances[account] += amount;\n        }\n        emit Transfer(address(0), account, amount);\n\n        _afterTokenTransfer(address(0), account, amount);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, reducing the\n     * total supply.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens.\n     */\n    function _burn(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: burn from the zero address\");\n\n        _beforeTokenTransfer(account, address(0), amount);\n\n        uint256 accountBalance = _balances[account];\n        require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n        unchecked {\n            _balances[account] = accountBalance - amount;\n            // Overflow not possible: amount <= accountBalance <= totalSupply.\n            _totalSupply -= amount;\n        }\n\n        emit Transfer(account, address(0), amount);\n\n        _afterTokenTransfer(account, address(0), amount);\n    }\n\n    /**\n     * @dev Sets `amount` 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    function _approve(address owner, address spender, uint256 amount) internal virtual {\n        require(owner != address(0), \"ERC20: approve from the zero address\");\n        require(spender != address(0), \"ERC20: approve to the zero address\");\n\n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    /**\n     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n     *\n     * Does not update the allowance amount in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Might emit an {Approval} event.\n     */\n    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance != type(uint256).max) {\n            require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n            unchecked {\n                _approve(owner, spender, currentAllowance - amount);\n            }\n        }\n    }\n\n    /**\n     * @dev Hook that is called before any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * will be transferred to `to`.\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n    /**\n     * @dev Hook that is called after any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * has been transferred to `to`.\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[45] private __gap;\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\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 amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` 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 amount) 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 `amount` as the allowance of `spender` over the 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 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` 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 amount) external returns (bool);\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\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-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\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 IERC20PermitUpgradeable {\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-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.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 SafeERC20Upgradeable {\n    using AddressUpgradeable for address;\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(IERC20Upgradeable token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, 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(IERC20Upgradeable token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 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(IERC20Upgradeable token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n    }\n\n    /**\n     * @dev Decrease 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 safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\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(IERC20Upgradeable token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n     * Revert on invalid signature.\n     */\n    function safePermit(\n        IERC20PermitUpgradeable token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        uint256 nonceBefore = token.nonces(owner);\n        token.permit(owner, spender, value, deadline, v, r, s);\n        uint256 nonceAfter = token.nonces(owner);\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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(IERC20Upgradeable 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, \"SafeERC20: low-level call failed\");\n        require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\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(IERC20Upgradeable 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\n            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\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, it is bubbled up by this\n     * function (like regular Solidity function calls).\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     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\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     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\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    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\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 amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` 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 amount) 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 `amount` as the allowance of `spender` over the 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 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` 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 amount) external returns (bool);\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\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/utils/Context.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"},{"file_path":"@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router01.sol","source_code":"pragma solidity >=0.6.2;\n\ninterface IUniswapV2Router01 {\n    function factory() external pure returns (address);\n    function WETH() external pure returns (address);\n\n    function addLiquidity(\n        address tokenA,\n        address tokenB,\n        uint amountADesired,\n        uint amountBDesired,\n        uint amountAMin,\n        uint amountBMin,\n        address to,\n        uint deadline\n    ) external returns (uint amountA, uint amountB, uint liquidity);\n    function addLiquidityETH(\n        address token,\n        uint amountTokenDesired,\n        uint amountTokenMin,\n        uint amountETHMin,\n        address to,\n        uint deadline\n    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);\n    function removeLiquidity(\n        address tokenA,\n        address tokenB,\n        uint liquidity,\n        uint amountAMin,\n        uint amountBMin,\n        address to,\n        uint deadline\n    ) external returns (uint amountA, uint amountB);\n    function removeLiquidityETH(\n        address token,\n        uint liquidity,\n        uint amountTokenMin,\n        uint amountETHMin,\n        address to,\n        uint deadline\n    ) external returns (uint amountToken, uint amountETH);\n    function removeLiquidityWithPermit(\n        address tokenA,\n        address tokenB,\n        uint liquidity,\n        uint amountAMin,\n        uint amountBMin,\n        address to,\n        uint deadline,\n        bool approveMax, uint8 v, bytes32 r, bytes32 s\n    ) external returns (uint amountA, uint amountB);\n    function removeLiquidityETHWithPermit(\n        address token,\n        uint liquidity,\n        uint amountTokenMin,\n        uint amountETHMin,\n        address to,\n        uint deadline,\n        bool approveMax, uint8 v, bytes32 r, bytes32 s\n    ) external returns (uint amountToken, uint amountETH);\n    function swapExactTokensForTokens(\n        uint amountIn,\n        uint amountOutMin,\n        address[] calldata path,\n        address to,\n        uint deadline\n    ) external returns (uint[] memory amounts);\n    function swapTokensForExactTokens(\n        uint amountOut,\n        uint amountInMax,\n        address[] calldata path,\n        address to,\n        uint deadline\n    ) external returns (uint[] memory amounts);\n    function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)\n        external\n        payable\n        returns (uint[] memory amounts);\n    function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)\n        external\n        returns (uint[] memory amounts);\n    function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)\n        external\n        returns (uint[] memory amounts);\n    function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)\n        external\n        payable\n        returns (uint[] memory amounts);\n\n    function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);\n    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);\n    function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);\n    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);\n    function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);\n}\n"},{"file_path":"@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol","source_code":"pragma solidity >=0.6.2;\n\nimport './IUniswapV2Router01.sol';\n\ninterface IUniswapV2Router02 is IUniswapV2Router01 {\n    function removeLiquidityETHSupportingFeeOnTransferTokens(\n        address token,\n        uint liquidity,\n        uint amountTokenMin,\n        uint amountETHMin,\n        address to,\n        uint deadline\n    ) external returns (uint amountETH);\n    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(\n        address token,\n        uint liquidity,\n        uint amountTokenMin,\n        uint amountETHMin,\n        address to,\n        uint deadline,\n        bool approveMax, uint8 v, bytes32 r, bytes32 s\n    ) external returns (uint amountETH);\n\n    function swapExactTokensForTokensSupportingFeeOnTransferTokens(\n        uint amountIn,\n        uint amountOutMin,\n        address[] calldata path,\n        address to,\n        uint deadline\n    ) external;\n    function swapExactETHForTokensSupportingFeeOnTransferTokens(\n        uint amountOutMin,\n        address[] calldata path,\n        address to,\n        uint deadline\n    ) external payable;\n    function swapExactTokensForETHSupportingFeeOnTransferTokens(\n        uint amountIn,\n        uint amountOutMin,\n        address[] calldata path,\n        address to,\n        uint deadline\n    ) external;\n}\n"},{"file_path":"contracts/GuardedLaunchUpgradable.sol","source_code":"//SPDX-License-Identifier: Apache 2.0\npragma solidity 0.8.10;\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\n/// @notice This abstract contract is used to add an updatable limit on the total value locked\n/// that the contract can have. It also have an emergency method that allows the owner to pull\n/// funds into predefined recovery address\n/// @dev Inherit this contract and add the _guarded method to the child contract\nabstract contract GuardedLaunchUpgradable is Initializable, OwnableUpgradeable, ReentrancyGuardUpgradeable {\n  using SafeERC20Upgradeable for IERC20Upgradeable;\n\n  // ERROR MESSAGES:\n  error Is0();\n  error ContractLimitReached();\n  error NotAuthorized();\n\n  // TVL limit in underlying value\n  uint256 public limit;\n  // recovery address\n  address public governanceRecoveryFund;\n\n  /// @param _limit TVL limit. (0 means unlimited)\n  /// @param _governanceRecoveryFund recovery address\n  /// @param _owner owner address\n  function __GuardedLaunch_init(uint256 _limit, address _governanceRecoveryFund, address _owner) internal {\n    _checkIs0(_governanceRecoveryFund == address(0) || _owner == address(0));\n    // Initialize inherited contracts\n    OwnableUpgradeable.__Ownable_init();\n    ReentrancyGuardUpgradeable.__ReentrancyGuard_init();\n    // Initialize state variables\n    limit = _limit;\n    governanceRecoveryFund = _governanceRecoveryFund;\n    // Transfer ownership\n    transferOwnership(_owner);\n  }\n\n  /// @notice this check should be called inside the child contract on deposits to check that the\n  /// TVL didn't exceed a threshold\n  /// @param _amount new amount to deposit\n  function _guarded(uint256 _amount) internal view {\n    uint256 _limit = limit;\n    if (_limit > 0) {\n      if (getContractValue() + _amount > _limit) revert ContractLimitReached();\n    }\n  }\n\n  /// @dev Check that the second function is not called in the same tx from the same tx.origin\n  function _checkOnlyOwner() internal view {\n    _checkNotAuthorized(owner() != msg.sender);\n  }\n\n  /// @notice abstract method, should return the TVL in underlyings\n  function getContractValue() public virtual view returns (uint256);\n\n  /// @notice set contract TVL limit\n  /// @param _limit limit in underlying value, 0 means no limit\n  function _setLimit(uint256 _limit) external {\n    _checkOnlyOwner();\n    limit = _limit;\n  }\n\n  /// @notice Emergency method, tokens gets transferred to the governanceRecoveryFund address\n  /// @param _token address of the token to transfer\n  /// @param _value amount to transfer\n  function transferToken(address _token, uint256 _value) external {\n    _checkOnlyOwner();\n    IERC20Upgradeable(_token).safeTransfer(governanceRecoveryFund, _value);\n  }\n\n  /// @notice check revert condition and revert with Is0 error\n  /// @param _revertCondition condition to check\n  function _checkIs0(bool _revertCondition) internal pure {\n    if (_revertCondition) revert Is0();\n  }\n\n  /// @notice check revert condition and revert with NotAuthorized error\n  /// @param _revertCondition condition to check\n  function _checkNotAuthorized(bool _revertCondition) internal pure {\n    if (_revertCondition) revert NotAuthorized();\n  }\n}\n"},{"file_path":"contracts/IdleCDOCreditVault.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.10;\n\nimport \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\nimport \"./interfaces/IIdleCDOStrategy.sol\";\nimport \"./interfaces/IERC20Detailed.sol\";\n\nimport \"./GuardedLaunchUpgradable.sol\";\nimport \"./IdleCDOTranche.sol\";\nimport \"./IdleCDOStorage.sol\";\n\n/// @title IdleCDO fork for credit vaults\n/// @author Idle Labs Inc.\n/// @notice Credit vault specific CDO runtime without legacy tranche/reward methods.\n/// @dev Storage layout intentionally matches IdleCDO so existing epoch-vault proxies can upgrade safely.\ncontract IdleCDOCreditVault is PausableUpgradeable, GuardedLaunchUpgradable, IdleCDOStorage {\n  using SafeERC20Upgradeable for IERC20Detailed;\n\n  // ERROR MESSAGES:\n  error AlreadyInitialized();\n  error Default();\n  error AmountTooHigh();\n\n  // Used to prevent initialization of the implementation contract\n  /// @custom:oz-upgrades-unsafe-allow constructor\n  constructor() {\n    token = address(1);\n  }\n\n  // ###################\n  // Initializer\n  // ###################\n\n  /// @notice can only be called once\n  /// @dev Initialize the upgradable contract\n  /// @param _limit contract value limit, can be 0\n  /// @param _guardedToken underlying token\n  /// @param _governanceFund address where funds will be sent in case of emergency\n  /// @param _owner guardian address (can pause, unpause and call emergencyShutdown)\n  /// @param _strategy strategy address\n  /// @param _trancheAPRSplitRatio trancheAPRSplitRatio value\n  function initialize(\n    uint256 _limit, \n    address _guardedToken, \n    address _governanceFund, \n    address _owner, // GuardedLaunch args\n    address,\n    address _strategy,\n    uint256 _trancheAPRSplitRatio// for AA tranches, so eg 10000 means 10% interest to AA and 90% BB\n  ) external virtual initializer {\n    if (token != address(0)) revert AlreadyInitialized();\n    _checkIs0(_strategy == address(0) || _guardedToken == address(0));\n    _checkAmountTooHigh(_trancheAPRSplitRatio > FULL_ALLOC);\n    // Initialize contracts\n    PausableUpgradeable.__Pausable_init();\n    // check for _governanceFund and _owner != address(0) are inside GuardedLaunchUpgradable\n    GuardedLaunchUpgradable.__GuardedLaunch_init(_limit, _governanceFund, _owner);\n    // Deploy Tranches tokens\n    address _strategyToken = IIdleCDOStrategy(_strategy).strategyToken();\n    // get strategy token symbol (eg. idleDAI)\n    string memory _symbol = IERC20Detailed(_strategyToken).symbol();\n    // create tranche tokens (concat strategy token symbol in the name and symbol of the tranche tokens)\n    AATranche = _deployTranche(string(\"Pareto \"), string(\"p\"), _symbol);\n    BBTranche = _deployTranche(string(\"Pareto BB \"), string(\"pBB_\"), _symbol);\n    // Set CDO params\n    token = _guardedToken;\n    strategy = _strategy;\n    strategyToken = _strategyToken;\n    trancheAPRSplitRatio = _trancheAPRSplitRatio;\n    uint256 _oneToken = 10**(IERC20Detailed(_guardedToken).decimals());\n    oneToken = _oneToken;\n    priceAA = _oneToken;\n    priceBB = _oneToken;\n    // skipDefaultCheck = false is the default value\n    // Set allowance for strategy\n    _allowUnlimitedSpend(_guardedToken, _strategy);\n    _allowUnlimitedSpend(_strategyToken, _strategy);\n    guardian = _owner;\n    isAYSActive = true; // adaptive yield split\n    minAprSplitAYS = AA_RATIO_LIM_DOWN; // AA tranche will get min 50% of the yield\n    // Credit vaults reuse this legacy slot as the management-fee checkpoint timestamp.\n    latestHarvestBlock = block.timestamp;\n    maxDecreaseDefault = 5000; // 5% decrease for triggering a default\n    _additionalInit();\n  }\n\n  /// @notice used by child contracts (cdo variants) if anything needs to be done on/after init\n  function _additionalInit() internal virtual {}\n\n  // ###############\n  // Public methods\n  // ###############\n\n  /// @notice pausable\n  /// @dev msg.sender should approve this contract first to spend `_amount` of `token`\n  /// @param _amount amount of `token` to deposit\n  /// @return AA tranche tokens minted\n  function depositAA(uint256 _amount) external returns (uint256) {\n    return _deposit(_amount, AATranche);\n  }\n\n  /// @notice pausable in _deposit\n  /// @dev msg.sender should approve this contract first to spend `_amount` of `token`\n  /// @param _amount amount of `token` to deposit\n  /// @return BB tranche tokens minted\n  function depositBB(uint256 _amount) external returns (uint256) {\n    return _deposit(_amount, BBTranche);\n  }\n\n  // ###############\n  // Views\n  // ###############\n\n  /// @param _tranche tranche address\n  /// @return tranche price, in underlyings, at the last interaction (not considering interest earned \n  /// since last interaction)\n  function tranchePrice(address _tranche) external view returns (uint256) {\n    return _tranchePrice(_tranche);\n  }\n\n  /// @notice calculates the current net TVL (in `token` terms)\n  /// @dev `unclaimedFees` are not counted.\n  function getContractValue() public override view returns (uint256) {\n    // Credit vault strategy tokens are minted 1:1 with underlyings and use the same decimals.\n    return _contractTokenBalance(strategyToken) + _contractTokenBalance(token) - unclaimedFees;\n  }\n\n  /// @notice Calculates the current managed net TVL.\n  /// @dev Raw underlyings held by the CDO are excluded because unsolicited transfers are skimmed on interactions.\n  /// @return Strategy-token-backed TVL net of accrued fees.\n  function _managedContractValue() internal virtual view returns (uint256) {\n    uint256 strategyTokenBalance = _contractTokenBalance(strategyToken);\n    uint256 fees = unclaimedFees;\n    return strategyTokenBalance > fees ? strategyTokenBalance - fees : 0;\n  }\n\n  /// @param _tranche tranche address\n  /// @return actual apr given current ratio between AA and BB tranches\n  function getApr(address _tranche) external view returns (uint256) {\n    uint256 _AATrancheSplitRatio = _getAARatio(false);\n    uint256 stratApr = _getStrategyApr();\n    if (_AATrancheSplitRatio == 0) {\n      // if there are no AA tranches, apr for AA is 0 (all apr to BB and it will be equal to stratApr)\n      return _tranche == AATranche ? 0 : stratApr;\n    }\n    uint256 _trancheAPRSplitRatio = trancheAPRSplitRatio;\n    if (_tranche != AATranche) {\n      // BB apr is: stratApr * BBaprSplitRatio / BBSplitRatio -> where\n      // BBaprSplitRatio is: (FULL_ALLOC - _trancheAPRSplitRatio) and\n      // BBSplitRatio is: (FULL_ALLOC - _AATrancheSplitRatio)\n      return stratApr * (FULL_ALLOC - _trancheAPRSplitRatio) / (FULL_ALLOC - _AATrancheSplitRatio);\n    }\n    // AA apr is: stratApr * AAaprSplitRatio / AASplitRatio\n    return stratApr * _trancheAPRSplitRatio / _AATrancheSplitRatio;\n  }\n\n  /// @notice calculates the current AA tranches ratio\n  /// @dev _virtualBalance is used to have a more accurate/recent value for the AA ratio\n  /// because it calculates the balance after splitting the accrued interest since the\n  /// last depositXX/withdrawXX\n  /// @return AA tranches ratio (in underlying value) considering all interest\n  function getCurrentAARatio() external view returns (uint256) {\n    return _getAARatio(false);\n  }\n\n  /// @notice calculates the current tranches price considering the interest/loss that is yet to be splitted\n  /// ie the interest/loss generated since the last update of priceAA and priceBB (done on depositXX/withdrawXX)\n  /// @param _tranche address of the requested tranche\n  /// @return _virtualPrice tranche price considering all interest/losses\n  function virtualPrice(address _tranche) public virtual view returns (uint256 _virtualPrice) {\n    (_virtualPrice, ) = _virtualPriceAux(\n      _tranche,\n      _managedContractValue(), // nav\n      lastNAVAA + lastNAVBB, // lastNAV\n      _lastSavedNAV(_tranche), // lastTrancheNAV\n      trancheAPRSplitRatio\n    );\n  }\n\n  // ###############\n  // Internal\n  // ###############\n\n  /// @notice method used to deposit `token` and mint tranche tokens\n  /// @dev this contract must be approved to spend at least _amount of `token` before calling this method\n  /// @param _amount amount of underlyings (`token`) to deposit\n  /// @param _tranche tranche address\n  /// @return _minted number of tranche tokens minted\n  function _deposit(uint256 _amount, address _tranche) internal virtual whenNotPaused returns (uint256 _minted) {\n    if (_amount == 0) {\n      return _minted;\n    }\n    // check that we are not depositing more than the contract available limit\n    _guarded(_amount);\n    // interest accrued since last depositXX/withdrawXX is splitted between AA and BB\n    // according to trancheAPRSplitRatio. NAVs of AA and BB are updated and tranche\n    // prices adjusted accordingly\n    _updateAccounting();\n    // get underlyings from sender\n    address _token = token;\n    uint256 _preBal = _contractTokenBalance(_token);\n    _transferUnderlyingsFrom(msg.sender, address(this), _amount);\n    // mint tranche tokens according to the current tranche price\n    _minted = _mintSharesAtCurrPrice(_contractTokenBalance(_token) - _preBal, msg.sender, _tranche);\n    // update trancheAPRSplitRatio\n    _updateSplitRatio(_getAARatio(true));\n\n    // direct deposit in the strategy\n    IIdleCDOStrategy(strategy).deposit(_amount);\n  }\n\n  /// @notice this method is called on depositXX/withdrawXX and\n  /// updates the accounting of the contract and effectively splits the yield/loss between the\n  /// AA and BB tranches\n  /// @dev this method:\n  /// - update tranche prices (priceAA and priceBB)\n  /// - update net asset value for both tranches (lastNAVAA and lastNAVBB)\n  /// - update fee accounting (unclaimedFees)\n  function _updateAccounting() internal virtual {\n    _accrueManagementFee();\n    uint256 _lastNAVAA = lastNAVAA;\n    uint256 _lastNAVBB = lastNAVBB;\n    uint256 _lastNAV = _lastNAVAA + _lastNAVBB;\n    uint256 nav = getContractValue();\n    uint256 _aprSplitRatio = trancheAPRSplitRatio;\n    // If gain is > 0, then collect some fees in `unclaimedFees`\n    if (nav > _lastNAV) {\n      unclaimedFees += (nav - _lastNAV) * fee / FULL_ALLOC;\n    }\n    (uint256 _priceAA, int256 _totalAAGain) = _virtualPriceAux(AATranche, nav, _lastNAV, _lastNAVAA, _aprSplitRatio);\n    (uint256 _priceBB, int256 _totalBBGain) = _virtualPriceAux(BBTranche, nav, _lastNAV, _lastNAVBB, _aprSplitRatio);\n    lastNAVAA = uint256(int256(_lastNAVAA) + _totalAAGain);\n\n    // if we have a loss and it's gte last junior NAV we trigger a default\n    if (_totalBBGain < 0 && -_totalBBGain >= int256(_lastNAVBB)) {\n      // revert with 'default' error (4) if skipDefaultCheck is false, as seniors will have a loss too not covered. \n      // `updateAccounting` should be manually called to distribute loss\n      if (!skipDefaultCheck) revert Default();\n      // This path will be called when a default happens and guardian calls\n      // `updateAccounting` after setting skipDefaultCheck or when skipDefaultCheck is already set to true\n      lastNAVBB = 0;\n      // if skipDefaultCheck is set to true prior a default (eg because AA is used as collateral and needs to be liquid), \n      // emergencyShutdown won't prevent the current deposit/redeem (the one that called this _updateAccounting) and is \n      // still correct because:\n      // - depositBB will revert as priceBB is 0\n      // - depositAA won't revert (unless the loss is 100% of TVL) and user will get \n      //   correct number of share at a priceAA already post junior default\n      // - withdrawBB will redeem 0 and burn BB tokens because priceBB is 0\n      // - withdrawAA will redeem the correct amount of underlyings post junior default\n      // We pass true as we still want AA to be redeemable in any case even after a junior default\n      _emergencyShutdown(true);\n    } else {\n      // we add the gain to last saved NAV\n      lastNAVBB = uint256(int256(_lastNAVBB) + _totalBBGain);\n    }\n    priceAA = _priceAA;\n    priceBB = _priceBB;\n  }\n\n  /// @notice calculates the NAV for a tranche considering the interest that is yet to be splitted\n  /// @param _tranche address of the requested tranche\n  /// @return net asset value, in underlying tokens, for _tranche considering all nav\n  function _virtualBalance(address _tranche) internal view returns (uint256) {\n    // balance is: tranche supply * virtual tranche price\n    return _trancheSupply(_tranche) * virtualPrice(_tranche) / ONE_TRANCHE_TOKEN;\n  }\n\n  /// @notice calculates the NAV for a tranche without considering the interest that is yet to be splitted\n  /// @param _tranche address of the requested tranche\n  /// @return net asset value, in underlying tokens, for _tranche\n  function _instantBalance(address _tranche) internal view returns (uint256) {\n    return _trancheSupply(_tranche) * _tranchePrice(_tranche) / ONE_TRANCHE_TOKEN;\n  }\n\n  /// @notice gets total supply for a specific tranche\n  /// @param _tranche address of the requested tranche\n  function _trancheSupply(address _tranche) internal view returns (uint256) {\n    return IdleCDOTranche(_tranche).totalSupply();\n  }\n\n  /// @notice gets last saved NAV for a specific tranche\n  /// @param _tranche address of the requested tranche\n  function _lastSavedNAV(address _tranche) internal view returns (uint256) {\n    return _tranche == AATranche ? lastNAVAA : lastNAVBB;\n  }\n\n  /// @notice calculates the current tranches price considering the interest/loss that is yet to be splitted and the\n  /// total gain/loss for a specific tranche\n  /// @dev Main scenarios covered:\n  /// - if there is a loss on the lending protocol (ie strategy price decrease) up to maxDecreaseDefault (_checkDefault method), the loss is\n  ///     - totally absorbed by junior holders if they have enough TVL and deposits/redeems work as normal\n  ///     - otherwise a 'default' error (4) is raised and deposits/redeems are blocked\n  /// - if there is a loss on the lending protocol (ie strategy price decrease) more than maxDecreaseDefault all deposits and redeems\n  ///   are blocked and a 'default' error (4) is raised\n  /// - if there is a loss somewhere not in the lending protocol (ie in our contracts) and the TVL decreases then the same process as above\n  ///   applies, the only difference is that maxDecreaseDefault is not considered\n  /// In any case, once a loss happens, it only gets accounted when new deposits/redeems are made, but those are blocked.\n  /// For this reason a protected updateAccounting method has been added which should be used to distributed the loss after a default event\n  /// @param _tranche address of the requested tranche\n  /// @param _nav current NAV\n  /// @param _lastNAV last saved NAV\n  /// @param _lastTrancheNAV last saved tranche NAV\n  /// @param _trancheAPRSplitRatio APR split ratio for AA tranche\n  /// @return _virtualPrice tranche price considering all interest\n  /// @return _totalTrancheGain (int256) tranche gain/loss since last update\n  function _virtualPriceAux(\n    address _tranche,\n    uint256 _nav,\n    uint256 _lastNAV,\n    uint256 _lastTrancheNAV,\n    uint256 _trancheAPRSplitRatio\n  ) internal virtual view returns (uint256 _virtualPrice, int256 _totalTrancheGain) {\n    // Check if there are tranche holders\n    uint256 trancheSupply = _trancheSupply(_tranche);\n    if (_lastNAV == 0 || trancheSupply == 0) {\n      return (oneToken, 0);\n    }\n\n    // In order to correctly split the interest generated between AA and BB tranche holders\n    // (according to the trancheAPRSplitRatio) we need to know how much interest/loss we gained\n    // since the last price update (during a depositXX/withdrawXX)\n    // To do that we need to get the current value of the assets in this contract\n    // and the last saved one (always during a depositXX/withdrawXX)\n    // Calculate the total gain/loss\n    int256 totalGain = int256(_nav) - int256(_lastNAV);\n    // If there is no gain/loss return the current price\n    if (totalGain == 0) {\n      return (_tranchePrice(_tranche), 0);\n    }\n\n    // Remove performance fee for gains\n    if (totalGain > 0) {\n      totalGain -= totalGain * int256(fee) / int256(FULL_ALLOC);\n    }\n\n    address _AATranche = AATranche;\n    address _BBTranche = BBTranche;\n    bool _isAATranche = _tranche == _AATranche;\n    // Get the supply of the other tranche and\n    // if it's 0 then give all gain to the current `_tranche` holders\n    if (_trancheSupply(_isAATranche ? _BBTranche : _AATranche) == 0) {\n      _totalTrancheGain = totalGain;\n    } else {\n      // if we gained something or the loss is between 0 and lossToleranceBps then we socialize the gain/loss\n      if (totalGain > 0) {\n        // Split the net gain, according to _trancheAPRSplitRatio, with precision loss favoring the AA tranche.\n        int256 totalBBGain = totalGain * int256(FULL_ALLOC - _trancheAPRSplitRatio) / int256(FULL_ALLOC);\n        // The new NAV for the tranche is old NAV + total gain for the tranche\n        _totalTrancheGain = _isAATranche ? (totalGain - totalBBGain) : totalBBGain;\n      } else if (uint256(-totalGain) <= (lossToleranceBps * _lastNAV) / FULL_ALLOC) {\n        // Split the loss, according to TVL ratio instead of _trancheAPRSplitRatio (loss socialized between all tranches)\n        uint256 _lastNAVBB = lastNAVBB;\n        int256 totalBBLoss = totalGain * int256(_lastNAVBB) / int256(lastNAVAA + _lastNAVBB);\n        // The new NAV for the tranche is old NAV - loss for the tranche\n        _totalTrancheGain = _isAATranche ? (totalGain - totalBBLoss) : totalBBLoss;\n      } else { // totalGain is negative here\n        // Redirect the whole loss (which should be < maxDecreaseDefault) to junior holders\n        int256 _juniorTVL = int256(_isAATranche ? _lastNAV - _lastTrancheNAV : _lastTrancheNAV);\n        int256 _newJuniorTVL = _juniorTVL + totalGain; \n        // if junior holders have enough TVL to cover\n        if (_newJuniorTVL > 0) {\n          // then juniors get all loss (totalGain) and senior gets 0 loss\n          _totalTrancheGain = _isAATranche ? int256(0) : totalGain;\n        } else {\n          // otherwise all loss minus junior tvl to senior\n          if (!_isAATranche) {\n            // juniors have no more claims, price is set to 0, gain is set to -juniorTVL\n            return (0, -_juniorTVL);\n          }\n          // seniors get the loss - old junior TVL\n          _totalTrancheGain = _newJuniorTVL;\n        }\n      }\n    }\n    // Split the new NAV (_lastTrancheNAV + _totalTrancheGain) per tranche token\n    _virtualPrice = uint256(int256(_lastTrancheNAV) + _totalTrancheGain) * ONE_TRANCHE_TOKEN / trancheSupply;\n  }\n\n  /// @notice mint tranche tokens at current price and updates tranche last NAV\n  /// @param _amount, in underlyings, to convert in tranche tokens\n  /// @param _to receiver address of the newly minted tranche tokens\n  /// @param _tranche tranche address\n  /// @return _minted number of tranche tokens minted\n  function _mintSharesAtCurrPrice(uint256 _amount, address _to, address _tranche) internal virtual returns (uint256 _minted) {\n    // calculate # of tranche token to mint based on current tranche price: _amount / tranchePrice\n    _minted = _amount * ONE_TRANCHE_TOKEN / _tranchePrice(_tranche);\n    _mintShares(_tranche, _to, _minted, _amount);\n  }\n\n  /// @notice mint tranche tokens and updates tranche last NAV\n  /// @param _tranche tranche address\n  /// @param _to receiver address of the newly minted tranche tokens\n  /// @param _shares number of tranche tokens to mint\n  /// @param _underlyings amount of underlyings added to the tranche\n  function _mintShares(address _tranche, address _to, uint256 _shares, uint256 _underlyings) internal {\n    IdleCDOTranche(_tranche).mint(_to, _shares);\n    // update NAV with the _amount of underlyings added\n    if (_tranche == AATranche) {\n      lastNAVAA += _underlyings;\n    } else {\n      lastNAVBB += _underlyings;\n    }\n  }\n\n  /// @notice Burn tranche tokens and update NAV and trancheAPRSplitRatio\n  /// @param _amount Amount of tranche tokens\n  /// @param _underlyings Amount of underlyings\n  /// @param _tranche Tranche to withdraw from\n  function _withdrawOps(uint256 _amount, uint256 _underlyings, address _tranche) internal {\n    // burn tranche token\n    IdleCDOTranche(_tranche).burn(msg.sender, _amount);\n\n    // update NAV with the _amount of underlyings removed\n    if (_tranche == AATranche) {\n      lastNAVAA -= _underlyings;\n    } else {\n      lastNAVBB -= _underlyings;\n    }\n\n    // update trancheAPRSplitRatio\n    _updateSplitRatio(_getAARatio(true));\n  }\n\n  /// @notice updates trancheAPRSplitRatio based on the current tranches TVL ratio between AA and BB\n  /// @dev the idea here is to limit the min and max APR that the senior tranche can get\n  function _updateSplitRatio(uint256 tvlAARatio) internal virtual {\n    uint256 _minSplit = minAprSplitAYS;\n    _minSplit = _minSplit == 0 ? AA_RATIO_LIM_DOWN : _minSplit;\n\n    if (isAYSActive) {\n      uint256 aux;\n      if (tvlAARatio >= AA_RATIO_LIM_UP) {\n        aux = tvlAARatio == FULL_ALLOC ? FULL_ALLOC : AA_RATIO_LIM_UP;\n      } else if (tvlAARatio > _minSplit) {\n        aux = tvlAARatio;\n      } else {\n        aux = _minSplit;\n      }\n      trancheAPRSplitRatio = aux * tvlAARatio / FULL_ALLOC;\n    }\n  }\n\n  /// @notice calculates the current AA tranches ratio\n  /// @dev it does count accrued interest not yet split since last\n  /// depositXX/withdrawXX only if _instant flag is true\n  /// @param _instant if true, it returns the current ratio without accrued interest\n  /// @return AA tranches ratio (in underlying value) considering all interest\n  function _getAARatio(bool _instant) internal view returns (uint256) {\n    function(address) internal view returns (uint256) _getNAV =\n      _instant ? _instantBalance : _virtualBalance;\n    uint256 AABal = _getNAV(AATranche);\n    uint256 contractVal = AABal + _getNAV(BBTranche);\n    if (contractVal == 0) {\n      return 0;\n    }\n    // Current AA tranche split ratio = AABal * FULL_ALLOC / (AABal + BBBal)\n    return AABal * FULL_ALLOC / contractVal;\n  }\n\n  /// @param _tranche tranche address\n  /// @return last saved tranche price, in underlyings\n  function _tranchePrice(address _tranche) internal view returns (uint256) {\n    if (_trancheSupply(_tranche) == 0) {\n      return oneToken;\n    }\n    return _tranche == AATranche ? priceAA : priceBB;\n  }\n\n  /// @notice internal method used to deploy a new tranche token\n  /// @param _namePrefix prefix for the name of the tranche token\n  /// @param _symbolPrefix prefix for the symbol of the tranche token\n  /// @param _symbol suffix for the symbol of the tranche token\n  /// @return address of the newly deployed tranche token\n  function _deployTranche(string memory _namePrefix, string memory _symbolPrefix, string memory _symbol) internal returns (address) {\n    return address(new IdleCDOTranche(_concat(_namePrefix, _symbol), _concat(_symbolPrefix, _symbol)));\n  }\n\n  // ###################\n  // onlyOwner\n  // ###################\n\n  /// @param _active flag to allow Adaptive Yield Split\n  function setIsAYSActive(bool _active) external virtual {\n    _checkOnlyOwner();\n    isAYSActive = _active;\n  }\n\n  /// @param _feeReceiver fee receiver address. It gets the portion of fees specified by `_feeSplit`.\n  /// The remaining fee portion goes to `owner()`.\n  /// @dev Reverts if `_feeReceiver` is address(0). Use `_feeSplit = 0` to route all fees to `owner()`.\n  /// @param _fee new performance fee value (in % with 100000 = 100%)\n  /// @param _feeSplit portion of collected fees sent to `_feeReceiver` (100000 = 100%)\n  /// @param _managementFee annualized management fee (in % with 100000 = 100%)\n  function setFeeParams(address _feeReceiver, uint256 _fee, uint256 _feeSplit, uint256 _managementFee) external {\n    _checkOnlyOwner();\n    _checkAmountTooHigh(_fee > MAX_FEE || _feeSplit > FULL_ALLOC || _managementFee > MAX_FEE / 10);\n    _checkIs0((feeReceiver = _feeReceiver) == address(0));\n\n    _accrueManagementFee();\n    fee = _fee;\n    feeSplit = _feeSplit;\n    managementFee = _managementFee;\n  }\n\n  /// @param _guardian new guardian (pauser) address\n  function setGuardian(address _guardian) external {\n    _checkOnlyOwner();\n    _checkIs0((guardian = _guardian) == address(0));\n  }\n\n  /// @param _aprSplit min apr split for AA, considering FULL_ALLOC = 100%\n  function setMinAprSplitAYS(uint256 _aprSplit) external virtual {\n    _checkOnlyOwner();\n    _checkAmountTooHigh((minAprSplitAYS = _aprSplit) > FULL_ALLOC);\n  }\n\n  /// @param _diffBps tolerance in % (FULL_ALLOC = 100%) for socializing small losses \n  function setLossToleranceBps(uint256 _diffBps) external {\n    _checkOnlyOwner();\n    lossToleranceBps = _diffBps;\n  }\n\n  /// @notice this method updates the accounting of the contract and effectively splits the yield/loss between the\n  /// AA and BB tranches. This can be called at any time as is called automatically on each deposit/redeem. It's here\n  /// just to be called when a default happened, as deposits/redeems are paused, but we need to update\n  /// the loss for junior holders\n  function updateAccounting() external virtual {\n    _checkOnlyOwnerOrGuardian();\n    _forceUpdateAccounting();\n  }\n\n  /// @notice force accounting update without reverting on default path\n  function _forceUpdateAccounting() internal {\n    skipDefaultCheck = true;\n    _updateAccounting();\n    // _updateAccounting can set `skipDefaultCheck` to true in case of default\n    // but this can be manually be reset to true if needed\n    skipDefaultCheck = false;\n  }\n\n  /// @notice pause deposits and redeems for all classes of tranches\n  /// @dev can be called by both the owner and the guardian\n  function emergencyShutdown() external {\n    _checkOnlyOwnerOrGuardian();\n    _emergencyShutdown(false);\n  }\n\n  function _emergencyShutdown(bool) internal virtual {}\n\n  /// @notice allow deposits and redeems for all classes of tranches\n  /// @dev can be called by the owner only\n  function restoreOperations() external virtual {}\n\n  /// @notice Pauses deposits\n  /// @dev can be called by both the owner and the guardian\n  function pause() external  {\n    _checkOnlyOwnerOrGuardian();\n    _pause();\n  }\n\n  /// @notice Unpauses deposits\n  /// @dev can be called by both the owner and the guardian\n  function unpause() external {\n    _checkOnlyOwnerOrGuardian();\n    _unpause();\n  }\n\n  // ###################\n  // Helpers\n  // ###################\n\n  /// @dev Check that the msg.sender is the either the owner or the guardian\n  function _checkOnlyOwnerOrGuardian() internal view {\n    _checkNotAuthorized(msg.sender != guardian && msg.sender != owner());\n  }\n\n  /// @notice returns the current balance of this contract for a specific token\n  /// @param _token token address\n  /// @return balance of `_token` for this contract\n  function _contractTokenBalance(address _token) internal view returns (uint256) {\n    return IERC20Detailed(_token).balanceOf(address(this));\n  }\n\n  /// @notice Checkpoint accrued management fees into `unclaimedFees`.\n  /// @dev Raw underlyings are excluded because unsolicited transfers are skimmed instead of managed.\n  function _accrueManagementFee() internal {\n    unclaimedFees += _calculateManagementFee(_managedContractValue(), block.timestamp - latestHarvestBlock);\n    latestHarvestBlock = block.timestamp;\n  }\n\n  /// @notice calculate annualized management fee for a balance over a duration\n  function _calculateManagementFee(uint256 _nav, uint256 _duration) internal view returns (uint256) {\n    // 3153600000000 == FULL_ALLOC * 365 days\n    return _nav * managementFee * _duration / 3153600000000;\n  }\n\n  /// @notice returns the user tranche balance for a specific tranche\n  /// @param _user user address\n  /// @param _tranche tranche address\n  function _userTrancheBal(address _user, address _tranche) internal view returns (uint256) {\n    return IERC20Detailed(_tranche).balanceOf(_user);\n  }\n\n  /// @dev Set allowance for _token to unlimited for _spender\n  /// @param _token token address\n  /// @param _spender spender address\n  function _allowUnlimitedSpend(address _token, address _spender) internal {\n    IERC20Detailed(_token).safeIncreaseAllowance(_spender, type(uint256).max);\n  }\n\n  /// @dev transfer underlyings to a specific address\n  /// @param _to receiver address\n  /// @param _amount amount to transfer\n  function _transferUnderlyings(address _to, uint256 _amount) internal {\n    if (_amount == 0) return;\n    IERC20Detailed(token).safeTransfer(_to, _amount);\n  }\n\n  /// @notice transfer fee to feeReceiver and owner according to feeSplit\n  /// @param _amount total fee amount to split and transfer (in underlyings)\n  function _transferFeeUnderlyings(uint256 _amount) internal {\n    uint256 feeReceiverAmount = _feeReceiverAmount(_amount);\n    _transferUnderlyings(feeReceiver, feeReceiverAmount);\n    _transferUnderlyings(owner(), _amount - feeReceiverAmount);\n  }\n\n  /// @notice calculates the amount to transfer to feeReceiver based on the feeSplit\n  /// @param _amount total fee amount to split\n  function _feeReceiverAmount(uint256 _amount) internal view returns (uint256) {\n    if (feeReceiver == address(0)) return 0;\n    return _amount * feeSplit / FULL_ALLOC;\n  }\n\n  /// @dev transfer underlyings from a specific address to another address\n  /// @param _from sender address\n  /// @param _to receiver address\n  /// @param _amount amount to transfer\n  function _transferUnderlyingsFrom(address _from, address _to, uint256 _amount) internal {\n    if (_amount == 0) return;\n    IERC20Detailed(token).safeTransferFrom(_from, _to, _amount);\n  }\n\n  /// @dev Get the current strategy apr\n  function _getStrategyApr() internal view returns (uint256) {\n    return IIdleCDOStrategy(strategy).getApr();\n  }\n\n  /// @notice concat 2 strings in a single one\n  /// @param a first string\n  /// @param b second string\n  /// @return new string with a and b concatenated\n  function _concat(string memory a, string memory b) internal pure returns (string memory) {\n    return string(abi.encodePacked(a, b));\n  }\n\n  /// @notice check revert condition and revert with AmountTooHigh error\n  /// @param _revertCondition condition to check\n  function _checkAmountTooHigh(bool _revertCondition) internal pure {\n    if (_revertCondition) revert AmountTooHigh();\n  }\n}\n"},{"file_path":"contracts/IdleCDOStorage.sol","source_code":"// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.10;\n\nimport '@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol';\n\ncontract IdleCDOStorage {\n  // constant to represent 100%\n  uint256 public constant FULL_ALLOC = 100000;\n  // max fee, relative to FULL_ALLOC\n  uint256 public constant MAX_FEE = 20000;\n  // one token\n  uint256 public constant ONE_TRANCHE_TOKEN = 10**18;\n  // variable used to save the last tx.origin and block.number\n  bytes32 internal _lastCallerBlock;\n  // variable used to save the block of the latest harvest\n  uint256 public latestHarvestBlock;\n  // WETH address\n  address internal weth;\n  // [DEPRECATED] tokens used to incentivize the idle tranche ideal ratio\n  address[] internal incentiveTokens;\n  // underlying token (eg DAI)\n  address public token;\n  // address that can only pause/unpause the contract in case of emergency\n  address public guardian;\n  // one `token` (eg for DAI 10**18)\n  uint256 public oneToken;\n  // address that can call the 'harvest' method and lend pool assets\n  address public rebalancer;\n  // address of the uniswap v2 router\n  IUniswapV2Router02 internal uniswapRouterV2;\n\n  // Flag for allowing AA withdraws\n  bool public allowAAWithdraw;\n  // Flag for allowing BB withdraws\n  bool public allowBBWithdraw;\n  // Flag for allowing to enable reverting in case the strategy gives back less\n  // amount than the requested one\n  bool internal revertIfTooLow;\n  // Flag to enable the `Default Check` (related to the emergency shutdown)\n  bool internal skipDefaultCheck;\n\n  // address of the strategy used to lend funds\n  address public strategy;\n  // address of the strategy token which represent the position in the lending provider\n  address public strategyToken;\n  // address of AA Tranche token contract\n  address public AATranche;\n  // address of BB Tranche token contract\n  address public BBTranche;\n  // address for stkIDLE gating for AA tranche. addr(0) -> inactive, addr(1) -> active\n  address internal AAStaking;\n  // address for stkIDLE gating for BB tranche. addr(0) -> inactive, addr(1) -> active\n  address internal BBStaking;\n\n  // Apr split ratio for AA tranches\n  // (relative to FULL_ALLOC so 50% => 50000 => 50% of the interest to tranche AA)\n  uint256 public trancheAPRSplitRatio; //\n  // [DEPRECATED] Ideal tranche split ratio in `token` value\n  // (relative to FULL_ALLOC so 50% => 50000 means 50% of tranches (in value) should be AA)\n  uint256 internal trancheIdealWeightRatio;\n  // Price for minting AA tranche, in underlyings\n  uint256 public priceAA;\n  // Price for minting BB tranche, in underlyings\n  uint256 public priceBB;\n  // last saved net asset value (in `token`) for AA tranches\n  uint256 public lastNAVAA;\n  // last saved net asset value (in `token`) for BB tranches\n  uint256 public lastNAVBB;\n  // last saved lending provider price\n  uint256 internal lastStrategyPrice;\n  // Keeps track of unclaimed fees for fee receivers\n  uint256 public unclaimedFees;\n  // Keeps an unlent balance both for cheap redeem and as 'insurance of last resort'\n  uint256 public unlentPerc;\n\n  // Fee amount (relative to FULL_ALLOC)\n  uint256 public fee;\n  // address receiving the feeSplit portion of collected fees\n  address public feeReceiver;\n\n  // [DEPRECATED] trancheIdealWeightRatio ± idealRanges, used in updateIncentives\n  uint256 internal idealRange;\n  // period, in blocks, for progressively releasing harvested rewards to users\n  uint256 public releaseBlocksPeriod;\n  // amount of rewards sold in the last harvest (in `token`)\n  uint256 internal harvestedRewards;\n  // stkAave address\n  address internal constant stkAave = address(0x4da27a545c0c5B758a6BA100e3a049001de870f5);\n  // aave address\n  address internal constant AAVE = address(0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9);\n  // if deposits will be put directly in the strategy\n  bool public directDeposit;\n  // referral address of the strategy developer\n  address public referral;\n  // portion of collected fees sent to feeReceiver. The rest goes to owner()\n  uint256 public feeSplit;\n\n  // if Adaptive Yield Split is active\n  bool public isAYSActive;\n  // constant to represent 99% (for ADS AA ratio upper limit)\n  uint256 internal constant AA_RATIO_LIM_UP = 99000;\n  // constant to represent 50% (for ADS AA ratio lower limit)\n  uint256 internal constant AA_RATIO_LIM_DOWN = 50000;\n  // stkIDLE address\n  address internal constant STK_IDLE = address(0xaAC13a116eA7016689993193FcE4BadC8038136f);\n  // liquidity burned at first tranche deposit\n  uint256 internal constant MIN_LIQUIDITY = 10**3;\n\n  // Referral event\n  event Referral(uint256 _amount, address _ref);\n  // tolerance in underlyings when redeeming\n  uint256 internal liquidationTolerance;\n\n  // Add new variables here. For each storage slot\n  // used, reduce the __gap length by 1. \n  // ####################### \n  // Min apr ratio for AA tranches when using AYS\n  uint256 public minAprSplitAYS;\n  // Max strategy price decrease before triggering a default\n  uint256 public maxDecreaseDefault;\n  // The tolerance for the loss socialized so equally distributed between junior and senior tranches.\n  uint256 public lossToleranceBps;\n  // Amount of stkIDLE required to mint 1 underlying\n  uint256 internal stkIDLEPerUnderlying;\n  // Explicit flag for epoch variants using programmable borrower hooks.\n  // This lives in shared storage so upgrading prefunded epoch variants does not shift child storage.\n  bool public isProgrammableBorrower;\n  // annualized management fee. Max is MAX_FEE / 10\n  uint256 public managementFee;\n  // uint256 public test;\n\n\n\n  // ####################### \n  // This is empty reserved space in storage that is put \n  // in place in Upgradeable contracts. It allows us to \n  // freely add new state variables in the future without \n  // compromising the storage compatibility with existing \n  // deployments.\n  // The size of the __gap array is calculated so that the \n  // amount of storage used by a contract always adds up to \n  // always the same number, 50 in this case.\n  uint256[44] private __gap;\n  // uint256[43] private __gap; -> after adding `test`\n  // #######################\n  // IMPORTANT: Do not add any variables below `__gap`\n}\n"},{"file_path":"contracts/IdleCDOTranche.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.10;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n/// @dev ERC20 representing a tranche token\ncontract IdleCDOTranche is ERC20 {\n  // allowed minter address\n  address public minter;\n  // liquidity burned at first tranche deposit\n  uint256 internal constant MIN_LIQUIDITY = 10**3;\n\n  /// @param _name tranche name\n  /// @param _symbol tranche symbol\n  constructor(\n    string memory _name, // eg. IdleDAI\n    string memory _symbol // eg. IDLEDAI\n  ) ERC20(_name, _symbol) {\n    // minter is msg.sender which is IdleCDO (in initialize)\n    minter = msg.sender;\n  }\n\n  /// @param account that should receive the tranche tokens\n  /// @param amount of tranche tokens to mint\n  function mint(address account, uint256 amount) external {\n    require(msg.sender == minter, '6');\n    // burn MIN_LIQUIDITY on first tranche deposit\n    if (totalSupply() == 0) {\n      _mint(address(1), MIN_LIQUIDITY);\n      amount -= MIN_LIQUIDITY;\n    }\n    _mint(account, amount);\n  }\n\n  /// @param account that should have the tranche tokens burned\n  /// @param amount of tranche tokens to burn\n  function burn(address account, uint256 amount) external {\n    require(msg.sender == minter, '6');\n    _burn(account, amount);\n  }\n}\n"},{"file_path":"contracts/interfaces/IERC20Detailed.sol","source_code":"// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.10;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\ninterface IERC20Detailed is IERC20Upgradeable {\n  function name() external view returns(string memory);\n  function symbol() external view returns(string memory);\n  function decimals() external view returns(uint256);\n}\n"},{"file_path":"contracts/interfaces/IIdleCDOStrategy.sol","source_code":"// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.8.10;\n\ninterface IIdleCDOStrategy {\n  function strategyToken() external view returns(address);\n  function token() external view returns(address);\n  function tokenDecimals() external view returns(uint256);\n  function oneToken() external view returns(uint256);\n  function redeemRewards(bytes calldata _extraData) external returns(uint256[] memory);\n  function pullStkAAVE() external returns(uint256);\n  function price() external view returns(uint256);\n  function getRewardTokens() external view returns(address[] memory);\n  function deposit(uint256 _amount) external returns(uint256);\n  // _amount in `strategyToken`\n  function redeem(uint256 _amount) external returns(uint256);\n  // _amount in `token`\n  function redeemUnderlying(uint256 _amount) external returns(uint256);\n  function getApr() external view returns(uint256);\n}\n"},{"file_path":"contracts/interfaces/IProgrammableBorrower.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.10;\n\n/// @notice Hook surface exposed by programmable borrowers used by `IdleCDOEpochVariant`.\ninterface IProgrammableBorrower {\n  /// @notice Sync borrower-side accounting when a new epoch starts.\n  /// @param _pendingWithdraws Underlyings reserved for withdraw requests at epoch end.\n  function onStartEpoch(uint256 _pendingWithdraws) external;\n\n  /// @notice Free enough liquidity so IdleCDO can pull stop-epoch funds.\n  /// @param _amountRequired Total underlyings IdleCDO will transfer from the borrower.\n  /// @param _isRequestingAllFunds Whether IdleCDO is closing the pool and recalling all funds.\n  /// @return success False when the borrower ledger makes close-pool settlement a real default.\n  function onStopEpoch(uint256 _amountRequired, bool _isRequestingAllFunds) external returns (bool success);\n\n  /// @notice Return the total net interest currently due for the running epoch.\n  /// @dev This is the pool-facing stop-epoch value: borrower contractual interest plus paid\n  /// buffer interest plus positive vault PnL minus vault losses.\n  /// @return Interest amount owed right now.\n  function totalInterestDueNow() external view returns (uint256);\n\n  /// @notice Move accrued borrower interest into settled debt.\n  /// @dev Called only on success path after IdleCDO fronted the interest. This settles the full\n  /// contractual borrower-interest sleeve, independently from vault gains or losses.\n  function settleBorrowerInterest() external;\n\n  /// @notice Abort active epoch accounting after IdleCDO has defaulted the facility.\n  /// @dev Used only on the default path when `onStopEpoch` could not complete successfully.\n  function onDefault() external;\n}\n"},{"file_path":"contracts/interfaces/keyring/IKeyring.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.10;\n\ninterface IKeyring {\n  function checkCredential(uint256 policyId, address entity) external view returns (bool);\n}"},{"file_path":"contracts/strategies/idle/IdleCreditVault.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.10;\n\nimport \"../../interfaces/IIdleCDOStrategy.sol\";\nimport \"../../interfaces/IERC20Detailed.sol\";\n\nimport '@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol';\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\n\ninterface IIdleCDOEpochVariant {\n  function isEpochRunning() external view returns (bool);\n  function epochEndDate() external view returns (uint256);\n  function expectedEpochInterest() external view returns (uint256);\n  function pendingWithdrawFees() external view returns (uint256);\n  function fee() external view returns (uint256);\n  function getContractValue() external view returns (uint256);\n  function defaulted() external view returns (bool);\n}\n\nerror NotAllowed();\n\ncontract IdleCreditVault is\n  Initializable,\n  OwnableUpgradeable,\n  ERC20Upgradeable,\n  ReentrancyGuardUpgradeable,\n  IIdleCDOStrategy\n{\n  using SafeERC20Upgradeable for IERC20Detailed;\n\n  /// @notice underlying token address (pool currency for Clearpool)\n  address public override token;\n  /// @notice decimals of the underlying asset\n  uint256 public override tokenDecimals;\n  /// @notice one underlying token\n  uint256 public override oneToken;\n  /// @notice underlying ERC20 token contract (pool currency for Clearpool)\n  IERC20Detailed public underlyingToken;\n  /// @notice address of the IdleCDO\n  address public idleCDO;\n  /// @notice one year, used to calculate the APR\n  uint256 public constant YEAR = 365 days;\n  /// @notice latest saved apr, already scaled to include the buffer period\n  uint256 public lastApr;\n  /// @notice address of the borrower\n  address public borrower;\n  /// @notice address of the manager\n  address public manager;\n  /// @notice user withdraw requests\n  mapping (address => uint256) public withdrawsRequests;\n  /// @notice user instant withdraw requests\n  mapping (address => uint256) public instantWithdrawsRequests;\n  /// @notice total withdraw requests\n  uint256 public pendingWithdraws;\n  /// @notice pending instant withdraw requests\n  uint256 public pendingInstantWithdraws;\n  /// @notice counter for epoch deposits\n  uint256 public totEpochDeposits;\n  /// @notice flag to allow transfers\n  bool public canTransfer;\n  /// @notice last withdraw request epoch for a user\n  mapping (address => uint256) public lastWithdrawRequest;\n  /// @notice current epoch number\n  uint256 public epochNumber;\n  /// @notice unscaled apr\n  uint256 public unscaledApr;\n  /// @notice constant representing a 100% fee used for accounting\n  uint256 private constant FULL_ALLOC = 100_000;\n  /// @notice total principal for APR=0 requests in the current epoch\n  uint256 public apr0TotalPrincipal;\n  struct Apr0UserData {\n    uint256 principal;\n    uint256 principalEpoch;\n    uint256 settledPrincipal;\n    uint256 settledInterest;\n  }\n  /// @notice APR=0 withdraw data per user\n  mapping (address => Apr0UserData) public apr0Users;\n  /// @notice net APR=0 interest rate per epoch, scaled by 1e18\n  mapping (uint256 => uint256) public apr0RateByEpoch;\n  /// @notice default maximum allowed scaled apr\n  uint256 public constant DEFAULT_MAX_APR = 20e18;\n  /// @notice maximum allowed scaled apr, 0 disables the cap\n  uint256 public maxApr;\n\n  /// @custom:oz-upgrades-unsafe-allow constructor\n  constructor() {\n    token = address(1);\n  }\n\n  /// @notice can be only called once\n  /// @param _underlyingToken address of the underlying token (pool currency)\n  function initialize(\n    address _underlyingToken,\n    address _owner,\n    address _manager,\n    address _borrower,\n    string memory borrowerName,\n    uint256 _apr\n  ) public virtual initializer {\n    OwnableUpgradeable.__Ownable_init();\n    ReentrancyGuardUpgradeable.__ReentrancyGuard_init();\n    require(token == address(0), \"Token is already initialized\");\n\n    //----- // -------//\n    token = _underlyingToken;\n    underlyingToken = IERC20Detailed(token);\n    tokenDecimals = underlyingToken.decimals();\n    oneToken = 10**(tokenDecimals);\n    borrower = _borrower;\n    manager = _manager;\n    maxApr = DEFAULT_MAX_APR;\n    // on the first setup we set the lastApr equal to the unscaledApr\n    lastApr = _apr;\n    unscaledApr = _apr;\n\n    // name will be like: Pareto Credit Vault Borrower\n    // symbol will be like: Borrower\n    ERC20Upgradeable.__ERC20_init(\n      _concat(string(\"Pareto Credit Vault \"), borrowerName),\n      borrowerName\n    );\n    //------//-------//\n\n    transferOwnership(_owner);\n  }\n\n  /// @notice strategy token decimals\n  /// @dev equal to underlying token decimals\n  /// @return number of decimals\n  function decimals() public view override returns (uint8) {\n    return uint8(tokenDecimals);\n  }\n\n  /// @notice strategy token address\n  function strategyToken() external view override returns (address) {\n    return address(this);\n  }\n\n  /// @notice return strategy token price which is always 1\n  /// @return price in underlyings\n  function price() public view virtual override returns (uint256) {\n    return oneToken;\n  }\n\n  /// @notice current fixed apr for the epoch\n  function getApr() external view returns (uint256) {\n    return lastApr;\n  }\n\n  /// @notice set manager address\n  /// @param _manager address of the new manager\n  function setManager(address _manager) external onlyOwner {\n    manager = _manager;\n  }\n\n  /// @notice set borrower address\n  /// @param _borrower address of the new borrower\n  function setBorrower(address _borrower) external onlyOwner {\n    require(_borrower != address(0), \"IS_0\");\n    borrower = _borrower;\n  }\n\n  /// @notice set maximum allowed scaled apr, 0 disables the cap\n  /// @param _maxApr new max apr\n  function setMaxApr(uint256 _maxApr) external onlyOwner {\n    maxApr = _maxApr;\n  }\n\n  /// @notice set both the scaled and unscaled apr\n  /// @dev only cdo and manager can set the apr.\n  /// @param _unscaledApr unscaled apr\n  /// @param _apr scaled apr\n  function setAprs(uint256 _unscaledApr, uint256 _apr) external {\n    unscaledApr = _unscaledApr;\n    // here we also check that msg.sender is allowed\n    setApr(_apr);\n  }\n\n  /// @notice set the fixed apr\n  /// @dev only cdo and manager can set the apr. If manager manually set apr from \n  /// here it will not be scaled to include the buffer period\n  function setApr(uint256 _apr) public {\n    address _cdo = idleCDO;\n\n    // if cdo is not yet set we skip the check (this can happen only during the setup)\n    if (_cdo != address(0)) {\n      if (msg.sender != _cdo && msg.sender != manager) revert NotAllowed();\n    }\n    uint256 _maxApr = maxApr;\n    if (_maxApr != 0 && _apr > _maxApr) revert NotAllowed();\n    lastApr = _apr;\n  }\n\n  /// @notice request withdraw of underlying token from the vault\n  /// @dev we don't burn strategy tokens here, but we increase the withdraw requests\n  /// @param _amount number of tokens claimable by the user\n  /// @param _user address of the user\n  /// @param _principal principal amount backing the withdraw request\n  function requestWithdraw(uint256 _amount, address _user, uint256 _principal) external {\n    _onlyIdleCDO();\n    if (_amount == 0) return;\n    // burn strategy tokens from cdo (we don't burn future interest here, only the principal)\n    _burn(msg.sender, _principal);\n    // mint equal amount of strategy tokens to the user as receipt (interest included), useful in case of default\n    _mint(_user, _amount);\n    // Global amount that stopEpoch must source from borrower/strategy for all pending receipts.\n    pendingWithdraws += _amount;\n    // save the epoch of the last withdraw request (buffer + epochDuration is 1 epoch)\n    lastWithdrawRequest[_user] = epochNumber;\n    // APR=0 requests keep separate accounting and settle interest at stopEpoch.\n    // `_amount` here is the post-management-fee principal bucket for that flow.\n    if (unscaledApr == 0) {\n      _requestWithdrawApr0(_amount, _user);\n    } else {\n      // increase the withdraw requests for the user\n      withdrawsRequests[_user] += _amount;\n    }\n  }\n\n  /// @notice claim the withdraw request\n  /// @dev we burn the strategy tokens and transfer the underlying tokens\n  /// @param _user address of the user\n  /// @return amount number of tokens claimed\n  function claimWithdrawRequest(address _user) external returns (uint256 amount) {\n    _onlyIdleCDO();\n    // User should wait at least an epoch before claiming the withdraw. Once the epoch is over user can withdraw \n    // at any time even if a new epoch started. \n    // So if epochNumber is the same as the last withdraw request then we revert. Epoch number is increased at stopEpoch\n    // NOTE: If a user does not claim a withdraw request and instead requests another withdraw, he will have to wait\n    // for another epoch to claim both requests.\n    // NOTE 2: if borrower defaults, old withdraw requests can still be claimed\n    if (IIdleCDOEpochVariant(idleCDO).epochEndDate() != 0 && (epochNumber <= lastWithdrawRequest[_user])) {\n      revert NotAllowed();\n    }\n    // settle APR=0 requests once the related epoch has ended\n    _settleApr0(_user);\n    Apr0UserData storage _apr0User = apr0Users[_user];\n    // Claim includes:\n    // - settled APR0 principal from finalized epochs\n    // - still-open APR0 principal: if pool-close mode was used (_interest == 1), IdleCDO sets\n    //   epochEndDate = 0 and claims can be immediate, while _settleApr0 can still skip settlement\n    //   for the current request epoch (reqEpoch >= epochNumber).\n    // - settled APR0 interest\n    uint256 normalAmount = withdrawsRequests[_user];\n    uint256 apr0PrincipalAmount = _apr0User.settledPrincipal + _apr0User.principal;\n    uint256 apr0InterestAmount = _apr0User.settledInterest;\n    amount = normalAmount + apr0PrincipalAmount + apr0InterestAmount;\n    // burn strategy tokens 1:1 with the principal only (normal amount already includes interest)\n    _burn(_user, normalAmount + apr0PrincipalAmount);\n    withdrawsRequests[_user] = 0;\n    lastWithdrawRequest[_user] = 0;\n    if (apr0PrincipalAmount != 0 || apr0InterestAmount != 0) {\n      delete apr0Users[_user];\n    }\n    underlyingToken.safeTransfer(_user, amount);\n  }\n\n  /// @notice request instant withdraw of underlying token from the vault\n  /// @dev we burn strategy tokens here, and we increase the instant withdraw requests\n  /// @param _amount number of tokens to withdraw\n  /// @param _user address of the user\n  function requestInstantWithdraw(uint256 _amount, address _user) external {\n    _onlyIdleCDO();\n    // burn strategy tokens from cdo\n    _burn(msg.sender, _amount);\n  \n    // mint equal amount of strategy tokens to the user as receipt, useful in case of default\n    _mint(_user, _amount);\n\n    // increase the instant withdraw requests for the user\n    instantWithdrawsRequests[_user] += _amount;\n    // increase the total instant withdraw requests\n    pendingInstantWithdraws += _amount;\n  }\n\n  /// @notice claim the instant withdraw request\n  /// @dev we transfer the underlying tokens\n  /// @param _user address of the user\n  function claimInstantWithdrawRequest(address _user) external {\n    _onlyIdleCDO();\n    uint256 amount = instantWithdrawsRequests[_user];\n    // burn strategy tokens from user\n    _burn(_user, amount);\n\n    instantWithdrawsRequests[_user] = 0;\n    underlyingToken.safeTransfer(_user, amount);\n  }\n\n  /// @notice collect the instant withdraw funds\n  /// @dev only IdleCDO can call this function\n  /// @param _amount number of tokens to collect\n  function collectInstantWithdrawFunds(uint256 _amount) external {\n    _onlyIdleCDO();\n    pendingInstantWithdraws -= _amount;\n    underlyingToken.safeTransferFrom(idleCDO, address(this), _amount);\n  }\n\n  /// @notice collect the withdraw funds\n  /// @dev only IdleCDO can call this function\n  /// @param _amount number of tokens to collect\n  function collectWithdrawFunds(uint256 _amount) external {\n    _onlyIdleCDO();\n    pendingWithdraws -= _amount;\n    underlyingToken.safeTransferFrom(idleCDO, address(this), _amount);\n  }\n\n  /// @notice compute and apply APR=0 epoch deltas for stopEpoch\n  /// @param _interest stopEpoch override interest (0 = expected epoch interest, 1 = repay all)\n  /// @return _expInterest stopEpoch interest after APR0 adjustments\n  /// @return _adjPendingWithdrawFees pending withdraw fees after APR0 adjustments\n  function prepareStopEpochWithApr0(uint256 _interest) external returns (uint256 _expInterest, uint256 _adjPendingWithdrawFees) {\n    _onlyIdleCDO();\n    IIdleCDOEpochVariant _cdo = IIdleCDOEpochVariant(idleCDO);\n    uint256 _pendingFees = _cdo.pendingWithdrawFees();\n    uint256 _tvl = _cdo.getContractValue();\n    _expInterest = _interest > 1 ? _interest : _cdo.expectedEpochInterest();\n    _adjPendingWithdrawFees = _pendingFees;\n    // Principal currently waiting for withdraw that was requested while APR was 0,\n    // net of the upfront management fee charged at request time.\n    uint256 _principal = apr0TotalPrincipal;\n\n    // Fast path: no APR0 accounting needed.\n    if (_principal == 0) {\n      return (_expInterest, _adjPendingWithdrawFees);\n    }\n    // APR0 principal is only valid while APR is 0 for that request lifecycle.\n    if (unscaledApr != 0) {\n      revert NotAllowed();\n    }\n\n    uint256 _apr0NetInterest;\n    // APR0 allocation is computed only when stopEpoch receives a real override interest.\n    // _expectedInterest == 1 is the \"request all funds back\" sentinel and is handled in IdleCDO.\n    if (_expInterest > 1 && _expInterest > _pendingFees) {\n      // Remove already booked withdraw fees from the interest base before splitting.\n      uint256 _interestNetOfFees = _expInterest - _pendingFees;\n      // Total principal used for the pro-rata split:\n      // IdleCDO TVL (which excludes APR0 requested principal) + APR0 principal bucket.\n      uint256 _totalPrincipalForSplit = _tvl + _principal;\n      if (_totalPrincipalForSplit != 0) {\n        // APR0 users get a pro-rata share of realized interest.\n        uint256 _apr0InterestGross = _interestNetOfFees * _principal / _totalPrincipalForSplit;\n        if (_apr0InterestGross != 0) {\n          // Same fee model as normal withdraw interest.\n          uint256 _apr0Fee = _apr0InterestGross * _cdo.fee() / FULL_ALLOC;\n          _apr0NetInterest = _apr0InterestGross - _apr0Fee;\n          _adjPendingWithdrawFees += _apr0Fee;\n          _expInterest -= _apr0NetInterest;\n        }\n      }\n    }\n\n    // Finalize one-epoch APR0 interest for current epoch only.\n    if (_apr0NetInterest != 0) {\n      // Funds owed to withdraw requesters increase by APR0 net interest.\n      pendingWithdraws += _apr0NetInterest;\n      // Save per-epoch net rate; each APR0 request accrues exactly once on its request epoch.\n      apr0RateByEpoch[epochNumber] = (_apr0NetInterest * 1e18) / _principal;\n    }\n    // Close current APR0 bucket so it cannot accrue again on later stopEpoch calls.\n    apr0TotalPrincipal = 0;\n  }\n\n  /// @notice settle APR=0 requests for a user once their epoch is finalized\n  /// @param _user address of the user\n  function _settleApr0(address _user) internal {\n    Apr0UserData storage _apr0User = apr0Users[_user];\n    uint256 _principal = _apr0User.principal;\n    if (_principal == 0) {\n      return;\n    }\n    uint256 _reqEpoch = _apr0User.principalEpoch;\n    // Settle only after stopEpoch bumped epochNumber (ie after one full wait epoch).\n    if (_reqEpoch >= epochNumber) {\n      return;\n    }\n    // Move principal from \"open APR0 bucket\" to \"settled bucket\" (same principal, not duplicated).\n    _apr0User.settledPrincipal += _principal;\n    uint256 _rate = apr0RateByEpoch[_reqEpoch];\n    if (_rate != 0) {\n      // Convert per-epoch rate to claimable underlying interest.\n      _apr0User.settledInterest += (_principal * _rate) / 1e18;\n    }\n    _apr0User.principal = 0;\n    _apr0User.principalEpoch = 0;\n  }\n\n  function _requestWithdrawApr0(uint256 _amount, address _user) internal {\n    // Settle any previous APR0 request first, then start/update current epoch bucket.\n    _settleApr0(_user);\n    Apr0UserData storage _apr0User = apr0Users[_user];\n    if (_apr0User.principal == 0) {\n      _apr0User.principalEpoch = epochNumber;\n    }\n    _apr0User.principal += _amount;\n    // Epoch-level APR0 principal used only to compute stopEpoch APR0 pro-rata interest.\n    apr0TotalPrincipal += _amount;\n  }\n\n  /// @notice Send funds to the IdleCDO\n  /// @param _amount number of underlyings to transfer\n  function sendInterestAndDeposits(uint256 _amount) external {\n    _onlyIdleCDO();\n    IERC20Detailed(token).safeTransfer(idleCDO, _amount);\n  }\n\n  /// @notice Burn strategy tokens from the CDO\n  /// @param _amount number of strategy tokens (1:1 with underlyings) to burn\n  function burnStrategyTokens(uint256 _amount) external {\n    _onlyIdleCDO();\n    _burn(msg.sender, _amount);\n  }\n\n  /// @notice Get funds from IdleCDO and mint strategy tokens. Funds are not sent to the borrower here\n  /// @param _amount number of underlyings to transfer\n  function deposit(uint256 _amount)\n    external\n    virtual\n    override\n    returns (uint256) {\n    _onlyIdleCDO();\n    if (_amount > 0) {\n      underlyingToken.safeTransferFrom(msg.sender, address(this), _amount);\n      _mint(msg.sender, _amount);\n    }\n\n    if (IIdleCDOEpochVariant(idleCDO).isEpochRunning()) {\n      // deposit done on stopEpoch (before setting the var to false) so we reset the counter\n      totEpochDeposits = 0;\n      epochNumber += 1;\n    } else {\n      // deposit done between epochs so we increase the counter\n      totEpochDeposits += _amount;\n    }\n\n    return _amount;\n  }\n\n  /// @notice Mint strategy tokens to the CDO without moving underlyings\n  /// @dev Used for mid-epoch deposits that send funds directly to the borrower\n  function mintStrategyTokens(uint256 _amount) external {\n    _onlyIdleCDO();\n    _mint(msg.sender, _amount);\n  }\n  \n  /// @inheritdoc ERC20Upgradeable\n  /// @dev we don't allow transfers of strategy tokens normally, transfers are allowed only after a default\n  function _transfer(address sender, address recipient, uint256 amount) internal virtual override {\n    if (msg.sender != idleCDO && !canTransfer) {\n      revert NotAllowed();\n    }\n    super._transfer(sender, recipient, amount);\n  }\n\n  /// @notice set transferability of strategy tokens after a default\n  /// @dev Manager-controlled manual switch. Transfers stay disabled by default because\n  /// claims are address-bound and moving receipts can sever redeemability.\n  function setCanTransfer(bool _canTransfer) external {\n    if (msg.sender != manager || !IIdleCDOEpochVariant(idleCDO).defaulted()) {\n      revert NotAllowed();\n    }\n    canTransfer = _canTransfer;\n  }\n\n  /// @notice allow to update whitelisted address\n  function setWhitelistedCDO(address _cdo) external onlyOwner {\n    require(_cdo != address(0), \"IS_0\");\n    idleCDO = _cdo;\n  }\n\n  /// @notice Emergency method to rescue funds\n  /// @param _token address of the token to transfer\n  /// @param value amount of `_token` to transfer\n  /// @param _to receiver address\n  function transferToken(address _token, uint256 value, address _to) external onlyOwner {\n    IERC20Detailed(_token).safeTransfer(_to, value);\n  }\n\n  /// @notice Modifier to make sure that caller os only the idleCDO contract\n  function _onlyIdleCDO() internal view {\n    if (msg.sender != idleCDO) {\n      revert NotAllowed();\n    }\n  }\n\n  /// @notice concat 2 strings in a single one\n  /// @param a first string\n  /// @param b second string\n  /// @return new string with a and b concatenated\n  function _concat(string memory a, string memory b) internal pure returns (string memory) {\n    return string(abi.encodePacked(a, b));\n  }\n\n  /// @notice Not used as redeems happens only via requestWithdraw and requestInstantWithdraw\n  function redeem(uint256 _amount)\n    external\n    override\n    returns (uint256) {}\n\n  /// @notice Not used as redeems happens only via requestWithdraw and requestInstantWithdraw\n  function redeemUnderlying(uint256)\n    external\n    returns (uint256) {}\n\n  /// @notice not used in this strategy\n  function pullStkAAVE() \n    external \n    pure \n    override \n    returns (uint256) {}\n\n  /// @notice not used for this strategy\n  function getRewardTokens()\n    external\n    view\n    override\n    returns (address[] memory) {}\n\n  /// @notice not used for this strategy\n  function redeemRewards(bytes calldata)\n    external\n    override\n    returns (uint256[] memory rewards) {}\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"AmountTooHigh","type":"error"},{"inputs":[],"name":"ContractLimitReached","type":"error"},{"inputs":[],"name":"Default","type":"error"},{"inputs":[],"name":"Is0","type":"error"},{"inputs":[],"name":"NotAllowed","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"interest","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fees","type":"uint256"}],"name":"AccrueInterest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"funds","type":"uint256"}],"name":"BorrowerDefault","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"_ref","type":"address"}],"name":"Referral","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"AATranche","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BBTranche","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FULL_ALLOC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_TRANCHE_TOKEN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"_setLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"allowAAWithdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowAAWithdrawRequest","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowBBWithdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowBBWithdrawRequest","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allowInstantWithdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bufferPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimInstantWithdrawRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimWithdrawRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaulted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositAA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositBB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_tranche","type":"address"}],"name":"depositDuringEpoch","outputs":[{"internalType":"uint256","name":"_minted","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"directDeposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"disableInstantWithdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emergencyShutdown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"epochDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochEndDate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"expectedEpochInterest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeSplit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tranche","type":"address"}],"name":"getApr","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getContractValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentAARatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_withdrawRequests","type":"uint256"},{"internalType":"uint256","name":"_instantWithdrawRequests","type":"uint256"}],"name":"getFundsFromBorrower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getInstantWithdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"governanceRecoveryFund","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_limit","type":"uint256"},{"internalType":"address","name":"_guardedToken","type":"address"},{"internalType":"address","name":"_governanceFund","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"uint256","name":"_trancheAPRSplitRatio","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"instantWithdrawAprDelta","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"instantWithdrawDeadline","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"instantWithdrawDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isAYSActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isDepositDuringEpochDisabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isEpochRunning","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isInterestMinted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isProgrammableBorrower","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"isWalletAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keyring","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keyringPolicyId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastEpochApr","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastEpochInterest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastNAVAA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastNAVBB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestHarvestBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"limit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lossToleranceBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"managementFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxDecreaseDefault","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_tranche","type":"address"}],"name":"maxWithdrawable","outputs":[{"internalType":"uint256","name":"currentUnderlyings","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minAprSplitAYS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oneToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingWithdrawFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceAA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceBB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebalancer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referral","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"releaseBlocksPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_tranche","type":"address"}],"name":"requestWithdraw","outputs":[{"internalType":"uint256","name":"_underlyings","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"restoreOperations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"sendFundsToBorrower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_epochDuration","type":"uint256"},{"internalType":"uint256","name":"_bufferPeriod","type":"uint256"}],"name":"setEpochParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeReceiver","type":"address"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"uint256","name":"_feeSplit","type":"uint256"},{"internalType":"uint256","name":"_managementFee","type":"uint256"}],"name":"setFeeParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guardian","type":"address"}],"name":"setGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_delay","type":"uint256"},{"internalType":"uint256","name":"_aprDelta","type":"uint256"},{"internalType":"bool","name":"_disable","type":"bool"}],"name":"setInstantWithdrawParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_active","type":"bool"}],"name":"setIsAYSActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isDisabled","type":"bool"}],"name":"setIsDepositDuringEpochDisabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isMinted","type":"bool"}],"name":"setIsInterestMinted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isProgrammable","type":"bool"}],"name":"setIsProgrammableBorrower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_keyring","type":"address"},{"internalType":"uint256","name":"_keyringPolicyId","type":"uint256"}],"name":"setKeyringParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_diffBps","type":"uint256"}],"name":"setLossToleranceBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_aprSplit","type":"uint256"}],"name":"setMinAprSplitAYS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newApr","type":"uint256"},{"internalType":"uint256","name":"_interest","type":"uint256"}],"name":"stopEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newApr","type":"uint256"},{"internalType":"uint256","name":"_interest","type":"uint256"},{"internalType":"uint256","name":"_duration","type":"uint256"},{"internalType":"uint256","name":"_lossAmount","type":"uint256"}],"name":"stopEpochWithDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"strategy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strategyToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trancheAPRSplitRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tranche","type":"address"}],"name":"tranchePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transferToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unclaimedFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlentPerc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateAccounting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tranche","type":"address"}],"name":"virtualPrice","outputs":[{"internalType":"uint256","name":"_virtualPrice","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_tranche","type":"address"}],"name":"writeOffDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":null}