{"file_path":"contracts/DebtToken.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {Initializable} from \"./dependencies/openzeppelin-upgradeable/proxy/utils/Initializable.sol\";\nimport {IERC20} from \"./dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {Manageable} from \"./access/Manageable.sol\";\nimport {ReentrancyGuardDeprecated} from \"./utils/ReentrancyGuardDeprecated.sol\";\nimport {ReentrancyGuardTransient} from \"./utils/ReentrancyGuardTransient.sol\";\nimport {TokenHolder} from \"./utils/TokenHolder.sol\";\nimport {WadRayMath} from \"./lib/WadRayMath.sol\";\nimport {IMasterOracle} from \"./interfaces/external/IMasterOracle.sol\";\nimport {IPool} from \"./interfaces/IPool.sol\";\nimport {ISyntheticToken} from \"./interfaces/ISyntheticToken.sol\";\nimport {IRewardsDistributor} from \"./interfaces/IRewardsDistributor.sol\";\nimport {DebtTokenStorageV2} from \"./storage/DebtTokenStorage.sol\";\n\nerror SyntheticDoesNotExist();\nerror SyntheticIsInactive();\nerror DebtTokenInactive();\nerror NameIsNull();\nerror SymbolIsNull();\nerror PoolIsNull();\nerror SyntheticIsNull();\nerror AllowanceNotSupported();\nerror ApprovalNotSupported();\nerror AmountIsZero();\nerror NotEnoughCollateral();\nerror DebtLowerThanTheFloor();\nerror RemainingDebtIsLowerThanTheFloor();\nerror TransferNotSupported();\nerror BurnFromNullAddress();\nerror BurnAmountExceedsBalance();\nerror MintToNullAddress();\nerror SurpassMaxDebtSupply();\nerror NewValueIsSameAsCurrent();\nerror SenderIsNotSmartFarmingManager();\n\n/**\n * @title Non-transferable token that represents users' debts\n */\ncontract DebtToken is\n    Initializable,\n    ReentrancyGuardDeprecated,\n    ReentrancyGuardTransient,\n    TokenHolder,\n    Manageable,\n    DebtTokenStorageV2\n{\n    using WadRayMath for uint256;\n\n    string public constant VERSION = \"1.4.1\";\n\n    uint256 public constant SECONDS_PER_YEAR = 365.25 days;\n    uint256 private constant HUNDRED_PERCENT = 1e18;\n\n    /// @notice Emitted when synthetic's debt is repaid\n    event DebtRepaid(address indexed payer, address indexed account, uint256 amount, uint256 repaid, uint256 fee);\n\n    /// @notice Emitted when active flag is updated\n    event DebtTokenActiveUpdated(bool newActive);\n\n    /// @notice Emitted when interest rate is updated\n    event InterestRateUpdated(uint256 oldInterestRate, uint256 newInterestRate);\n\n    /// @notice Emitted when max total supply is updated\n    event MaxTotalSupplyUpdated(uint256 oldMaxTotalSupply, uint256 newMaxTotalSupply);\n\n    /// @notice Emitted when synthetic token is issued\n    event SyntheticTokenIssued(\n        address indexed account,\n        address indexed to,\n        uint256 amount,\n        uint256 issued,\n        uint256 fee\n    );\n\n    /**\n     * @dev Throws if sender is not SmartFarmingManager\n     */\n    modifier onlyIfSmartFarmingManager() {\n        if (_msgSender() != address(pool.smartFarmingManager())) revert SenderIsNotSmartFarmingManager();\n        _;\n    }\n\n    /**\n     * @dev Throws if synthetic token doesn't exist\n     */\n    modifier onlyIfSyntheticTokenExists() {\n        if (!pool.doesSyntheticTokenExist(syntheticToken)) revert SyntheticDoesNotExist();\n        _;\n    }\n\n    /**\n     * @dev Throws if debt token isn't enabled\n     */\n    modifier onlyIfDebtTokenIsActive() {\n        if (!isActive) revert DebtTokenInactive();\n        _;\n    }\n\n    /**\n     * @dev Throws if synthetic token isn't enabled\n     */\n    modifier onlyIfSyntheticTokenIsActive() {\n        if (!syntheticToken.isActive()) revert SyntheticIsInactive();\n        _;\n    }\n\n    /**\n     * @notice Update reward contracts' states\n     * @dev Should be called before balance changes (i.e. mint/burn)\n     */\n    modifier updateRewardsBeforeMintOrBurn(address account_) {\n        address[] memory _rewardsDistributors = pool.getRewardsDistributors();\n        uint256 _length = _rewardsDistributors.length;\n        for (uint256 i; i < _length; ++i) {\n            IRewardsDistributor(_rewardsDistributors[i]).updateBeforeMintOrBurn(this, account_);\n        }\n        _;\n    }\n\n    constructor() {\n        _disableInitializers();\n    }\n\n    function initialize(\n        string calldata name_,\n        string calldata symbol_,\n        IPool pool_,\n        ISyntheticToken syntheticToken_,\n        uint256 interestRate_,\n        uint256 maxTotalSupply_\n    ) external initializer {\n        if (bytes(name_).length == 0) revert NameIsNull();\n        if (bytes(symbol_).length == 0) revert SymbolIsNull();\n        if (address(pool_) == address(0)) revert PoolIsNull();\n        if (address(syntheticToken_) == address(0)) revert SyntheticIsNull();\n\n        __Manageable_init(pool_);\n\n        name = name_;\n        symbol = symbol_;\n        decimals = syntheticToken_.decimals();\n        syntheticToken = syntheticToken_;\n        lastTimestampAccrued = block.timestamp;\n        debtIndex = 1e18;\n        interestRate = interestRate_;\n        maxTotalSupply = maxTotalSupply_;\n        isActive = true;\n    }\n\n    /**\n     * @notice Accrue interest over debt supply\n     */\n    function accrueInterest() public override {\n        (\n            uint256 _interestAmountAccrued,\n            uint256 _debtIndex,\n            uint256 _lastTimestampAccrued\n        ) = _calculateInterestAccrual();\n\n        if (block.timestamp == _lastTimestampAccrued) {\n            return;\n        }\n\n        lastTimestampAccrued = block.timestamp;\n\n        if (_interestAmountAccrued > 0) {\n            totalSupply_ += _interestAmountAccrued;\n            debtIndex = _debtIndex;\n\n            // Note: Address states where minting will fail (e.g. the token is inactive, it reached max supply, etc)\n            try syntheticToken.mint(pool.feeCollector(), _interestAmountAccrued + pendingInterestFee) {\n                pendingInterestFee = 0;\n            } catch {\n                pendingInterestFee += _interestAmountAccrued;\n            }\n        }\n    }\n\n    /// @inheritdoc IERC20\n    function allowance(address /*owner_*/, address /*spender_*/) external pure override returns (uint256) {\n        revert AllowanceNotSupported();\n    }\n\n    /// @inheritdoc IERC20\n    // solhint-disable-next-line\n    function approve(address /*spender_*/, uint256 /*amount_*/) external override returns (bool) {\n        revert ApprovalNotSupported();\n    }\n\n    /**\n     * @notice Get the updated (principal + interest) user's debt\n     */\n    function balanceOf(address account_) public view override returns (uint256) {\n        uint256 _principal = principalOf[account_];\n        if (_principal == 0) {\n            return 0;\n        }\n\n        (, uint256 _debtIndex, ) = _calculateInterestAccrual();\n\n        // Note: The `debtIndex / debtIndexOf` gives the interest to apply to the principal amount\n        return (_principal * _debtIndex) / debtIndexOf[account_];\n    }\n\n    /**\n     * @notice Burn debt token\n     * @param from_ The account to burn from\n     * @param amount_ The amount to burn\n     */\n    function burnFor(address from_, uint256 amount_) external override onlyPool {\n        _burn(from_, amount_);\n    }\n\n    /**\n     * @notice Collect pending interest fee if any\n     */\n    function collectPendingInterestFee() external {\n        uint256 _pendingInterestFee = pendingInterestFee;\n        if (_pendingInterestFee > 0) {\n            syntheticToken.mint(pool.feeCollector(), _pendingInterestFee);\n            pendingInterestFee = 0;\n        }\n    }\n\n    /**\n     * @notice Lock collateral and mint synthetic token\n     * @param amount_ The amount to mint\n     * @param to_ The beneficiary account\n     * @return _issued The amount issued after fees\n     * @return _fee The fee amount collected\n     */\n    function issue(\n        uint256 amount_,\n        address to_\n    )\n        external\n        override\n        whenNotShutdown\n        nonReentrant\n        onlyIfSyntheticTokenExists\n        returns (uint256 _issued, uint256 _fee)\n    {\n        if (amount_ == 0) revert AmountIsZero();\n\n        accrueInterest();\n\n        address _msgSender = _msgSender();\n        IPool _pool = pool;\n        ISyntheticToken _syntheticToken = syntheticToken;\n\n        (, , , , uint256 _issuableInUsd) = _pool.debtPositionOf(_msgSender);\n\n        IMasterOracle _masterOracle = _pool.masterOracle();\n\n        if (amount_ > _masterOracle.quoteUsdToToken(address(_syntheticToken), _issuableInUsd)) {\n            revert NotEnoughCollateral();\n        }\n\n        _mint(_pool, _masterOracle, _msgSender, amount_);\n\n        (_issued, _fee) = quoteIssueOut(amount_);\n        if (_fee > 0) {\n            _syntheticToken.mint(_pool.feeCollector(), _fee);\n        }\n        _syntheticToken.mint(to_, _issued);\n\n        emit SyntheticTokenIssued(_msgSender, to_, amount_, _issued, _fee);\n    }\n\n    /**\n     * @notice Issue synth without checking collateral and without minting debt tokens\n     * @dev The healthy of outcome position must be done afterhand\n     * @param to_ The beneficiary account\n     * @param amount_ The amount to mint\n     * @return _issued The amount issued after fees\n     * @return _fee The fee amount collected\n     */\n    function flashIssue(\n        address to_,\n        uint256 amount_\n    )\n        external\n        override\n        onlyIfSmartFarmingManager\n        whenNotShutdown\n        nonReentrant\n        onlyIfSyntheticTokenExists\n        onlyIfDebtTokenIsActive\n        returns (uint256 _issued, uint256 _fee)\n    {\n        if (amount_ == 0) revert AmountIsZero();\n\n        accrueInterest();\n\n        ISyntheticToken _syntheticToken = syntheticToken;\n\n        (_issued, _fee) = quoteIssueOut(amount_);\n        if (_fee > 0) {\n            _syntheticToken.mint(pool.feeCollector(), _fee);\n        }\n        _syntheticToken.mint(to_, _issued);\n    }\n\n    /**\n     * @notice Get updated pending interest fee\n     */\n    function getPendingInterestFee() external view returns (uint256 _stored, uint256 _current) {\n        (uint256 _interestAmountAccrued, , ) = _calculateInterestAccrual();\n        uint256 _pendingInterestFee = pendingInterestFee;\n        return (_pendingInterestFee, _pendingInterestFee + _interestAmountAccrued);\n    }\n\n    /**\n     * @notice Return interest rate (in percent) per second\n     */\n    function interestRatePerSecond() public view override returns (uint256) {\n        return interestRate / SECONDS_PER_YEAR;\n    }\n\n    /**\n     * @notice onlySmartFarmingManager:: Mint `amount_` of debtToken at `to_`.\n     * @param to_ Receiver address\n     * @param amount_ Token amount to mint\n     */\n    function mint(\n        address to_,\n        uint256 amount_\n    )\n        external\n        override\n        onlyIfSmartFarmingManager\n        whenNotShutdown\n        nonReentrant\n        onlyIfSyntheticTokenExists\n        onlyIfSyntheticTokenIsActive\n    {\n        accrueInterest();\n\n        IPool _pool = pool;\n\n        _mint(_pool, _pool.masterOracle(), to_, amount_);\n    }\n\n    /**\n     * @notice Quote gross `_amount` to issue `amountToIssue_` synthetic tokens\n     * @param amountToIssue_ Synth to issue\n     * @return _amount Gross amount\n     * @return _fee The fee amount to collect\n     */\n    function quoteIssueIn(uint256 amountToIssue_) external view override returns (uint256 _amount, uint256 _fee) {\n        uint256 _issueFee = pool.feeProvider().issueFee();\n        if (_issueFee == 0) {\n            return (amountToIssue_, _fee);\n        }\n\n        _amount = amountToIssue_.wadDiv(HUNDRED_PERCENT - _issueFee);\n        _fee = _amount - amountToIssue_;\n    }\n\n    /**\n     * @notice Quote synthetic tokens `_amountToIssue` by using gross `_amount`\n     * @param amount_ Gross amount\n     * @return _amountToIssue Synth to issue\n     * @return _fee The fee amount to collect\n     */\n    function quoteIssueOut(uint256 amount_) public view override returns (uint256 _amountToIssue, uint256 _fee) {\n        uint256 _issueFee = pool.feeProvider().issueFee();\n        if (_issueFee == 0) {\n            return (amount_, _fee);\n        }\n\n        _fee = amount_.wadMul(_issueFee);\n        _amountToIssue = amount_ - _fee;\n    }\n\n    /**\n     * @notice Quote synthetic token `_amount` need to repay `amountToRepay_` debt\n     * @param amountToRepay_ Debt amount to repay\n     * @return _amount Gross amount\n     * @return _fee The fee amount to collect\n     */\n    function quoteRepayIn(uint256 amountToRepay_) public view override returns (uint256 _amount, uint256 _fee) {\n        uint256 _repayFee = pool.feeProvider().repayFee();\n        if (_repayFee == 0) {\n            return (amountToRepay_, _fee);\n        }\n\n        _fee = amountToRepay_.wadMul(_repayFee);\n        _amount = amountToRepay_ + _fee;\n    }\n\n    /**\n     * @notice Quote debt `_amountToRepay` by burning `_amount` synthetic tokens\n     * @param amount_ Gross amount\n     * @return _amountToRepay Debt amount to repay\n     * @return _fee The fee amount to collect\n     */\n    function quoteRepayOut(uint256 amount_) public view override returns (uint256 _amountToRepay, uint256 _fee) {\n        uint256 _repayFee = pool.feeProvider().repayFee();\n        if (_repayFee == 0) {\n            return (amount_, _fee);\n        }\n\n        _amountToRepay = amount_.wadDiv(HUNDRED_PERCENT + _repayFee);\n        _fee = amount_ - _amountToRepay;\n    }\n\n    /**\n     * @notice Send synthetic token to decrease debt\n     * @dev The _msgSender() is the payer and the account beneficed\n     * @param onBehalfOf_ The account that will have debt decreased\n     * @param amount_ The amount of synthetic token to burn (this is the gross amount, the repay fee will be subtracted from it)\n     * @return _repaid The amount repaid after fees\n     */\n    function repay(\n        address onBehalfOf_,\n        uint256 amount_\n    )\n        external\n        override\n        whenNotShutdown\n        nonReentrant\n        onlyIfSyntheticTokenExists\n        returns (uint256 _repaid, uint256 _fee)\n    {\n        if (amount_ == 0) revert AmountIsZero();\n\n        accrueInterest();\n\n        address _msgSender = _msgSender();\n        IPool _pool = pool;\n        ISyntheticToken _syntheticToken = syntheticToken;\n\n        (_repaid, _fee) = quoteRepayOut(amount_);\n        if (_fee > 0) {\n            _syntheticToken.seize(_msgSender, _pool.feeCollector(), _fee);\n        }\n\n        uint256 _debtFloorInUsd = _pool.debtFloorInUsd();\n        if (_debtFloorInUsd > 0) {\n            uint256 _newDebtInUsd = _pool.masterOracle().quoteTokenToUsd(\n                address(_syntheticToken),\n                balanceOf(onBehalfOf_) - _repaid\n            );\n            if (_newDebtInUsd > 0 && _newDebtInUsd < _debtFloorInUsd) {\n                revert RemainingDebtIsLowerThanTheFloor();\n            }\n        }\n\n        _syntheticToken.burnFor(_msgSender, _repaid);\n        _burn(onBehalfOf_, _repaid);\n\n        emit DebtRepaid(_msgSender, onBehalfOf_, amount_, _repaid, _fee);\n    }\n\n    /**\n     * @notice Send synthetic token to decrease debt\n     * @dev This function helps users to no leave debt dust behind\n     * @param onBehalfOf_ The account that will have debt decreased\n     * @return _repaid The amount repaid after fees\n     * @return _fee The fee amount collected\n     */\n    function repayAll(\n        address onBehalfOf_\n    )\n        external\n        override\n        whenNotShutdown\n        nonReentrant\n        onlyIfSyntheticTokenExists\n        returns (uint256 _repaid, uint256 _fee)\n    {\n        accrueInterest();\n\n        _repaid = balanceOf(onBehalfOf_);\n        if (_repaid == 0) revert AmountIsZero();\n\n        address _msgSender = _msgSender();\n        ISyntheticToken _syntheticToken = syntheticToken;\n\n        uint256 _amount;\n        (_amount, _fee) = quoteRepayIn(_repaid);\n\n        if (_fee > 0) {\n            _syntheticToken.seize(_msgSender, pool.feeCollector(), _fee);\n        }\n\n        _syntheticToken.burnFor(_msgSender, _repaid);\n        _burn(onBehalfOf_, _repaid);\n\n        emit DebtRepaid(_msgSender, onBehalfOf_, _amount, _repaid, _fee);\n    }\n\n    /**\n     * @notice Return the total supply\n     */\n    function totalSupply() external view override returns (uint256) {\n        (uint256 _interestAmountAccrued, , ) = _calculateInterestAccrual();\n        return totalSupply_ + _interestAmountAccrued;\n    }\n\n    /// @inheritdoc IERC20\n    // solhint-disable-next-line\n    function transfer(address /*recipient_*/, uint256 /*amount_*/) external override returns (bool) {\n        revert TransferNotSupported();\n    }\n\n    /// @inheritdoc IERC20\n    // solhint-disable-next-line\n    function transferFrom(\n        address /*sender_*/,\n        address /*recipient_*/,\n        uint256 /*amount_*/\n    ) external override returns (bool) {\n        revert TransferNotSupported();\n    }\n\n    /**\n     * @notice Destroy `amount` tokens from `account`, reducing the\n     * total supply\n     */\n    function _burn(address account_, uint256 amount_) private updateRewardsBeforeMintOrBurn(account_) {\n        if (account_ == address(0)) revert BurnFromNullAddress();\n\n        uint256 _accountBalance = balanceOf(account_);\n        if (_accountBalance < amount_) revert BurnAmountExceedsBalance();\n\n        uint256 _totalSupply = totalSupply_;\n        unchecked {\n            principalOf[account_] = _accountBalance - amount_;\n            debtIndexOf[account_] = debtIndex;\n            totalSupply_ = amount_ < _totalSupply ? _totalSupply - amount_ : 0;\n        }\n\n        emit Transfer(account_, address(0), amount_);\n\n        // Remove this token from the debt tokens list if the sender's balance goes to zero\n        if (amount_ > 0 && balanceOf(account_) == 0) {\n            pool.removeFromDebtTokensOfAccount(account_);\n        }\n    }\n\n    /**\n     * @notice Calculate interest to accrue\n     * @dev This util function avoids code duplication across `balanceOf` and `accrueInterest`\n     * @return _interestAmountAccrued The total amount of debt tokens accrued\n     * @return _debtIndex The new `debtIndex` value\n     */\n    function _calculateInterestAccrual()\n        private\n        view\n        returns (uint256 _interestAmountAccrued, uint256 _debtIndex, uint256 _lastTimestampAccrued)\n    {\n        _lastTimestampAccrued = lastTimestampAccrued;\n        _debtIndex = debtIndex;\n\n        if (block.timestamp > _lastTimestampAccrued) {\n            uint256 _interestRateToAccrue = interestRatePerSecond() * (block.timestamp - _lastTimestampAccrued);\n            if (_interestRateToAccrue > 0) {\n                _interestAmountAccrued = _interestRateToAccrue.wadMul(totalSupply_);\n                _debtIndex += _interestRateToAccrue.wadMul(_debtIndex);\n            }\n        }\n    }\n\n    /**\n     * @dev Create `amount` tokens and assigns them to `account`, increasing\n     * the total supply\n     */\n    function _mint(\n        IPool pool_,\n        IMasterOracle masterOracle_,\n        address account_,\n        uint256 amount_\n    ) private onlyIfDebtTokenIsActive updateRewardsBeforeMintOrBurn(account_) {\n        if (account_ == address(0)) revert MintToNullAddress();\n\n        uint256 _debtFloorInUsd = pool_.debtFloorInUsd();\n        uint256 _balanceBefore = balanceOf(account_);\n\n        if (\n            _debtFloorInUsd > 0 &&\n            masterOracle_.quoteTokenToUsd(address(syntheticToken), _balanceBefore + amount_) < _debtFloorInUsd\n        ) {\n            revert DebtLowerThanTheFloor();\n        }\n\n        totalSupply_ += amount_;\n        if (totalSupply_ > maxTotalSupply) revert SurpassMaxDebtSupply();\n\n        principalOf[account_] = _balanceBefore + amount_;\n        debtIndexOf[account_] = debtIndex;\n        emit Transfer(address(0), account_, amount_);\n\n        //  Add this token to the debt tokens list if the recipient is receiving it for the 1st time\n        if (_balanceBefore == 0 && amount_ > 0) {\n            pool.addToDebtTokensOfAccount(account_);\n        }\n    }\n\n    /// @inheritdoc TokenHolder\n    // solhint-disable-next-line no-empty-blocks\n    function _requireCanSweep() internal view override onlyGovernor {}\n\n    /**\n     * @notice Update max total supply\n     */\n    function updateMaxTotalSupply(uint256 newMaxTotalSupply_) external override onlyGovernor {\n        uint256 _currentMaxTotalSupply = maxTotalSupply;\n        if (newMaxTotalSupply_ == _currentMaxTotalSupply) revert NewValueIsSameAsCurrent();\n        emit MaxTotalSupplyUpdated(_currentMaxTotalSupply, newMaxTotalSupply_);\n        maxTotalSupply = newMaxTotalSupply_;\n    }\n\n    /**\n     * @notice Update interest rate (APR)\n     */\n    function updateInterestRate(uint256 newInterestRate_) external override onlyGovernor {\n        accrueInterest();\n        uint256 _currentInterestRate = interestRate;\n        if (newInterestRate_ == _currentInterestRate) revert NewValueIsSameAsCurrent();\n        emit InterestRateUpdated(_currentInterestRate, newInterestRate_);\n        interestRate = newInterestRate_;\n    }\n\n    /**\n     * @notice Enable/Disable the Debt Token\n     */\n    function toggleIsActive() external override onlyGovernor {\n        bool _newIsActive = !isActive;\n        emit DebtTokenActiveUpdated(_newIsActive);\n        isActive = _newIsActive;\n    }\n}\n","deployed_bytecode":"0x608060405260043610610233575f3560e01c806374e87e1e1161012d578063afcff50f116100aa578063d25933291161006e578063d25933291461066f578063d38f2ba914610683578063dd62ed3e146106a2578063e6a69ab8146106c1578063ffa1ad74146106d857610251565b8063afcff50f146105e9578063b696a6ad146105fd578063bb8c631f1461061c578063bfa1765614610631578063c9dc4b4d1461065057610251565b80638e84ab22116100f15780638e84ab221461057f57806395d89b41146105935780639cc820da146105a7578063a6afed95146105bb578063a9059cbb146105cf57610251565b806374e87e1e146104ee578063752a50a61461050d5780637c27383b1461052c5780637c3a00fd1461054b5780638230ecd61461056057610251565b806323b872dd116101bb57806340c10f191161017f57806340c10f191461045d5780634754d1761461047c578063565f3d4f1461049b57806362c06767146104b057806370a08231146104cf57610251565b806323b872dd146103c45780632ab4d052146103e35780632d4aeea1146103f8578063313ce5671461041757806336248ab41461044957610251565b8063172f50a411610202578063172f50a41461030e57806318160ddd1461032f5780631dd319cb1461035157806322867d781461037057806322f3e2d4146103a457610251565b806306fdde031461026a578063095ea7b3146102945780630c340a24146102c357806316f0115b146102ef57610251565b3661025157604051636436c22d60e11b815260040160405180910390fd5b60405163a0152e6360e01b815260040160405180910390fd5b348015610275575f80fd5b5061027e610708565b60405161028b9190613424565b60405180910390f35b34801561029f575f80fd5b506102b36102ae36600461346a565b610794565b604051901515815260200161028b565b3480156102ce575f80fd5b506102d76107ae565b6040516001600160a01b03909116815260200161028b565b3480156102fa575f80fd5b506002546102d7906001600160a01b031681565b348015610319575f80fd5b5061032d610328366004613494565b61081e565b005b34801561033a575f80fd5b506103436108c0565b60405190815260200161028b565b34801561035c575f80fd5b5061032d61036b36600461346a565b6108e2565b34801561037b575f80fd5b5061038f61038a36600461346a565b61092b565b6040805192835260208301919091520161028b565b3480156103af575f80fd5b50603d546102b390600160a01b900460ff1681565b3480156103cf575f80fd5b506102b36103de3660046134ab565b610dc2565b3480156103ee575f80fd5b5061034360385481565b348015610403575f80fd5b5061038f610412366004613494565b610ddc565b348015610422575f80fd5b50603d5461043790600160a81b900460ff1681565b60405160ff909116815260200161028b565b348015610454575f80fd5b5061032d610ef2565b348015610468575f80fd5b5061032d61047736600461346a565b610fc4565b348015610487575f80fd5b5061038f610496366004613494565b6112b1565b3480156104a6575f80fd5b50610343603a5481565b3480156104bb575f80fd5b5061032d6104ca3660046134ab565b6113b5565b3480156104da575f80fd5b506103436104e93660046134e9565b6113ee565b3480156104f9575f80fd5b5061032d610508366004613542565b611458565b348015610518575f80fd5b5061032d610527366004613494565b611639565b348015610537575f80fd5b5061038f6105463660046134e9565b6116e3565b348015610556575f80fd5b50610343603c5481565b34801561056b575f80fd5b50603d546102d7906001600160a01b031681565b34801561058a575f80fd5b5061038f611a16565b34801561059e575f80fd5b5061027e611a3e565b3480156105b2575f80fd5b50610343611a4b565b3480156105c6575f80fd5b5061032d611a5e565b3480156105da575f80fd5b506102b36103de36600461346a565b3480156105f4575f80fd5b506102d7611b91565b348015610608575f80fd5b5061038f6106173660046135e2565b611bd8565b348015610627575f80fd5b50610343603b5481565b34801561063c575f80fd5b5061038f61064b36600461346a565b612031565b34801561065b575f80fd5b5061038f61066a366004613494565b6123a9565b34801561067a575f80fd5b5061032d6124a5565b34801561068e575f80fd5b5061038f61069d366004613494565b612546565b3480156106ad575f80fd5b506103436106bc366004613610565b61264d565b3480156106cc575f80fd5b506103436301e187e081565b3480156106e3575f80fd5b5061027e60405180604001604052806005815260200164312e342e3160d81b81525081565b603480546107159061363c565b80601f01602080910402602001604051908101604052809291908181526020018280546107419061363c565b801561078c5780601f106107635761010080835404028352916020019161078c565b820191905f5260205f20905b81548152906001019060200180831161076f57829003601f168201915b505050505081565b5f604051631b48e8f360e21b815260040160405180910390fd5b6002546040805163030d028960e21b815290515f926001600160a01b031691630c340a249160048083019260209291908290030181865afa1580156107f5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610819919061367f565b905090565b6108266107ae565b6001600160a01b0316610837612667565b6001600160a01b03161461085e57604051634b98449160e11b815260040160405180910390fd5b60385480820361088157604051630333a68160e41b815260040160405180910390fd5b60408051828152602081018490527fc58cd6132bb46df23d468939c03dd023b74b509aaa6b04c39d5a6461c65963bd910160405180910390a150603855565b5f806108ca612765565b50509050806039546108dc91906136ae565b91505090565b6002546001600160a01b03166108f6612667565b6001600160a01b03161461091d5760405163531f2aa960e11b815260040160405180910390fd5b61092782826127c8565b5050565b5f8060025f9054906101000a90046001600160a01b03166001600160a01b031663ecf3a3f96040518163ffffffff1660e01b8152600401602060405180830381865afa15801561097d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109a191906136d0565b156109bf57604051631b0e923f60e11b815260040160405180910390fd5b6109c7612a28565b600254603d54604051631a0dd00b60e01b81526001600160a01b039182166004820152911690631a0dd00b90602401602060405180830381865afa158015610a11573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a3591906136d0565b610a525760405163a596698b60e01b815260040160405180910390fd5b825f03610a72576040516310eb483f60e21b815260040160405180910390fd5b610a7a611a5e565b5f610a83612667565b600254603d549192506001600160a01b039081169116610aa286610ddc565b90955093508315610b8057806001600160a01b031663b2a02ff184846001600160a01b031663c415b95c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610af9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b1d919061367f565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604481018790526064015f604051808303815f87803b158015610b69575f80fd5b505af1158015610b7b573d5f803e3d5ffd5b505050505b5f826001600160a01b031663f60928096040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bbd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610be191906136e9565b90508015610cf9575f836001600160a01b031663eaada3826040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c26573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c4a919061367f565b6001600160a01b0316638d0dba008489610c638d6113ee565b610c6d9190613700565b6040518363ffffffff1660e01b8152600401610c8a929190613713565b602060405180830381865afa158015610ca5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cc991906136e9565b90505f81118015610cd957508181105b15610cf7576040516332b9d47360e01b815260040160405180910390fd5b505b604051631dd319cb60e01b81526001600160a01b03831690631dd319cb90610d279087908a90600401613713565b5f604051808303815f87803b158015610d3e575f80fd5b505af1158015610d50573d5f803e3d5ffd5b50505050610d5e88876127c8565b60408051888152602081018890529081018690526001600160a01b03808a1691908616907fe02887340b03318642b6755f258294b795be42ed57d4b5d0ef27be3038d8a7649060600160405180910390a350505050610dbb612a97565b9250929050565b5f60405163d21ad44b60e01b815260040160405180910390fd5b5f805f60025f9054906101000a90046001600160a01b03166001600160a01b0316634066fdea6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e2f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e53919061367f565b6001600160a01b0316637c0f59f46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e8e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610eb291906136e9565b9050805f03610ec2575091929050565b610ede610ed782670de0b6b3a76400006136ae565b8590612ac1565b9250610eea8385613700565b915050915091565b603e548015610fc157603d54600254604080516331056e5760e21b815290516001600160a01b03938416936340c10f1993169163c415b95c9160048083019260209291908290030181865afa158015610f4d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f71919061367f565b836040518363ffffffff1660e01b8152600401610f8f929190613713565b5f604051808303815f87803b158015610fa6575f80fd5b505af1158015610fb8573d5f803e3d5ffd5b50505f603e5550505b50565b60025f9054906101000a90046001600160a01b03166001600160a01b03166396aaccfe6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611014573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611038919061367f565b6001600160a01b0316611049612667565b6001600160a01b03161461107057604051630935fed760e11b815260040160405180910390fd5b60025f9054906101000a90046001600160a01b03166001600160a01b031663ecf3a3f96040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110c0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110e491906136d0565b1561110257604051631b0e923f60e11b815260040160405180910390fd5b61110a612a28565b600254603d54604051631a0dd00b60e01b81526001600160a01b039182166004820152911690631a0dd00b90602401602060405180830381865afa158015611154573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061117891906136d0565b6111955760405163a596698b60e01b815260040160405180910390fd5b603d5f9054906101000a90046001600160a01b03166001600160a01b03166322f3e2d46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111e5573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061120991906136d0565b611226576040516303127d9160e31b815260040160405180910390fd5b61122e611a5e565b60025460408051637556d1c160e11b815290516001600160a01b03909216916112a8918391829163eaada3829160048083019260209291908290030181865afa15801561127d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112a1919061367f565b8585612afd565b50610927612a97565b5f805f60025f9054906101000a90046001600160a01b03166001600160a01b0316634066fdea6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611304573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611328919061367f565b6001600160a01b0316632a9133c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015611363573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061138791906136e9565b9050805f03611397575091929050565b6113a18482612e8a565b91506113ad8285613700565b925050915091565b6113bd612ec0565b6001600160a01b0383166113da576113d58282612f00565b505050565b6113d56001600160a01b038416838361301a565b6001600160a01b0381165f9081526036602052604081205480820361141557505f92915050565b5f61141e612765565b506001600160a01b0386165f908152603760205260409020549092509050611446828461372c565b6114509190613743565b949350505050565b5f6114636001613070565b9050801561147a575f805461ff0019166101001790555b5f88900361149b57604051636e83f50760e01b815260040160405180910390fd5b5f8690036114bc576040516330507cff60e11b815260040160405180910390fd5b6001600160a01b0385166114e357604051633cb1fb1f60e11b815260040160405180910390fd5b6001600160a01b03841661150a5760405163013a1b4360e51b815260040160405180910390fd5b611513856130f9565b6034611520898b836137c1565b50603561152e8789836137c1565b50836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561156b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061158f919061387b565b603d805442603a55670de0b6b3a7640000603b55603c86905560388590556001600160a81b031960ff93909316600160a81b02929092166001600160b01b0319909216919091176001600160a01b03861617600160a01b179055801561162e575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050565b6116416107ae565b6001600160a01b0316611652612667565b6001600160a01b03161461167957604051634b98449160e11b815260040160405180910390fd5b611681611a5e565b603c548082036116a457604051630333a68160e41b815260040160405180910390fd5b60408051828152602081018490527f41e376fd99913dea7fda140f5c0bd997515b1a181acc58737320322548ec6e72910160405180910390a150603c55565b5f8060025f9054906101000a90046001600160a01b03166001600160a01b031663ecf3a3f96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611735573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061175991906136d0565b1561177757604051631b0e923f60e11b815260040160405180910390fd5b61177f612a28565b600254603d54604051631a0dd00b60e01b81526001600160a01b039182166004820152911690631a0dd00b90602401602060405180830381865afa1580156117c9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117ed91906136d0565b61180a5760405163a596698b60e01b815260040160405180910390fd5b611812611a5e565b61181b836113ee565b9150815f0361183d576040516310eb483f60e21b815260040160405180910390fd5b5f611846612667565b603d549091506001600160a01b03165f61185f856123a9565b94509050831561195057816001600160a01b031663b2a02ff18460025f9054906101000a90046001600160a01b03166001600160a01b031663c415b95c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118c9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118ed919061367f565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604481018790526064015f604051808303815f87803b158015611939575f80fd5b505af115801561194b573d5f803e3d5ffd5b505050505b604051631dd319cb60e01b81526001600160a01b03831690631dd319cb9061197e9086908990600401613713565b5f604051808303815f87803b158015611995575f80fd5b505af11580156119a7573d5f803e3d5ffd5b505050506119b586866127c8565b60408051828152602081018790529081018590526001600160a01b0380881691908516907fe02887340b03318642b6755f258294b795be42ed57d4b5d0ef27be3038d8a7649060600160405180910390a3505050611a11612a97565b915091565b5f805f611a21612765565b5050603e5490915080611a3483826136ae565b9350935050509091565b603580546107159061363c565b5f6301e187e0603c546108199190613743565b5f805f611a69612765565b925092509250804203611a7b57505050565b42603a5582156113d5578260395f828254611a9691906136ae565b9091555050603b829055603d54600254604080516331056e5760e21b815290516001600160a01b03938416936340c10f1993169163c415b95c9160048083019260209291908290030181865afa158015611af2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b16919061367f565b603e54611b2390876136ae565b6040518363ffffffff1660e01b8152600401611b40929190613713565b5f604051808303815f87803b158015611b57575f80fd5b505af1925050508015611b68575060015b611b885782603e5f828254611b7d91906136ae565b909155506113d59050565b5f603e55505050565b6002546040805163afcff50f60e01b815290515f926001600160a01b03169163afcff50f9160048083019260209291908290030181865afa1580156107f5573d5f803e3d5ffd5b5f8060025f9054906101000a90046001600160a01b03166001600160a01b031663ecf3a3f96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c2a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c4e91906136d0565b15611c6c57604051631b0e923f60e11b815260040160405180910390fd5b611c74612a28565b600254603d54604051631a0dd00b60e01b81526001600160a01b039182166004820152911690631a0dd00b90602401602060405180830381865afa158015611cbe573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ce291906136d0565b611cff5760405163a596698b60e01b815260040160405180910390fd5b835f03611d1f576040516310eb483f60e21b815260040160405180910390fd5b611d27611a5e565b5f611d30612667565b600254603d5460405163dde3ab9560e01b81526001600160a01b0380851660048301529394509183169216905f90839063dde3ab959060240160a060405180830381865afa158015611d84573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611da8919061389b565b9450505050505f836001600160a01b031663eaada3826040518163ffffffff1660e01b8152600401602060405180830381865afa158015611deb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e0f919061367f565b60405163b5e9bef560e01b81529091506001600160a01b0382169063b5e9bef590611e409086908690600401613713565b602060405180830381865afa158015611e5b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e7f91906136e9565b891115611e9e5760405162d11df360e61b815260040160405180910390fd5b611eaa8482878c612afd565b611eb3896112b1565b90975095508515611f7957826001600160a01b03166340c10f19856001600160a01b031663c415b95c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f09573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f2d919061367f565b886040518363ffffffff1660e01b8152600401611f4b929190613713565b5f604051808303815f87803b158015611f62575f80fd5b505af1158015611f74573d5f803e3d5ffd5b505050505b6040516340c10f1960e01b81526001600160a01b038416906340c10f1990611fa7908b908b90600401613713565b5f604051808303815f87803b158015611fbe575f80fd5b505af1158015611fd0573d5f803e3d5ffd5b5050604080518c8152602081018b90529081018990526001600160a01b03808c169350881691507f197d5e1e72d62df9dad3add8609553402104dbeb4f83f9789e33aeb6723a78399060600160405180910390a35050505050610dbb612a97565b5f8060025f9054906101000a90046001600160a01b03166001600160a01b03166396aaccfe6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612083573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120a7919061367f565b6001600160a01b03166120b8612667565b6001600160a01b0316146120df57604051630935fed760e11b815260040160405180910390fd5b60025f9054906101000a90046001600160a01b03166001600160a01b031663ecf3a3f96040518163ffffffff1660e01b8152600401602060405180830381865afa15801561212f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061215391906136d0565b1561217157604051631b0e923f60e11b815260040160405180910390fd5b612179612a28565b600254603d54604051631a0dd00b60e01b81526001600160a01b039182166004820152911690631a0dd00b90602401602060405180830381865afa1580156121c3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121e791906136d0565b6122045760405163a596698b60e01b815260040160405180910390fd5b603d54600160a01b900460ff1661222e5760405163a4382ae360e01b815260040160405180910390fd5b825f0361224e576040516310eb483f60e21b815260040160405180910390fd5b612256611a5e565b603d546001600160a01b031661226b846112b1565b9093509150811561234557806001600160a01b03166340c10f1960025f9054906101000a90046001600160a01b03166001600160a01b031663c415b95c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122f9919061367f565b846040518363ffffffff1660e01b8152600401612317929190613713565b5f604051808303815f87803b15801561232e575f80fd5b505af1158015612340573d5f803e3d5ffd5b505050505b6040516340c10f1960e01b81526001600160a01b038216906340c10f19906123739088908790600401613713565b5f604051808303815f87803b15801561238a575f80fd5b505af115801561239c573d5f803e3d5ffd5b5050505050610dbb612a97565b5f805f60025f9054906101000a90046001600160a01b03166001600160a01b0316634066fdea6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123fc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612420919061367f565b6001600160a01b0316637c0f59f46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561245b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061247f91906136e9565b9050805f0361248f575091929050565b6124998482612e8a565b91506113ad82856136ae565b6124ad6107ae565b6001600160a01b03166124be612667565b6001600160a01b0316146124e557604051634b98449160e11b815260040160405180910390fd5b603d54604051600160a01b90910460ff1615808252907fb1d9ceb4467fd05a16930f966760d70eb5926cf0c1c19a7b6bfe59d805c190459060200160405180910390a1603d8054911515600160a01b0260ff60a01b19909216919091179055565b5f805f60025f9054906101000a90046001600160a01b03166001600160a01b0316634066fdea6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612599573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125bd919061367f565b6001600160a01b0316632a9133c16040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125f8573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061261c91906136e9565b9050805f0361262c575091929050565b612641610ed782670de0b6b3a7640000613700565b9250610eea8484613700565b5f60405163effde13d60e01b815260040160405180910390fd5b5f80612671611b91565b90506001600160a01b0381161561275e575f816001600160a01b031663570ca7356040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126bf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126e3919061367f565b90506001600160a01b038116330361275c57806001600160a01b031663d2c869a46040518163ffffffff1660e01b8152600401602060405180830381865afa158015612731573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612755919061367f565b9250505090565b505b3391505090565b603a54603b545f91428110156127c3575f6127808242613700565b612788611a4b565b612792919061372c565b905080156127c1576039546127a8908290612e8a565b93506127b48184612e8a565b6127be90846136ae565b92505b505b909192565b815f60025f9054906101000a90046001600160a01b03166001600160a01b0316633605b51b6040518163ffffffff1660e01b81526004015f60405180830381865afa158015612819573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261284091908101906138de565b80519091505f5b818110156128d3578281815181106128615761286161399e565b6020908102919091010151604051626cc3c360e61b81523060048201526001600160a01b03868116602483015290911690631b30f0c0906044015f604051808303815f87803b1580156128b2575f80fd5b505af11580156128c4573d5f803e3d5ffd5b50505050806001019050612847565b506001600160a01b0385166128fb5760405163170476af60e21b815260040160405180910390fd5b5f612905866113ee565b90508481101561292857604051630bba337f60e11b815260040160405180910390fd5b6039546001600160a01b0387165f9081526036602090815260408083208986039055603b54603790925290912055808610612963575f612967565b8581035b6039556040518681525f906001600160a01b038916907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35f861180156129bf57506129bd876113ee565b155b15612a1f57600254604051631d71be3b60e21b81526001600160a01b038981166004830152909116906375c6f8ec906024015f604051808303815f87803b158015612a08575f80fd5b505af1158015612a1a573d5f803e3d5ffd5b505050505b50505050505050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c15612a6857604051633ee5aeb560e01b815260040160405180910390fd5b612a9560017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005b906131ac565b565b612a955f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00612a8f565b5f81612ace600282613743565b612ae0670de0b6b3a76400008661372c565b612aea91906136ae565b612af49190613743565b90505b92915050565b603d54600160a01b900460ff16612b275760405163a4382ae360e01b815260040160405180910390fd5b815f60025f9054906101000a90046001600160a01b03166001600160a01b0316633605b51b6040518163ffffffff1660e01b81526004015f60405180830381865afa158015612b78573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612b9f91908101906138de565b80519091505f5b81811015612c3257828181518110612bc057612bc061399e565b6020908102919091010151604051626cc3c360e61b81523060048201526001600160a01b03868116602483015290911690631b30f0c0906044015f604051808303815f87803b158015612c11575f80fd5b505af1158015612c23573d5f803e3d5ffd5b50505050806001019050612ba6565b506001600160a01b038516612c5a57604051632b61339160e21b815260040160405180910390fd5b5f876001600160a01b031663f60928096040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c97573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612cbb91906136e9565b90505f612cc7876113ee565b90505f82118015612d535750603d5482906001600160a01b03808b1691638d0dba009116612cf58a866136ae565b6040518363ffffffff1660e01b8152600401612d12929190613713565b602060405180830381865afa158015612d2d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d5191906136e9565b105b15612d7157604051637e76d52960e11b815260040160405180910390fd5b8560395f828254612d8291906136ae565b90915550506038546039541115612dac57604051634aed251160e11b815260040160405180910390fd5b612db686826136ae565b6001600160a01b0388165f81815260366020908152604080832094909455603b5460378252848320559251898152919290917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a380158015612e2057505f86115b1561162e57600254604051631dc2da6d60e21b81526001600160a01b0389811660048301529091169063770b69b4906024015f604051808303815f87803b158015612e69575f80fd5b505af1158015612e7b573d5f803e3d5ffd5b50505050505050505050505050565b5f821580612e96575081155b15612ea257505f612af7565b670de0b6b3a7640000612eb6600282613743565b612ae0848661372c565b612ec86107ae565b6001600160a01b0316612ed9612667565b6001600160a01b031614612a9557604051634b98449160e11b815260040160405180910390fd5b80471015612f555760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064015b60405180910390fd5b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114612f9e576040519150601f19603f3d011682016040523d82523d5f602084013e612fa3565b606091505b50509050806113d55760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401612f4c565b6113d58363a9059cbb60e01b8484604051602401613039929190613713565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526131b3565b5f8054610100900460ff16156130b5578160ff1660011480156130925750303b155b6130ae5760405162461bcd60e51b8152600401612f4c906139b2565b505f919050565b5f5460ff8084169116106130db5760405162461bcd60e51b8152600401612f4c906139b2565b505f805460ff191660ff92909216919091179055600190565b919050565b5f54610100900460ff166131635760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401612f4c565b6001600160a01b03811661318a5760405163724f500960e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b80825d5050565b5f613207826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166132849092919063ffffffff16565b8051909150156113d5578080602001905181019061322591906136d0565b6113d55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401612f4c565b606061329284845f8561329c565b90505b9392505050565b6060824710156132fd5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401612f4c565b6001600160a01b0385163b6133545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401612f4c565b5f80866001600160a01b0316858760405161336f9190613a00565b5f6040518083038185875af1925050503d805f81146133a9576040519150601f19603f3d011682016040523d82523d5f602084013e6133ae565b606091505b50915091506133be8282866133c9565b979650505050505050565b606083156133d8575081613295565b8251156133e85782518084602001fd5b8160405162461bcd60e51b8152600401612f4c9190613424565b5f5b8381101561341c578181015183820152602001613404565b50505f910152565b602081525f8251806020840152613442816040850160208701613402565b601f01601f19169190910160400192915050565b6001600160a01b0381168114610fc1575f80fd5b5f806040838503121561347b575f80fd5b823561348681613456565b946020939093013593505050565b5f602082840312156134a4575f80fd5b5035919050565b5f805f606084860312156134bd575f80fd5b83356134c881613456565b925060208401356134d881613456565b929592945050506040919091013590565b5f602082840312156134f9575f80fd5b813561329581613456565b5f8083601f840112613514575f80fd5b50813567ffffffffffffffff81111561352b575f80fd5b602083019150836020828501011115610dbb575f80fd5b5f805f805f805f8060c0898b031215613559575f80fd5b883567ffffffffffffffff80821115613570575f80fd5b61357c8c838d01613504565b909a50985060208b0135915080821115613594575f80fd5b506135a18b828c01613504565b90975095505060408901356135b581613456565b935060608901356135c581613456565b979a969950949793969295929450505060808201359160a0013590565b5f80604083850312156135f3575f80fd5b82359150602083013561360581613456565b809150509250929050565b5f8060408385031215613621575f80fd5b823561362c81613456565b9150602083013561360581613456565b600181811c9082168061365057607f821691505b60208210810361366e57634e487b7160e01b5f52602260045260245ffd5b50919050565b80516130f481613456565b5f6020828403121561368f575f80fd5b815161329581613456565b634e487b7160e01b5f52601160045260245ffd5b80820180821115612af757612af761369a565b805180151581146130f4575f80fd5b5f602082840312156136e0575f80fd5b612af4826136c1565b5f602082840312156136f9575f80fd5b5051919050565b81810381811115612af757612af761369a565b6001600160a01b03929092168252602082015260400190565b8082028115828204841417612af757612af761369a565b5f8261375d57634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52604160045260245ffd5b601f8211156113d557805f5260205f20601f840160051c8101602085101561379b5750805b601f840160051c820191505b818110156137ba575f81556001016137a7565b5050505050565b67ffffffffffffffff8311156137d9576137d9613762565b6137ed836137e7835461363c565b83613776565b5f601f84116001811461381e575f85156138075750838201355b5f19600387901b1c1916600186901b1783556137ba565b5f83815260208120601f198716915b8281101561384d578685013582556020948501946001909201910161382d565b5086821015613869575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b5f6020828403121561388b575f80fd5b815160ff81168114613295575f80fd5b5f805f805f60a086880312156138af575f80fd5b6138b8866136c1565b602087015160408801516060890151608090990151929a91995097965090945092505050565b5f60208083850312156138ef575f80fd5b825167ffffffffffffffff80821115613906575f80fd5b818501915085601f830112613919575f80fd5b81518181111561392b5761392b613762565b8060051b604051601f19603f8301168101818110858211171561395057613950613762565b60405291825284820192508381018501918883111561396d575f80fd5b938501935b828510156139925761398385613674565b84529385019392850192613972565b98975050505050505050565b634e487b7160e01b5f52603260045260245ffd5b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b5f8251613a11818460208701613402565b919091019291505056fea26469706673582212209345aea9298a6817005a5587ee0edbd299b47749882102085c38a9fc0f7b771a64736f6c63430008180033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"cancun","libraries":{},"metadata":{"useLiteralContent":true},"optimizer":{"enabled":true,"runs":200},"outputSelection":{"*":{"":["*"],"*":["*"]}}},"optimization_runs":200,"sourcify_repo_url":null,"decoded_constructor_args":null,"compiler_version":"v0.8.24+commit.e11b9ed9","is_verified_via_verifier_alliance":false,"verified_at":"2026-10-01T18:19:07.719712Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x608060405234801562000010575f80fd5b506200001b62000021565b62000128565b6200002d60ff62000030565b50565b5f8054610100900460ff1615620000b2578160ff166001148015620000545750303b155b620000ab5760405162461bcd60e51b815260206004820152602e60248201525f8051602062003b8783398151915260448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b505f919050565b5f5460ff8084169116106200010f5760405162461bcd60e51b815260206004820152602e60248201525f8051602062003b8783398151915260448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620000a2565b505f805460ff191660ff92909216919091179055600190565b613a5180620001365f395ff3fe608060405260043610610233575f3560e01c806374e87e1e1161012d578063afcff50f116100aa578063d25933291161006e578063d25933291461066f578063d38f2ba914610683578063dd62ed3e146106a2578063e6a69ab8146106c1578063ffa1ad74146106d857610251565b8063afcff50f146105e9578063b696a6ad146105fd578063bb8c631f1461061c578063bfa1765614610631578063c9dc4b4d1461065057610251565b80638e84ab22116100f15780638e84ab221461057f57806395d89b41146105935780639cc820da146105a7578063a6afed95146105bb578063a9059cbb146105cf57610251565b806374e87e1e146104ee578063752a50a61461050d5780637c27383b1461052c5780637c3a00fd1461054b5780638230ecd61461056057610251565b806323b872dd116101bb57806340c10f191161017f57806340c10f191461045d5780634754d1761461047c578063565f3d4f1461049b57806362c06767146104b057806370a08231146104cf57610251565b806323b872dd146103c45780632ab4d052146103e35780632d4aeea1146103f8578063313ce5671461041757806336248ab41461044957610251565b8063172f50a411610202578063172f50a41461030e57806318160ddd1461032f5780631dd319cb1461035157806322867d781461037057806322f3e2d4146103a457610251565b806306fdde031461026a578063095ea7b3146102945780630c340a24146102c357806316f0115b146102ef57610251565b3661025157604051636436c22d60e11b815260040160405180910390fd5b60405163a0152e6360e01b815260040160405180910390fd5b348015610275575f80fd5b5061027e610708565b60405161028b9190613424565b60405180910390f35b34801561029f575f80fd5b506102b36102ae36600461346a565b610794565b604051901515815260200161028b565b3480156102ce575f80fd5b506102d76107ae565b6040516001600160a01b03909116815260200161028b565b3480156102fa575f80fd5b506002546102d7906001600160a01b031681565b348015610319575f80fd5b5061032d610328366004613494565b61081e565b005b34801561033a575f80fd5b506103436108c0565b60405190815260200161028b565b34801561035c575f80fd5b5061032d61036b36600461346a565b6108e2565b34801561037b575f80fd5b5061038f61038a36600461346a565b61092b565b6040805192835260208301919091520161028b565b3480156103af575f80fd5b50603d546102b390600160a01b900460ff1681565b3480156103cf575f80fd5b506102b36103de3660046134ab565b610dc2565b3480156103ee575f80fd5b5061034360385481565b348015610403575f80fd5b5061038f610412366004613494565b610ddc565b348015610422575f80fd5b50603d5461043790600160a81b900460ff1681565b60405160ff909116815260200161028b565b348015610454575f80fd5b5061032d610ef2565b348015610468575f80fd5b5061032d61047736600461346a565b610fc4565b348015610487575f80fd5b5061038f610496366004613494565b6112b1565b3480156104a6575f80fd5b50610343603a5481565b3480156104bb575f80fd5b5061032d6104ca3660046134ab565b6113b5565b3480156104da575f80fd5b506103436104e93660046134e9565b6113ee565b3480156104f9575f80fd5b5061032d610508366004613542565b611458565b348015610518575f80fd5b5061032d610527366004613494565b611639565b348015610537575f80fd5b5061038f6105463660046134e9565b6116e3565b348015610556575f80fd5b50610343603c5481565b34801561056b575f80fd5b50603d546102d7906001600160a01b031681565b34801561058a575f80fd5b5061038f611a16565b34801561059e575f80fd5b5061027e611a3e565b3480156105b2575f80fd5b50610343611a4b565b3480156105c6575f80fd5b5061032d611a5e565b3480156105da575f80fd5b506102b36103de36600461346a565b3480156105f4575f80fd5b506102d7611b91565b348015610608575f80fd5b5061038f6106173660046135e2565b611bd8565b348015610627575f80fd5b50610343603b5481565b34801561063c575f80fd5b5061038f61064b36600461346a565b612031565b34801561065b575f80fd5b5061038f61066a366004613494565b6123a9565b34801561067a575f80fd5b5061032d6124a5565b34801561068e575f80fd5b5061038f61069d366004613494565b612546565b3480156106ad575f80fd5b506103436106bc366004613610565b61264d565b3480156106cc575f80fd5b506103436301e187e081565b3480156106e3575f80fd5b5061027e60405180604001604052806005815260200164312e342e3160d81b81525081565b603480546107159061363c565b80601f01602080910402602001604051908101604052809291908181526020018280546107419061363c565b801561078c5780601f106107635761010080835404028352916020019161078c565b820191905f5260205f20905b81548152906001019060200180831161076f57829003601f168201915b505050505081565b5f604051631b48e8f360e21b815260040160405180910390fd5b6002546040805163030d028960e21b815290515f926001600160a01b031691630c340a249160048083019260209291908290030181865afa1580156107f5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610819919061367f565b905090565b6108266107ae565b6001600160a01b0316610837612667565b6001600160a01b03161461085e57604051634b98449160e11b815260040160405180910390fd5b60385480820361088157604051630333a68160e41b815260040160405180910390fd5b60408051828152602081018490527fc58cd6132bb46df23d468939c03dd023b74b509aaa6b04c39d5a6461c65963bd910160405180910390a150603855565b5f806108ca612765565b50509050806039546108dc91906136ae565b91505090565b6002546001600160a01b03166108f6612667565b6001600160a01b03161461091d5760405163531f2aa960e11b815260040160405180910390fd5b61092782826127c8565b5050565b5f8060025f9054906101000a90046001600160a01b03166001600160a01b031663ecf3a3f96040518163ffffffff1660e01b8152600401602060405180830381865afa15801561097d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109a191906136d0565b156109bf57604051631b0e923f60e11b815260040160405180910390fd5b6109c7612a28565b600254603d54604051631a0dd00b60e01b81526001600160a01b039182166004820152911690631a0dd00b90602401602060405180830381865afa158015610a11573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a3591906136d0565b610a525760405163a596698b60e01b815260040160405180910390fd5b825f03610a72576040516310eb483f60e21b815260040160405180910390fd5b610a7a611a5e565b5f610a83612667565b600254603d549192506001600160a01b039081169116610aa286610ddc565b90955093508315610b8057806001600160a01b031663b2a02ff184846001600160a01b031663c415b95c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610af9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b1d919061367f565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604481018790526064015f604051808303815f87803b158015610b69575f80fd5b505af1158015610b7b573d5f803e3d5ffd5b505050505b5f826001600160a01b031663f60928096040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bbd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610be191906136e9565b90508015610cf9575f836001600160a01b031663eaada3826040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c26573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c4a919061367f565b6001600160a01b0316638d0dba008489610c638d6113ee565b610c6d9190613700565b6040518363ffffffff1660e01b8152600401610c8a929190613713565b602060405180830381865afa158015610ca5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cc991906136e9565b90505f81118015610cd957508181105b15610cf7576040516332b9d47360e01b815260040160405180910390fd5b505b604051631dd319cb60e01b81526001600160a01b03831690631dd319cb90610d279087908a90600401613713565b5f604051808303815f87803b158015610d3e575f80fd5b505af1158015610d50573d5f803e3d5ffd5b50505050610d5e88876127c8565b60408051888152602081018890529081018690526001600160a01b03808a1691908616907fe02887340b03318642b6755f258294b795be42ed57d4b5d0ef27be3038d8a7649060600160405180910390a350505050610dbb612a97565b9250929050565b5f60405163d21ad44b60e01b815260040160405180910390fd5b5f805f60025f9054906101000a90046001600160a01b03166001600160a01b0316634066fdea6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e2f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e53919061367f565b6001600160a01b0316637c0f59f46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e8e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610eb291906136e9565b9050805f03610ec2575091929050565b610ede610ed782670de0b6b3a76400006136ae565b8590612ac1565b9250610eea8385613700565b915050915091565b603e548015610fc157603d54600254604080516331056e5760e21b815290516001600160a01b03938416936340c10f1993169163c415b95c9160048083019260209291908290030181865afa158015610f4d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f71919061367f565b836040518363ffffffff1660e01b8152600401610f8f929190613713565b5f604051808303815f87803b158015610fa6575f80fd5b505af1158015610fb8573d5f803e3d5ffd5b50505f603e5550505b50565b60025f9054906101000a90046001600160a01b03166001600160a01b03166396aaccfe6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611014573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611038919061367f565b6001600160a01b0316611049612667565b6001600160a01b03161461107057604051630935fed760e11b815260040160405180910390fd5b60025f9054906101000a90046001600160a01b03166001600160a01b031663ecf3a3f96040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110c0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110e491906136d0565b1561110257604051631b0e923f60e11b815260040160405180910390fd5b61110a612a28565b600254603d54604051631a0dd00b60e01b81526001600160a01b039182166004820152911690631a0dd00b90602401602060405180830381865afa158015611154573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061117891906136d0565b6111955760405163a596698b60e01b815260040160405180910390fd5b603d5f9054906101000a90046001600160a01b03166001600160a01b03166322f3e2d46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111e5573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061120991906136d0565b611226576040516303127d9160e31b815260040160405180910390fd5b61122e611a5e565b60025460408051637556d1c160e11b815290516001600160a01b03909216916112a8918391829163eaada3829160048083019260209291908290030181865afa15801561127d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112a1919061367f565b8585612afd565b50610927612a97565b5f805f60025f9054906101000a90046001600160a01b03166001600160a01b0316634066fdea6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611304573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611328919061367f565b6001600160a01b0316632a9133c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015611363573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061138791906136e9565b9050805f03611397575091929050565b6113a18482612e8a565b91506113ad8285613700565b925050915091565b6113bd612ec0565b6001600160a01b0383166113da576113d58282612f00565b505050565b6113d56001600160a01b038416838361301a565b6001600160a01b0381165f9081526036602052604081205480820361141557505f92915050565b5f61141e612765565b506001600160a01b0386165f908152603760205260409020549092509050611446828461372c565b6114509190613743565b949350505050565b5f6114636001613070565b9050801561147a575f805461ff0019166101001790555b5f88900361149b57604051636e83f50760e01b815260040160405180910390fd5b5f8690036114bc576040516330507cff60e11b815260040160405180910390fd5b6001600160a01b0385166114e357604051633cb1fb1f60e11b815260040160405180910390fd5b6001600160a01b03841661150a5760405163013a1b4360e51b815260040160405180910390fd5b611513856130f9565b6034611520898b836137c1565b50603561152e8789836137c1565b50836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561156b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061158f919061387b565b603d805442603a55670de0b6b3a7640000603b55603c86905560388590556001600160a81b031960ff93909316600160a81b02929092166001600160b01b0319909216919091176001600160a01b03861617600160a01b179055801561162e575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050565b6116416107ae565b6001600160a01b0316611652612667565b6001600160a01b03161461167957604051634b98449160e11b815260040160405180910390fd5b611681611a5e565b603c548082036116a457604051630333a68160e41b815260040160405180910390fd5b60408051828152602081018490527f41e376fd99913dea7fda140f5c0bd997515b1a181acc58737320322548ec6e72910160405180910390a150603c55565b5f8060025f9054906101000a90046001600160a01b03166001600160a01b031663ecf3a3f96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611735573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061175991906136d0565b1561177757604051631b0e923f60e11b815260040160405180910390fd5b61177f612a28565b600254603d54604051631a0dd00b60e01b81526001600160a01b039182166004820152911690631a0dd00b90602401602060405180830381865afa1580156117c9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117ed91906136d0565b61180a5760405163a596698b60e01b815260040160405180910390fd5b611812611a5e565b61181b836113ee565b9150815f0361183d576040516310eb483f60e21b815260040160405180910390fd5b5f611846612667565b603d549091506001600160a01b03165f61185f856123a9565b94509050831561195057816001600160a01b031663b2a02ff18460025f9054906101000a90046001600160a01b03166001600160a01b031663c415b95c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118c9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118ed919061367f565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604481018790526064015f604051808303815f87803b158015611939575f80fd5b505af115801561194b573d5f803e3d5ffd5b505050505b604051631dd319cb60e01b81526001600160a01b03831690631dd319cb9061197e9086908990600401613713565b5f604051808303815f87803b158015611995575f80fd5b505af11580156119a7573d5f803e3d5ffd5b505050506119b586866127c8565b60408051828152602081018790529081018590526001600160a01b0380881691908516907fe02887340b03318642b6755f258294b795be42ed57d4b5d0ef27be3038d8a7649060600160405180910390a3505050611a11612a97565b915091565b5f805f611a21612765565b5050603e5490915080611a3483826136ae565b9350935050509091565b603580546107159061363c565b5f6301e187e0603c546108199190613743565b5f805f611a69612765565b925092509250804203611a7b57505050565b42603a5582156113d5578260395f828254611a9691906136ae565b9091555050603b829055603d54600254604080516331056e5760e21b815290516001600160a01b03938416936340c10f1993169163c415b95c9160048083019260209291908290030181865afa158015611af2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b16919061367f565b603e54611b2390876136ae565b6040518363ffffffff1660e01b8152600401611b40929190613713565b5f604051808303815f87803b158015611b57575f80fd5b505af1925050508015611b68575060015b611b885782603e5f828254611b7d91906136ae565b909155506113d59050565b5f603e55505050565b6002546040805163afcff50f60e01b815290515f926001600160a01b03169163afcff50f9160048083019260209291908290030181865afa1580156107f5573d5f803e3d5ffd5b5f8060025f9054906101000a90046001600160a01b03166001600160a01b031663ecf3a3f96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c2a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c4e91906136d0565b15611c6c57604051631b0e923f60e11b815260040160405180910390fd5b611c74612a28565b600254603d54604051631a0dd00b60e01b81526001600160a01b039182166004820152911690631a0dd00b90602401602060405180830381865afa158015611cbe573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ce291906136d0565b611cff5760405163a596698b60e01b815260040160405180910390fd5b835f03611d1f576040516310eb483f60e21b815260040160405180910390fd5b611d27611a5e565b5f611d30612667565b600254603d5460405163dde3ab9560e01b81526001600160a01b0380851660048301529394509183169216905f90839063dde3ab959060240160a060405180830381865afa158015611d84573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611da8919061389b565b9450505050505f836001600160a01b031663eaada3826040518163ffffffff1660e01b8152600401602060405180830381865afa158015611deb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e0f919061367f565b60405163b5e9bef560e01b81529091506001600160a01b0382169063b5e9bef590611e409086908690600401613713565b602060405180830381865afa158015611e5b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e7f91906136e9565b891115611e9e5760405162d11df360e61b815260040160405180910390fd5b611eaa8482878c612afd565b611eb3896112b1565b90975095508515611f7957826001600160a01b03166340c10f19856001600160a01b031663c415b95c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f09573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f2d919061367f565b886040518363ffffffff1660e01b8152600401611f4b929190613713565b5f604051808303815f87803b158015611f62575f80fd5b505af1158015611f74573d5f803e3d5ffd5b505050505b6040516340c10f1960e01b81526001600160a01b038416906340c10f1990611fa7908b908b90600401613713565b5f604051808303815f87803b158015611fbe575f80fd5b505af1158015611fd0573d5f803e3d5ffd5b5050604080518c8152602081018b90529081018990526001600160a01b03808c169350881691507f197d5e1e72d62df9dad3add8609553402104dbeb4f83f9789e33aeb6723a78399060600160405180910390a35050505050610dbb612a97565b5f8060025f9054906101000a90046001600160a01b03166001600160a01b03166396aaccfe6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612083573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120a7919061367f565b6001600160a01b03166120b8612667565b6001600160a01b0316146120df57604051630935fed760e11b815260040160405180910390fd5b60025f9054906101000a90046001600160a01b03166001600160a01b031663ecf3a3f96040518163ffffffff1660e01b8152600401602060405180830381865afa15801561212f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061215391906136d0565b1561217157604051631b0e923f60e11b815260040160405180910390fd5b612179612a28565b600254603d54604051631a0dd00b60e01b81526001600160a01b039182166004820152911690631a0dd00b90602401602060405180830381865afa1580156121c3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121e791906136d0565b6122045760405163a596698b60e01b815260040160405180910390fd5b603d54600160a01b900460ff1661222e5760405163a4382ae360e01b815260040160405180910390fd5b825f0361224e576040516310eb483f60e21b815260040160405180910390fd5b612256611a5e565b603d546001600160a01b031661226b846112b1565b9093509150811561234557806001600160a01b03166340c10f1960025f9054906101000a90046001600160a01b03166001600160a01b031663c415b95c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122f9919061367f565b846040518363ffffffff1660e01b8152600401612317929190613713565b5f604051808303815f87803b15801561232e575f80fd5b505af1158015612340573d5f803e3d5ffd5b505050505b6040516340c10f1960e01b81526001600160a01b038216906340c10f19906123739088908790600401613713565b5f604051808303815f87803b15801561238a575f80fd5b505af115801561239c573d5f803e3d5ffd5b5050505050610dbb612a97565b5f805f60025f9054906101000a90046001600160a01b03166001600160a01b0316634066fdea6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123fc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612420919061367f565b6001600160a01b0316637c0f59f46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561245b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061247f91906136e9565b9050805f0361248f575091929050565b6124998482612e8a565b91506113ad82856136ae565b6124ad6107ae565b6001600160a01b03166124be612667565b6001600160a01b0316146124e557604051634b98449160e11b815260040160405180910390fd5b603d54604051600160a01b90910460ff1615808252907fb1d9ceb4467fd05a16930f966760d70eb5926cf0c1c19a7b6bfe59d805c190459060200160405180910390a1603d8054911515600160a01b0260ff60a01b19909216919091179055565b5f805f60025f9054906101000a90046001600160a01b03166001600160a01b0316634066fdea6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612599573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125bd919061367f565b6001600160a01b0316632a9133c16040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125f8573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061261c91906136e9565b9050805f0361262c575091929050565b612641610ed782670de0b6b3a7640000613700565b9250610eea8484613700565b5f60405163effde13d60e01b815260040160405180910390fd5b5f80612671611b91565b90506001600160a01b0381161561275e575f816001600160a01b031663570ca7356040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126bf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126e3919061367f565b90506001600160a01b038116330361275c57806001600160a01b031663d2c869a46040518163ffffffff1660e01b8152600401602060405180830381865afa158015612731573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612755919061367f565b9250505090565b505b3391505090565b603a54603b545f91428110156127c3575f6127808242613700565b612788611a4b565b612792919061372c565b905080156127c1576039546127a8908290612e8a565b93506127b48184612e8a565b6127be90846136ae565b92505b505b909192565b815f60025f9054906101000a90046001600160a01b03166001600160a01b0316633605b51b6040518163ffffffff1660e01b81526004015f60405180830381865afa158015612819573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261284091908101906138de565b80519091505f5b818110156128d3578281815181106128615761286161399e565b6020908102919091010151604051626cc3c360e61b81523060048201526001600160a01b03868116602483015290911690631b30f0c0906044015f604051808303815f87803b1580156128b2575f80fd5b505af11580156128c4573d5f803e3d5ffd5b50505050806001019050612847565b506001600160a01b0385166128fb5760405163170476af60e21b815260040160405180910390fd5b5f612905866113ee565b90508481101561292857604051630bba337f60e11b815260040160405180910390fd5b6039546001600160a01b0387165f9081526036602090815260408083208986039055603b54603790925290912055808610612963575f612967565b8581035b6039556040518681525f906001600160a01b038916907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35f861180156129bf57506129bd876113ee565b155b15612a1f57600254604051631d71be3b60e21b81526001600160a01b038981166004830152909116906375c6f8ec906024015f604051808303815f87803b158015612a08575f80fd5b505af1158015612a1a573d5f803e3d5ffd5b505050505b50505050505050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c15612a6857604051633ee5aeb560e01b815260040160405180910390fd5b612a9560017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005b906131ac565b565b612a955f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00612a8f565b5f81612ace600282613743565b612ae0670de0b6b3a76400008661372c565b612aea91906136ae565b612af49190613743565b90505b92915050565b603d54600160a01b900460ff16612b275760405163a4382ae360e01b815260040160405180910390fd5b815f60025f9054906101000a90046001600160a01b03166001600160a01b0316633605b51b6040518163ffffffff1660e01b81526004015f60405180830381865afa158015612b78573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612b9f91908101906138de565b80519091505f5b81811015612c3257828181518110612bc057612bc061399e565b6020908102919091010151604051626cc3c360e61b81523060048201526001600160a01b03868116602483015290911690631b30f0c0906044015f604051808303815f87803b158015612c11575f80fd5b505af1158015612c23573d5f803e3d5ffd5b50505050806001019050612ba6565b506001600160a01b038516612c5a57604051632b61339160e21b815260040160405180910390fd5b5f876001600160a01b031663f60928096040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c97573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612cbb91906136e9565b90505f612cc7876113ee565b90505f82118015612d535750603d5482906001600160a01b03808b1691638d0dba009116612cf58a866136ae565b6040518363ffffffff1660e01b8152600401612d12929190613713565b602060405180830381865afa158015612d2d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d5191906136e9565b105b15612d7157604051637e76d52960e11b815260040160405180910390fd5b8560395f828254612d8291906136ae565b90915550506038546039541115612dac57604051634aed251160e11b815260040160405180910390fd5b612db686826136ae565b6001600160a01b0388165f81815260366020908152604080832094909455603b5460378252848320559251898152919290917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a380158015612e2057505f86115b1561162e57600254604051631dc2da6d60e21b81526001600160a01b0389811660048301529091169063770b69b4906024015f604051808303815f87803b158015612e69575f80fd5b505af1158015612e7b573d5f803e3d5ffd5b50505050505050505050505050565b5f821580612e96575081155b15612ea257505f612af7565b670de0b6b3a7640000612eb6600282613743565b612ae0848661372c565b612ec86107ae565b6001600160a01b0316612ed9612667565b6001600160a01b031614612a9557604051634b98449160e11b815260040160405180910390fd5b80471015612f555760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064015b60405180910390fd5b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114612f9e576040519150601f19603f3d011682016040523d82523d5f602084013e612fa3565b606091505b50509050806113d55760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401612f4c565b6113d58363a9059cbb60e01b8484604051602401613039929190613713565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526131b3565b5f8054610100900460ff16156130b5578160ff1660011480156130925750303b155b6130ae5760405162461bcd60e51b8152600401612f4c906139b2565b505f919050565b5f5460ff8084169116106130db5760405162461bcd60e51b8152600401612f4c906139b2565b505f805460ff191660ff92909216919091179055600190565b919050565b5f54610100900460ff166131635760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401612f4c565b6001600160a01b03811661318a5760405163724f500960e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b80825d5050565b5f613207826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166132849092919063ffffffff16565b8051909150156113d5578080602001905181019061322591906136d0565b6113d55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401612f4c565b606061329284845f8561329c565b90505b9392505050565b6060824710156132fd5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401612f4c565b6001600160a01b0385163b6133545760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401612f4c565b5f80866001600160a01b0316858760405161336f9190613a00565b5f6040518083038185875af1925050503d805f81146133a9576040519150601f19603f3d011682016040523d82523d5f602084013e6133ae565b606091505b50915091506133be8282866133c9565b979650505050505050565b606083156133d8575081613295565b8251156133e85782518084602001fd5b8160405162461bcd60e51b8152600401612f4c9190613424565b5f5b8381101561341c578181015183820152602001613404565b50505f910152565b602081525f8251806020840152613442816040850160208701613402565b601f01601f19169190910160400192915050565b6001600160a01b0381168114610fc1575f80fd5b5f806040838503121561347b575f80fd5b823561348681613456565b946020939093013593505050565b5f602082840312156134a4575f80fd5b5035919050565b5f805f606084860312156134bd575f80fd5b83356134c881613456565b925060208401356134d881613456565b929592945050506040919091013590565b5f602082840312156134f9575f80fd5b813561329581613456565b5f8083601f840112613514575f80fd5b50813567ffffffffffffffff81111561352b575f80fd5b602083019150836020828501011115610dbb575f80fd5b5f805f805f805f8060c0898b031215613559575f80fd5b883567ffffffffffffffff80821115613570575f80fd5b61357c8c838d01613504565b909a50985060208b0135915080821115613594575f80fd5b506135a18b828c01613504565b90975095505060408901356135b581613456565b935060608901356135c581613456565b979a969950949793969295929450505060808201359160a0013590565b5f80604083850312156135f3575f80fd5b82359150602083013561360581613456565b809150509250929050565b5f8060408385031215613621575f80fd5b823561362c81613456565b9150602083013561360581613456565b600181811c9082168061365057607f821691505b60208210810361366e57634e487b7160e01b5f52602260045260245ffd5b50919050565b80516130f481613456565b5f6020828403121561368f575f80fd5b815161329581613456565b634e487b7160e01b5f52601160045260245ffd5b80820180821115612af757612af761369a565b805180151581146130f4575f80fd5b5f602082840312156136e0575f80fd5b612af4826136c1565b5f602082840312156136f9575f80fd5b5051919050565b81810381811115612af757612af761369a565b6001600160a01b03929092168252602082015260400190565b8082028115828204841417612af757612af761369a565b5f8261375d57634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52604160045260245ffd5b601f8211156113d557805f5260205f20601f840160051c8101602085101561379b5750805b601f840160051c820191505b818110156137ba575f81556001016137a7565b5050505050565b67ffffffffffffffff8311156137d9576137d9613762565b6137ed836137e7835461363c565b83613776565b5f601f84116001811461381e575f85156138075750838201355b5f19600387901b1c1916600186901b1783556137ba565b5f83815260208120601f198716915b8281101561384d578685013582556020948501946001909201910161382d565b5086821015613869575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b5f6020828403121561388b575f80fd5b815160ff81168114613295575f80fd5b5f805f805f60a086880312156138af575f80fd5b6138b8866136c1565b602087015160408801516060890151608090990151929a91995097965090945092505050565b5f60208083850312156138ef575f80fd5b825167ffffffffffffffff80821115613906575f80fd5b818501915085601f830112613919575f80fd5b81518181111561392b5761392b613762565b8060051b604051601f19603f8301168101818110858211171561395057613950613762565b60405291825284820192508381018501918883111561396d575f80fd5b938501935b828510156139925761398385613674565b84529385019392850192613972565b98975050505050505050565b634e487b7160e01b5f52603260045260245ffd5b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b5f8251613a11818460208701613402565b919091019291505056fea26469706673582212209345aea9298a6817005a5587ee0edbd299b47749882102085c38a9fc0f7b771a64736f6c63430008180033496e697469616c697a61626c653a20636f6e747261637420697320616c726561","name":"DebtToken","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"cancun","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"contracts/storage/PoolRegistryStorage.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {EnumerableSet} from \"../dependencies/openzeppelin/utils/structs/EnumerableSet.sol\";\nimport {IMasterOracle} from \"../interfaces/external/IMasterOracle.sol\";\nimport {ISwapper} from \"../interfaces/external/ISwapper.sol\";\nimport {IPoolRegistry} from \"../interfaces/IPoolRegistry.sol\";\nimport {IOperator} from \"../interfaces/IOperator.sol\";\n\nabstract contract PoolRegistryStorageV1 is IPoolRegistry {\n    /**\n     * @notice Pools collection\n     */\n    EnumerableSet.AddressSet internal pools;\n\n    /**\n     * @notice Prices' oracle\n     */\n    IMasterOracle public override masterOracle;\n\n    /**\n     * @notice Fee collector address\n     */\n    address public override feeCollector;\n\n    /**\n     * @notice Native token gateway address\n     */\n    address public override nativeTokenGateway;\n\n    /**\n     * @notice Map of the ids of the pools\n     */\n    mapping(address => uint256) public override idOfPool;\n\n    /**\n     * @notice Counter of ids of the pools\n     */\n    uint256 public override nextPoolId;\n\n    /**\n     * @notice Swapper contract\n     */\n    ISwapper public swapper;\n}\n\nabstract contract PoolRegistryStorageV2 is PoolRegistryStorageV1 {\n    /**\n     * @notice The Quoter contract\n     */\n    address private quoter_DEPRECATED;\n\n    /**\n     * @notice The Cross-chain dispatcher contract\n     */\n    address private crossChainDispatcher_DEPRECATED;\n}\n\nabstract contract PoolRegistryStorageV3 is PoolRegistryStorageV2 {\n    /**\n     * @notice Flag that pause/unpause all cross-chain flash repay operations\n     */\n    bool private isCrossChainFlashRepayActive_DEPRECATED;\n}\n\nabstract contract PoolRegistryStorageV4 is PoolRegistryStorageV3 {\n    /**\n     * @notice Pools collection\n     */\n    EnumerableSet.AddressSet internal guardians;\n\n    /**\n     * @notice Flag that pause/unpause all cross-chain flash repay operations\n     */\n    IOperator public operator;\n}\n\nabstract contract PoolRegistryStorageV5 is PoolRegistryStorageV4 {\n    /**\n     * @notice The base gas to pay for cross-chain calls\n     * @dev This limit covers basic token transfer LZ cost\n     */\n    uint256 public lzBaseGasLimit;\n\n    /**\n     * @notice Flag that pause/unpause all cross-chain activities\n     */\n    bool public isBridgingActive;\n\n    /**\n     * @notice Maps supported cross-chain routes (i.e. which chains are allowed to be used as source of liquidity)\n     */\n    mapping(uint16 => bool) public isDestinationChainSupported;\n}\n"},{"file_path":"contracts/utils/SynthContext.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {Context} from \"../dependencies/openzeppelin/utils/Context.sol\";\nimport {IOperator} from \"../interfaces/IOperator.sol\";\nimport {IPoolRegistry} from \"../interfaces/IPoolRegistry.sol\";\n\nabstract contract SynthContext is Context {\n    /// @notice Get pool registry contract\n    function poolRegistry() public view virtual returns (IPoolRegistry);\n\n    /// @inheritdoc Context\n    function _msgSender() internal view virtual override returns (address) {\n        IPoolRegistry _poolRegistry = poolRegistry();\n        if (address(_poolRegistry) != address(0)) {\n            IOperator _operator = _poolRegistry.operator();\n            if (msg.sender == address(_operator)) {\n                return _operator.getActualMsgSender();\n            }\n        }\n\n        return msg.sender;\n    }\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/token/oft/composable/IOFTReceiver.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface IOFTReceiver {\n    /**\n     * @dev Called by the OFT contract when tokens are received from source chain.\n     * @param _srcChainId The chain id of the source chain.\n     * @param _srcAddress The address of the OFT token contract on the source chain.\n     * @param _nonce The nonce of the transaction on the source chain.\n     * @param _from The address of the account who calls the sendAndCall() on the source chain.\n     * @param _amount The amount of tokens to transfer.\n     * @param _payload Additional data with no specified format.\n     */\n    function onOFTReceived(\n        uint16 _srcChainId,\n        bytes calldata _srcAddress,\n        uint64 _nonce,\n        bytes calldata _from,\n        uint _amount,\n        bytes calldata _payload\n    ) external;\n}\n"},{"file_path":"contracts/interfaces/external/IWETH.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IERC20} from \"../../dependencies/openzeppelin/token/ERC20/IERC20.sol\";\n\ninterface IWETH is IERC20 {\n    function deposit() external payable;\n\n    function withdraw(uint256) external;\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/proxy/transparent/ProxyAdmin.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./TransparentUpgradeableProxy.sol\";\nimport \"../../access/Ownable.sol\";\n\n/**\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\n */\ncontract ProxyAdmin is Ownable {\n    /**\n     * @dev Returns the current implementation of `proxy`.\n     *\n     * Requirements:\n     *\n     * - This contract must be the admin of `proxy`.\n     */\n    function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n        // We need to manually run the static call since the getter cannot be flagged as view\n        // bytes4(keccak256(\"implementation()\")) == 0x5c60da1b\n        (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"5c60da1b\");\n        require(success);\n        return abi.decode(returndata, (address));\n    }\n\n    /**\n     * @dev Returns the current admin of `proxy`.\n     *\n     * Requirements:\n     *\n     * - This contract must be the admin of `proxy`.\n     */\n    function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n        // We need to manually run the static call since the getter cannot be flagged as view\n        // bytes4(keccak256(\"admin()\")) == 0xf851a440\n        (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"f851a440\");\n        require(success);\n        return abi.decode(returndata, (address));\n    }\n\n    /**\n     * @dev Changes the admin of `proxy` to `newAdmin`.\n     *\n     * Requirements:\n     *\n     * - This contract must be the current admin of `proxy`.\n     */\n    function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\n        proxy.changeAdmin(newAdmin);\n    }\n\n    /**\n     * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\n     *\n     * Requirements:\n     *\n     * - This contract must be the admin of `proxy`.\n     */\n    function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\n        proxy.upgradeTo(implementation);\n    }\n\n    /**\n     * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\n     * {TransparentUpgradeableProxy-upgradeToAndCall}.\n     *\n     * Requirements:\n     *\n     * - This contract must be the admin of `proxy`.\n     */\n    function upgradeAndCall(\n        TransparentUpgradeableProxy proxy,\n        address implementation,\n        bytes memory data\n    ) public payable virtual onlyOwner {\n        proxy.upgradeToAndCall{value: msg.value}(implementation, data);\n    }\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/interfaces/draft-IERC1822.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n    /**\n     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n     * address.\n     *\n     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n     * function revert if invoked through a proxy.\n     */\n    function proxiableUUID() external view returns (bytes32);\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/utils/introspection/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/contracts-upgradeable/interfaces/ILayerZeroReceiverUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.2;\n\ninterface ILayerZeroReceiverUpgradeable {\n    // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n    // @param _srcChainId - the source endpoint identifier\n    // @param _srcAddress - the source sending contract address from the source chain\n    // @param _nonce - the ordered message nonce\n    // @param _payload - the signed payload is the UA bytes has encoded to be sent\n    function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n"},{"file_path":"contracts/interfaces/external/IMasterOracle.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\ninterface IMasterOracle {\n    function quoteTokenToUsd(address _asset, uint256 _amount) external view returns (uint256 _amountInUsd);\n\n    function quoteUsdToToken(address _asset, uint256 _amountInUsd) external view returns (uint256 _amount);\n\n    function quote(address _assetIn, address _assetOut, uint256 _amountIn) external view returns (uint256 _amountOut);\n}\n"},{"file_path":"contracts/mock/TokenHolderMock.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {TokenHolder} from \"../utils/TokenHolder.sol\";\n\ncontract TokenHolderMock is TokenHolder {\n    address public sweeper;\n    bool public acceptETH;\n\n    constructor(address _sweeper) {\n        sweeper = _sweeper;\n    }\n\n    function _requireCanSweep() internal view override {\n        require(msg.sender == sweeper, \"not-sweeper\");\n    }\n\n    function toggleAcceptETH() public {\n        acceptETH = !acceptETH;\n    }\n\n    receive() external payable override {\n        require(acceptETH, \"not-allowed-to-receive-eth\");\n    }\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/token/oft/composable/IComposableOFT.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\nimport \"./IComposableOFTCore.sol\";\nimport \"../IOFT.sol\";\n\n/**\n * @dev Interface of the OFT standard\n */\ninterface IComposableOFT is IOFT, IComposableOFTCore {\n\n}\n"},{"file_path":"contracts/mock/SwapperMock.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IERC20} from \"../dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {IMasterOracle} from \"../interfaces/external/IMasterOracle.sol\";\nimport {ISwapper} from \"../interfaces/external/ISwapper.sol\";\n\ncontract SwapperMock is ISwapper {\n    uint256 public rate = 1e18;\n    IMasterOracle masterOracle;\n\n    constructor(IMasterOracle masterOracle_) {\n        masterOracle = masterOracle_;\n    }\n\n    function swapExactInput(\n        address tokenIn_,\n        address tokenOut_,\n        uint256 amountIn_,\n        uint256 amountOutMin_,\n        address receiver_\n    ) external returns (uint256 _amountOut) {\n        IERC20(tokenIn_).transferFrom(msg.sender, address(this), amountIn_);\n        _amountOut = (masterOracle.quote(tokenIn_, tokenOut_, amountIn_) * rate) / 1e18;\n        require(_amountOut >= amountOutMin_, \"swapper-mock-slippage\");\n        require(_amountOut > 100, \"amount-out-zero\");\n        IERC20(tokenOut_).transfer(receiver_, _amountOut);\n    }\n\n    function updateRate(uint256 rate_) external {\n        rate = rate_;\n    }\n}\n"},{"file_path":"contracts/storage/DebtTokenStorage.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IDebtToken} from \"../interfaces/IDebtToken.sol\";\nimport {ISyntheticToken} from \"../interfaces/ISyntheticToken.sol\";\n\nabstract contract DebtTokenStorageV1 is IDebtToken {\n    /**\n     * @notice The name of the token\n     */\n    string public override name;\n\n    /**\n     * @notice The symbol of the token\n     */\n    string public override symbol;\n\n    /**\n     * @notice The mapping of the users' minted tokens\n     * @dev This value changes within the mint and burn operations\n     */\n    mapping(address => uint256) internal principalOf;\n\n    /**\n     * @notice The `debtIndex` \"snapshot\" of the account's latest `principalOf` update (i.e. mint/burn)\n     */\n    mapping(address => uint256) internal debtIndexOf;\n\n    /**\n     * @notice The supply cap\n     */\n    uint256 public override maxTotalSupply;\n\n    /**\n     * @notice The total amount of minted tokens\n     */\n    uint256 internal totalSupply_;\n\n    /**\n     * @notice The timestamp when interest accrual was calculated for the last time\n     */\n    uint256 public override lastTimestampAccrued;\n\n    /**\n     * @notice Accumulator of the total earned interest rate since the beginning\n     */\n    uint256 public override debtIndex;\n\n    /**\n     * @notice Interest rate\n     * @dev Use 0.1e18 for 10% APR\n     */\n    uint256 public override interestRate;\n\n    /**\n     * @notice The Synthetic token\n     */\n    ISyntheticToken public override syntheticToken;\n\n    /**\n     * @notice If true, disables msAsset minting on this pool\n     */\n    bool public override isActive;\n\n    /**\n     * @notice The decimals of the token\n     */\n    uint8 public override decimals;\n}\n\nabstract contract DebtTokenStorageV2 is DebtTokenStorageV1 {\n    /**\n     * @notice Pending interest fee to collect\n     */\n    uint256 internal pendingInterestFee;\n}\n"},{"file_path":"contracts/interfaces/IRewardsDistributor.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IERC20} from \"../dependencies/openzeppelin/token/ERC20/IERC20.sol\";\n\n/**\n * @notice Reward Distributor interface\n */\ninterface IRewardsDistributor {\n    function rewardToken() external view returns (IERC20);\n\n    function tokenSpeeds(IERC20 token_) external view returns (uint256);\n\n    function tokensAccruedOf(address account_) external view returns (uint256);\n\n    function updateBeforeMintOrBurn(IERC20 token_, address account_) external;\n\n    function updateBeforeTransfer(IERC20 token_, address from_, address to_) external;\n\n    function claimable(address account_) external view returns (uint256 _claimable);\n\n    function claimable(address account_, IERC20 token_) external view returns (uint256 _claimable);\n\n    function claimRewards(address account_) external;\n\n    function claimRewards(address account_, IERC20[] memory tokens_) external;\n\n    function claimRewards(address[] memory accounts_, IERC20[] memory tokens_) external;\n\n    function updateTokenSpeed(IERC20 token_, uint256 newSpeed_) external;\n\n    function updateTokenSpeeds(IERC20[] calldata tokens_, uint256[] calldata speeds_) external;\n\n    function tokens(uint256) external view returns (IERC20);\n\n    function tokenStates(IERC20) external view returns (uint224 index, uint32 timestamp);\n\n    function accountIndexOf(IERC20, address) external view returns (uint256);\n}\n"},{"file_path":"contracts/mock/TokenOracleMock.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\ncontract TokenOracleMock {\n    mapping(address => uint256) public prices;\n\n    function updatePrice(address token_, uint256 price_) external {\n        prices[token_] = price_;\n    }\n\n    function getPriceInUsd(address token_) external view returns (uint256 _priceInUsd) {\n        return prices[token_];\n    }\n}\n"},{"file_path":"contracts/interfaces/external/IPoolRewards.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\ninterface IPoolRewards {\n    function claimReward(address) external;\n\n    function updateReward(address) external;\n\n    function getRewardTokens() external view returns (address[] memory);\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/utils/math/SafeCast.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits.\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value >= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128) {\n        require(value >= type(int128).min && value <= type(int128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return int128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64) {\n        require(value >= type(int64).min && value <= type(int64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return int64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32) {\n        require(value >= type(int32).min && value <= type(int32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return int32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16) {\n        require(value >= type(int16).min && value <= type(int16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return int16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits.\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8) {\n        require(value >= type(int8).min && value <= type(int8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return int8(value);\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/interfaces/ILayerZeroReceiver.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n    // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n    // @param _srcChainId - the source endpoint identifier\n    // @param _srcAddress - the source sending contract address from the source chain\n    // @param _nonce - the ordered message nonce\n    // @param _payload - the signed payload is the UA bytes has encoded to be sent\n    function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/proxy/beacon/IBeacon.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n    /**\n     * @dev Must return an address that can be used as a delegate call target.\n     *\n     * {BeaconProxy} will check that this address is a contract.\n     */\n    function implementation() external view returns (address);\n}\n"},{"file_path":"contracts/interfaces/IPauseable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\ninterface IPauseable {\n    function paused() external view returns (bool);\n\n    function everythingStopped() external view returns (bool);\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/contracts-upgradeable/token/oft/OFTCoreUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.2;\n\nimport \"./IOFTCoreUpgradeable.sol\";\nimport \"../../../../../openzeppelin-upgradeable/utils/introspection/ERC165Upgradeable.sol\";\nimport \"../../lzApp/NonblockingLzAppUpgradeable.sol\";\n\nabstract contract OFTCoreUpgradeable is\n    Initializable,\n    NonblockingLzAppUpgradeable,\n    ERC165Upgradeable,\n    IOFTCoreUpgradeable\n{\n    using BytesLib for bytes;\n\n    uint public constant NO_EXTRA_GAS = 0;\n\n    // packet type\n    uint16 public constant PT_SEND = 0;\n\n    bool public useCustomAdapterParams;\n\n    function __OFTCoreUpgradeable_init(address _lzEndpoint) internal onlyInitializing {\n        __Ownable_init_unchained();\n        __LzAppUpgradeable_init_unchained(_lzEndpoint);\n    }\n\n    function __OFTCoreUpgradeable_init_unchained() internal onlyInitializing {}\n\n    function supportsInterface(\n        bytes4 interfaceId\n    ) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {\n        return interfaceId == type(IOFTCoreUpgradeable).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    function estimateSendFee(\n        uint16 _dstChainId,\n        bytes calldata _toAddress,\n        uint _amount,\n        bool _useZro,\n        bytes calldata _adapterParams\n    ) public view virtual override returns (uint nativeFee, uint zroFee) {\n        // mock the payload for sendFrom()\n        bytes memory payload = abi.encode(PT_SEND, _toAddress, _amount);\n        return lzEndpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _adapterParams);\n    }\n\n    function sendFrom(\n        address _from,\n        uint16 _dstChainId,\n        bytes calldata _toAddress,\n        uint _amount,\n        address payable _refundAddress,\n        address _zroPaymentAddress,\n        bytes calldata _adapterParams\n    ) public payable virtual override {\n        _send(_from, _dstChainId, _toAddress, _amount, _refundAddress, _zroPaymentAddress, _adapterParams);\n    }\n\n    function setUseCustomAdapterParams(bool _useCustomAdapterParams) public virtual onlyOwner {\n        useCustomAdapterParams = _useCustomAdapterParams;\n        emit SetUseCustomAdapterParams(_useCustomAdapterParams);\n    }\n\n    function _nonblockingLzReceive(\n        uint16 _srcChainId,\n        bytes memory _srcAddress,\n        uint64 _nonce,\n        bytes memory _payload\n    ) internal virtual override {\n        uint16 packetType;\n        assembly {\n            packetType := mload(add(_payload, 32))\n        }\n\n        if (packetType == PT_SEND) {\n            _sendAck(_srcChainId, _srcAddress, _nonce, _payload);\n        } else {\n            revert(\"OFTCore: unknown packet type\");\n        }\n    }\n\n    function _send(\n        address _from,\n        uint16 _dstChainId,\n        bytes memory _toAddress,\n        uint _amount,\n        address payable _refundAddress,\n        address _zroPaymentAddress,\n        bytes memory _adapterParams\n    ) internal virtual {\n        _checkAdapterParams(_dstChainId, PT_SEND, _adapterParams, NO_EXTRA_GAS);\n\n        uint amount = _debitFrom(_from, _dstChainId, _toAddress, _amount);\n\n        bytes memory lzPayload = abi.encode(PT_SEND, _toAddress, amount);\n        _lzSend(_dstChainId, lzPayload, _refundAddress, _zroPaymentAddress, _adapterParams, msg.value);\n\n        emit SendToChain(_dstChainId, _from, _toAddress, amount);\n    }\n\n    function _sendAck(uint16 _srcChainId, bytes memory, uint64, bytes memory _payload) internal virtual {\n        (, bytes memory toAddressBytes, uint amount) = abi.decode(_payload, (uint16, bytes, uint));\n\n        address to = toAddressBytes.toAddress(0);\n\n        amount = _creditTo(_srcChainId, to, amount);\n        emit ReceiveFromChain(_srcChainId, to, amount);\n    }\n\n    function _checkAdapterParams(\n        uint16 _dstChainId,\n        uint16 _pkType,\n        bytes memory _adapterParams,\n        uint _extraGas\n    ) internal virtual {\n        if (useCustomAdapterParams) {\n            _checkGasLimit(_dstChainId, _pkType, _adapterParams, _extraGas);\n        } else {\n            require(_adapterParams.length == 0, \"OFTCore: _adapterParams must be empty.\");\n        }\n    }\n\n    function _debitFrom(\n        address _from,\n        uint16 _dstChainId,\n        bytes memory _toAddress,\n        uint _amount\n    ) internal virtual returns (uint);\n\n    function _creditTo(uint16 _srcChainId, address _toAddress, uint _amount) internal virtual returns (uint);\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    uint[49] private __gap;\n}\n"},{"file_path":"contracts/mock/VPoolMock.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IERC20, IERC20Metadata, ERC20} from \"../dependencies/openzeppelin/token/ERC20/ERC20.sol\";\nimport {IVPool} from \"../interfaces/external/IVPool.sol\";\n\ncontract VPoolMock is IVPool, ERC20 {\n    address public token;\n\n    constructor(string memory name_, string memory symbol_, address token_) ERC20(name_, symbol_) {\n        token = token_;\n    }\n\n    function deposit(uint256 amount_) external {\n        IERC20(token).transferFrom(msg.sender, address(this), amount_);\n        _mint(msg.sender, amount_ * (10 ** (decimals() - IERC20Metadata(token).decimals())));\n    }\n\n    function withdraw(uint256 shares_) external {\n        _burn(msg.sender, shares_);\n        IERC20(token).transfer(msg.sender, shares_ / (10 ** (decimals() - IERC20Metadata(token).decimals())));\n    }\n\n    function mint(address to_, uint256 amount_) external {\n        _mint(to_, amount_);\n    }\n\n    function poolRewards() external pure returns (address) {\n        revert(\"mock-does-not-implement\");\n    }\n\n    function pricePerShare() external pure returns (uint256) {\n        revert(\"mock-does-not-implement\");\n    }\n}\n"},{"file_path":"contracts/interfaces/IFeeProvider.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\n/**\n * @notice FeeProvider interface\n */\ninterface IFeeProvider {\n    struct LiquidationFees {\n        uint128 liquidatorIncentive;\n        uint128 protocolFee;\n    }\n\n    function swapFees(address synthIn, address synthOut) external view returns (uint256);\n\n    function depositFee() external view returns (uint256);\n\n    function issueFee() external view returns (uint256);\n\n    function liquidationFees() external view returns (uint128 liquidatorIncentive, uint128 protocolFee);\n\n    function repayFee() external view returns (uint256);\n\n    function withdrawFee() external view returns (uint256);\n}\n"},{"file_path":"contracts/utils/ReentrancyGuardTransient.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.24;\n\nimport {TransientSlot} from \"../dependencies/openzeppelin/utils/TransientSlot.sol\";\n\n/**\n * @dev Variant of {ReentrancyGuard} that uses transient storage.\n *\n * NOTE: This variant only works on networks where EIP-1153 is available.\n *\n * _Available since v5.1._\n */\nabstract contract ReentrancyGuardTransient {\n    using TransientSlot for *;\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant REENTRANCY_GUARD_STORAGE =\n        0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        if (_reentrancyGuardEntered()) {\n            revert ReentrancyGuardReentrantCall();\n        }\n\n        // Any calls to nonReentrant after this point will fail\n        REENTRANCY_GUARD_STORAGE.asBoolean().tstore(true);\n    }\n\n    function _nonReentrantAfter() private {\n        REENTRANCY_GUARD_STORAGE.asBoolean().tstore(false);\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 REENTRANCY_GUARD_STORAGE.asBoolean().tload();\n    }\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/contracts-upgradeable/lzApp/LzAppUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.2;\n\nimport \"../../../../openzeppelin-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"../interfaces/ILayerZeroReceiverUpgradeable.sol\";\nimport \"../interfaces/ILayerZeroUserApplicationConfigUpgradeable.sol\";\nimport \"../interfaces/ILayerZeroEndpointUpgradeable.sol\";\nimport \"../../util/BytesLib.sol\";\n\n/*\n * a generic LzReceiver implementation\n */\nabstract contract LzAppUpgradeable is\n    Initializable,\n    OwnableUpgradeable,\n    ILayerZeroReceiverUpgradeable,\n    ILayerZeroUserApplicationConfigUpgradeable\n{\n    using BytesLib for bytes;\n\n    // ua can not send payload larger than this by default, but it can be changed by the ua owner\n    uint public constant DEFAULT_PAYLOAD_SIZE_LIMIT = 10000;\n\n    ILayerZeroEndpointUpgradeable public lzEndpoint;\n    mapping(uint16 => bytes) public trustedRemoteLookup;\n    mapping(uint16 => mapping(uint16 => uint)) public minDstGasLookup;\n    mapping(uint16 => uint) public payloadSizeLimitLookup;\n    address public precrime;\n\n    event SetPrecrime(address precrime);\n    event SetTrustedRemote(uint16 _remoteChainId, bytes _path);\n    event SetTrustedRemoteAddress(uint16 _remoteChainId, bytes _remoteAddress);\n    event SetMinDstGas(uint16 _dstChainId, uint16 _type, uint _minDstGas);\n\n    function __LzAppUpgradeable_init(address _endpoint) internal onlyInitializing {\n        __Ownable_init_unchained();\n        __LzAppUpgradeable_init_unchained(_endpoint);\n    }\n\n    function __LzAppUpgradeable_init_unchained(address _endpoint) internal onlyInitializing {\n        lzEndpoint = ILayerZeroEndpointUpgradeable(_endpoint);\n    }\n\n    function lzReceive(\n        uint16 _srcChainId,\n        bytes calldata _srcAddress,\n        uint64 _nonce,\n        bytes calldata _payload\n    ) public virtual override {\n        // lzReceive must be called by the endpoint for security\n        require(_msgSender() == address(lzEndpoint), \"LzApp: invalid endpoint caller\");\n\n        bytes memory trustedRemote = trustedRemoteLookup[_srcChainId];\n        // if will still block the message pathway from (srcChainId, srcAddress). should not receive message from untrusted remote.\n        require(\n            _srcAddress.length == trustedRemote.length &&\n                trustedRemote.length > 0 &&\n                keccak256(_srcAddress) == keccak256(trustedRemote),\n            \"LzApp: invalid source sending contract\"\n        );\n\n        _blockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);\n    }\n\n    // abstract function - the default behaviour of LayerZero is blocking. See: NonblockingLzApp if you dont need to enforce ordered messaging\n    function _blockingLzReceive(\n        uint16 _srcChainId,\n        bytes memory _srcAddress,\n        uint64 _nonce,\n        bytes memory _payload\n    ) internal virtual;\n\n    function _lzSend(\n        uint16 _dstChainId,\n        bytes memory _payload,\n        address payable _refundAddress,\n        address _zroPaymentAddress,\n        bytes memory _adapterParams,\n        uint _nativeFee\n    ) internal virtual {\n        bytes memory trustedRemote = trustedRemoteLookup[_dstChainId];\n        require(trustedRemote.length != 0, \"LzApp: destination chain is not a trusted source\");\n        _checkPayloadSize(_dstChainId, _payload.length);\n        lzEndpoint.send{value: _nativeFee}(\n            _dstChainId,\n            trustedRemote,\n            _payload,\n            _refundAddress,\n            _zroPaymentAddress,\n            _adapterParams\n        );\n    }\n\n    function _checkGasLimit(\n        uint16 _dstChainId,\n        uint16 _type,\n        bytes memory _adapterParams,\n        uint _extraGas\n    ) internal view virtual {\n        uint providedGasLimit = _getGasLimit(_adapterParams);\n        uint minGasLimit = minDstGasLookup[_dstChainId][_type] + _extraGas;\n        require(minGasLimit > 0, \"LzApp: minGasLimit not set\");\n        require(providedGasLimit >= minGasLimit, \"LzApp: gas limit is too low\");\n    }\n\n    function _getGasLimit(bytes memory _adapterParams) internal pure virtual returns (uint gasLimit) {\n        require(_adapterParams.length >= 34, \"LzApp: invalid adapterParams\");\n        assembly {\n            gasLimit := mload(add(_adapterParams, 34))\n        }\n    }\n\n    function _checkPayloadSize(uint16 _dstChainId, uint _payloadSize) internal view virtual {\n        uint payloadSizeLimit = payloadSizeLimitLookup[_dstChainId];\n        if (payloadSizeLimit == 0) {\n            // use default if not set\n            payloadSizeLimit = DEFAULT_PAYLOAD_SIZE_LIMIT;\n        }\n        require(_payloadSize <= payloadSizeLimit, \"LzApp: payload size is too large\");\n    }\n\n    //---------------------------UserApplication config----------------------------------------\n    function getConfig(\n        uint16 _version,\n        uint16 _chainId,\n        address,\n        uint _configType\n    ) external view returns (bytes memory) {\n        return lzEndpoint.getConfig(_version, _chainId, address(this), _configType);\n    }\n\n    // generic config for LayerZero user Application\n    function setConfig(\n        uint16 _version,\n        uint16 _chainId,\n        uint _configType,\n        bytes calldata _config\n    ) external override onlyOwner {\n        lzEndpoint.setConfig(_version, _chainId, _configType, _config);\n    }\n\n    function setSendVersion(uint16 _version) external override onlyOwner {\n        lzEndpoint.setSendVersion(_version);\n    }\n\n    function setReceiveVersion(uint16 _version) external override onlyOwner {\n        lzEndpoint.setReceiveVersion(_version);\n    }\n\n    function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external override onlyOwner {\n        lzEndpoint.forceResumeReceive(_srcChainId, _srcAddress);\n    }\n\n    // _path = abi.encodePacked(remoteAddress, localAddress)\n    // this function set the trusted path for the cross-chain communication\n    function setTrustedRemote(uint16 _srcChainId, bytes calldata _path) external onlyOwner {\n        trustedRemoteLookup[_srcChainId] = _path;\n        emit SetTrustedRemote(_srcChainId, _path);\n    }\n\n    function setTrustedRemoteAddress(uint16 _remoteChainId, bytes calldata _remoteAddress) external onlyOwner {\n        trustedRemoteLookup[_remoteChainId] = abi.encodePacked(_remoteAddress, address(this));\n        emit SetTrustedRemoteAddress(_remoteChainId, _remoteAddress);\n    }\n\n    function getTrustedRemoteAddress(uint16 _remoteChainId) external view returns (bytes memory) {\n        bytes memory path = trustedRemoteLookup[_remoteChainId];\n        require(path.length != 0, \"LzApp: no trusted path record\");\n        return path.slice(0, path.length - 20); // the last 20 bytes should be address(this)\n    }\n\n    function setPrecrime(address _precrime) external onlyOwner {\n        precrime = _precrime;\n        emit SetPrecrime(_precrime);\n    }\n\n    function setMinDstGas(uint16 _dstChainId, uint16 _packetType, uint _minGas) external onlyOwner {\n        require(_minGas > 0, \"LzApp: invalid minGas\");\n        minDstGasLookup[_dstChainId][_packetType] = _minGas;\n        emit SetMinDstGas(_dstChainId, _packetType, _minGas);\n    }\n\n    // if the size is 0, it means default size limit\n    function setPayloadSizeLimit(uint16 _dstChainId, uint _size) external onlyOwner {\n        payloadSizeLimitLookup[_dstChainId] = _size;\n    }\n\n    //--------------------------- VIEW FUNCTION ----------------------------------------\n    function isTrustedRemote(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool) {\n        bytes memory trustedSource = trustedRemoteLookup[_srcChainId];\n        return keccak256(trustedSource) == keccak256(_srcAddress);\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    uint[45] private __gap;\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/token/ERC20/ERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n\n// OpenZeppelin Contracts (last updated v4.8.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":"contracts/storage/ProxyOFTStorage.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {ISyntheticToken} from \"../interfaces/ISyntheticToken.sol\";\nimport {IProxyOFT} from \"../interfaces/IProxyOFT.sol\";\n\nabstract contract ProxyOFTStorageV1 is IProxyOFT {\n    /**\n     * @notice The synthetic token contract\n     */\n    ISyntheticToken internal syntheticToken;\n}\n\nabstract contract ProxyOFTStorageV2 is ProxyOFTStorageV1 {\n    /**\n     * @notice The fee charged on the source chain when bridging synthetic tokens\n     * @dev Use 18 decimals (e.g. 1e16 = 1%)\n     */\n    uint256 public override oftFee;\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/utils/StorageSlot.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n *     function _getImplementation() internal view returns (address) {\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n *     }\n *\n *     function _setImplementation(address newImplementation) internal {\n *         require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlot {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct BooleanSlot {\n        bool value;\n    }\n\n    struct Bytes32Slot {\n        bytes32 value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    /**\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n     */\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        assembly {\n            r.slot := slot\n        }\n    }\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/token/ERC20/utils/SafeERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    function safeTransfer(\n        IERC20 token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value\n    ) 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(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) 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    function safeIncreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        if (returndata.length > 0) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/contracts-upgradeable/interfaces/ILayerZeroUserApplicationConfigUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.2;\n\ninterface ILayerZeroUserApplicationConfigUpgradeable {\n    // @notice set the configuration of the LayerZero messaging library of the specified version\n    // @param _version - messaging library version\n    // @param _chainId - the chainId for the pending config change\n    // @param _configType - type of configuration. every messaging library has its own convention.\n    // @param _config - configuration in the bytes. can encode arbitrary content.\n    function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n    // @notice set the send() LayerZero messaging library version to _version\n    // @param _version - new messaging library version\n    function setSendVersion(uint16 _version) external;\n\n    // @notice set the lzReceive() LayerZero messaging library version to _version\n    // @param _version - new messaging library version\n    function setReceiveVersion(uint16 _version) external;\n\n    // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n    // @param _srcChainId - the chainId of the source chain\n    // @param _srcAddress - the contract address of the source contract at the source chain\n    function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/contracts-upgradeable/token/oft/composable/IComposableOFTCoreUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\nimport \"../IOFTCoreUpgradeable.sol\";\n\n/**\n * @dev Interface of the composable OFT core standard\n */\ninterface IComposableOFTCoreUpgradeable is IOFTCoreUpgradeable {\n    function estimateSendAndCallFee(\n        uint16 _dstChainId,\n        bytes calldata _toAddress,\n        uint _amount,\n        bytes calldata _payload,\n        uint64 _dstGasForCall,\n        bool _useZro,\n        bytes calldata _adapterParams\n    ) external view returns (uint nativeFee, uint zroFee);\n\n    function sendAndCall(\n        address _from,\n        uint16 _dstChainId,\n        bytes calldata _toAddress,\n        uint _amount,\n        bytes calldata _payload,\n        uint64 _dstGasForCall,\n        address payable _refundAddress,\n        address _zroPaymentAddress,\n        bytes calldata _adapterParams\n    ) external payable;\n\n    function retryOFTReceived(\n        uint16 _srcChainId,\n        bytes calldata _srcAddress,\n        uint64 _nonce,\n        bytes calldata _from,\n        address _to,\n        uint _amount,\n        bytes calldata _payload\n    ) external;\n\n    event CallOFTReceivedFailure(\n        uint16 indexed _srcChainId,\n        bytes _srcAddress,\n        uint64 _nonce,\n        bytes _from,\n        address indexed _to,\n        uint _amount,\n        bytes _payload,\n        bytes _reason\n    );\n\n    event CallOFTReceivedSuccess(uint16 indexed _srcChainId, bytes _srcAddress, uint64 _nonce, bytes32 _hash);\n\n    event RetryOFTReceivedSuccess(bytes32 _messageHash);\n\n    event NonContractAddress(address _address);\n}\n"},{"file_path":"contracts/interfaces/external/IVPool.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IERC20} from \"../../dependencies/openzeppelin/token/ERC20/IERC20.sol\";\n\ninterface IVPool is IERC20 {\n    function token() external view returns (address _token);\n\n    function deposit(uint256 _amount) external;\n\n    function withdraw(uint256 _shares) external;\n\n    function poolRewards() external view returns (address);\n\n    function pricePerShare() external view returns (uint256);\n}\n"},{"file_path":"contracts/interfaces/external/IStargateBridge.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {ILayerZeroEndpoint} from \"../../dependencies/@layerzerolabs/solidity-examples/interfaces/ILayerZeroEndpoint.sol\";\n\ninterface IStargateBridge {\n    function layerZeroEndpoint() external view returns (ILayerZeroEndpoint _lzEndpoint);\n}\n"},{"file_path":"contracts/NativeTokenGateway.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {Address} from \"./dependencies/openzeppelin/utils/Address.sol\";\nimport {SafeERC20} from \"./dependencies/openzeppelin/token/ERC20/utils/SafeERC20.sol\";\nimport {IERC20} from \"./dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {SynthContext} from \"./utils/SynthContext.sol\";\nimport {ReentrancyGuardTransient} from \"./utils/ReentrancyGuardTransient.sol\";\nimport {TokenHolder} from \"./utils/TokenHolder.sol\";\nimport {IWETH} from \"./interfaces/external/IWETH.sol\";\nimport {INativeTokenGateway} from \"./interfaces/INativeTokenGateway.sol\";\nimport {IDepositToken} from \"./interfaces/IDepositToken.sol\";\nimport {IPoolRegistry} from \"./interfaces/IPoolRegistry.sol\";\nimport {IPool} from \"./interfaces/IPool.sol\";\n\nerror SenderIsNotGovernor();\nerror SenderIsNotNativeToken();\nerror UnregisteredPool();\n\n/**\n * @title Helper contract to easily support native tokens (e.g. ETH/AVAX) as collateral\n */\ncontract NativeTokenGateway is SynthContext, ReentrancyGuardTransient, TokenHolder, INativeTokenGateway {\n    using SafeERC20 for IERC20;\n    using SafeERC20 for IWETH;\n    using SafeERC20 for IDepositToken;\n\n    IPoolRegistry internal immutable _poolRegistry;\n    IWETH public immutable nativeToken;\n\n    modifier onlyGovernor() {\n        if (_poolRegistry.governor() != _msgSender()) revert SenderIsNotGovernor();\n        _;\n    }\n\n    constructor(IPoolRegistry poolRegistry_, IWETH nativeToken_) {\n        _poolRegistry = poolRegistry_;\n        nativeToken = nativeToken_;\n    }\n\n    /**\n     * @notice deposits NATIVE_TOKEN as collateral using native. A corresponding amount of the deposit token is minted.\n     * @param pool_ The Pool contract\n     */\n    function deposit(IPool pool_) external payable override {\n        if (!_poolRegistry.isPoolRegistered(address(pool_))) revert UnregisteredPool();\n\n        nativeToken.deposit{value: msg.value}();\n        IDepositToken _depositToken = pool_.depositTokenOf(nativeToken);\n        nativeToken.safeApprove(address(_depositToken), 0);\n        nativeToken.safeApprove(address(_depositToken), msg.value);\n        _depositToken.deposit(msg.value, _msgSender());\n    }\n\n    /**\n     * @notice withdraws the NATIVE_TOKEN deposit of _msgSender().\n     * @param pool_ The Pool contract\n     * @param amount_ The amount of deposit tokens to withdraw and receive native ETH\n     */\n    function withdraw(IPool pool_, uint256 amount_) external override nonReentrant {\n        if (!_poolRegistry.isPoolRegistered(address(pool_))) revert UnregisteredPool();\n\n        address _msgSender = _msgSender();\n        IDepositToken _depositToken = pool_.depositTokenOf(nativeToken);\n        _depositToken.safeTransferFrom(_msgSender, address(this), amount_);\n        (uint256 _withdrawn, ) = _depositToken.withdraw(amount_, address(this));\n        nativeToken.withdraw(_withdrawn);\n        Address.sendValue(payable(_msgSender), _withdrawn);\n    }\n\n    /// @inheritdoc SynthContext\n    function poolRegistry() public view override returns (IPoolRegistry) {\n        return _poolRegistry;\n    }\n\n    /// @inheritdoc TokenHolder\n    // solhint-disable-next-line no-empty-blocks\n    function _requireCanSweep() internal view override onlyGovernor {}\n\n    /**\n     * @dev Only `nativeToken` contract is allowed to transfer to here. Prevent other addresses to send coins to this contract.\n     */\n    receive() external payable override {\n        if (_msgSender() != address(nativeToken)) revert SenderIsNotNativeToken();\n    }\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/interfaces/ILayerZeroEndpoint.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\nimport \"./ILayerZeroUserApplicationConfig.sol\";\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n    // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n    // @param _dstChainId - the destination chain identifier\n    // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n    // @param _payload - a custom bytes payload to send to the destination contract\n    // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n    // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n    // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n    function send(\n        uint16 _dstChainId,\n        bytes calldata _destination,\n        bytes calldata _payload,\n        address payable _refundAddress,\n        address _zroPaymentAddress,\n        bytes calldata _adapterParams\n    ) external payable;\n\n    // @notice used by the messaging library to publish verified payload\n    // @param _srcChainId - the source chain identifier\n    // @param _srcAddress - the source contract (as bytes) at the source chain\n    // @param _dstAddress - the address on destination chain\n    // @param _nonce - the unbound message ordering nonce\n    // @param _gasLimit - the gas limit for external contract execution\n    // @param _payload - verified payload to send to the destination contract\n    function receivePayload(\n        uint16 _srcChainId,\n        bytes calldata _srcAddress,\n        address _dstAddress,\n        uint64 _nonce,\n        uint _gasLimit,\n        bytes calldata _payload\n    ) external;\n\n    // @notice get the inboundNonce of a lzApp from a source chain which could be EVM or non-EVM chain\n    // @param _srcChainId - the source chain identifier\n    // @param _srcAddress - the source chain contract address\n    function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n    // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n    // @param _srcAddress - the source chain contract address\n    function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n    // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n    // @param _dstChainId - the destination chain identifier\n    // @param _userApplication - the user app address on this EVM chain\n    // @param _payload - the custom message to send over LayerZero\n    // @param _payInZRO - if false, user app pays the protocol fee in native token\n    // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n    function estimateFees(\n        uint16 _dstChainId,\n        address _userApplication,\n        bytes calldata _payload,\n        bool _payInZRO,\n        bytes calldata _adapterParam\n    ) external view returns (uint nativeFee, uint zroFee);\n\n    // @notice get this Endpoint's immutable source identifier\n    function getChainId() external view returns (uint16);\n\n    // @notice the interface to retry failed message on this Endpoint destination\n    // @param _srcChainId - the source chain identifier\n    // @param _srcAddress - the source chain contract address\n    // @param _payload - the payload to be retried\n    function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n    // @notice query if any STORED payload (message blocking) at the endpoint.\n    // @param _srcChainId - the source chain identifier\n    // @param _srcAddress - the source chain contract address\n    function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n    // @notice query if the _libraryAddress is valid for sending msgs.\n    // @param _userApplication - the user app address on this EVM chain\n    function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n    // @notice query if the _libraryAddress is valid for receiving msgs.\n    // @param _userApplication - the user app address on this EVM chain\n    function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n    // @notice query if the non-reentrancy guard for send() is on\n    // @return true if the guard is on. false otherwise\n    function isSendingPayload() external view returns (bool);\n\n    // @notice query if the non-reentrancy guard for receive() is on\n    // @return true if the guard is on. false otherwise\n    function isReceivingPayload() external view returns (bool);\n\n    // @notice get the configuration of the LayerZero messaging library of the specified version\n    // @param _version - messaging library version\n    // @param _chainId - the chainId for the pending config change\n    // @param _userApplication - the contract address of the user application\n    // @param _configType - type of configuration. every messaging library has its own convention.\n    function getConfig(\n        uint16 _version,\n        uint16 _chainId,\n        address _userApplication,\n        uint _configType\n    ) external view returns (bytes memory);\n\n    // @notice get the send() LayerZero messaging library version\n    // @param _userApplication - the contract address of the user application\n    function getSendVersion(address _userApplication) external view returns (uint16);\n\n    // @notice get the lzReceive() LayerZero messaging library version\n    // @param _userApplication - the contract address of the user application\n    function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n"},{"file_path":"contracts/dependencies/stargate-protocol/Pool.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.9;\npragma abicoder v2;\n\n// imports\nimport \"../openzeppelin/access/Ownable.sol\";\nimport \"../openzeppelin/security/ReentrancyGuard.sol\";\nimport \"./LPTokenERC20.sol\";\nimport \"./interfaces/IStargateFeeLibrary.sol\";\n\n// libraries\nimport \"../openzeppelin/utils/math/SafeMath.sol\";\n\n/// Pool contracts on other chains and managed by the Stargate protocol.\ncontract Pool is LPTokenERC20, ReentrancyGuard {\n    using SafeMath for uint256;\n\n    //---------------------------------------------------------------------------\n    // CONSTANTS\n    bytes4 private constant SELECTOR = bytes4(keccak256(bytes(\"transfer(address,uint256)\")));\n    uint256 public constant BP_DENOMINATOR = 10000;\n\n    //---------------------------------------------------------------------------\n    // STRUCTS\n    struct ChainPath {\n        bool ready; // indicate if the counter chainPath has been created.\n        uint16 dstChainId;\n        uint256 dstPoolId;\n        uint256 weight;\n        uint256 balance;\n        uint256 lkb;\n        uint256 credits;\n        uint256 idealBalance;\n    }\n\n    struct SwapObj {\n        uint256 amount;\n        uint256 eqFee;\n        uint256 eqReward;\n        uint256 lpFee;\n        uint256 protocolFee;\n        uint256 lkbRemove;\n    }\n\n    struct CreditObj {\n        uint256 credits;\n        uint256 idealBalance;\n    }\n\n    //---------------------------------------------------------------------------\n    // VARIABLES\n\n    // chainPath\n    ChainPath[] public chainPaths; // list of connected chains with shared pools\n    mapping(uint16 => mapping(uint256 => uint256)) public chainPathIndexLookup; // lookup for chainPath by chainId => poolId =>index\n\n    // metadata\n    uint256 public immutable poolId; // shared id between chains to represent same pool\n    uint256 public sharedDecimals; // the shared decimals (lowest common decimals between chains)\n    uint256 public localDecimals; // the decimals for the token\n    uint256 public immutable convertRate; // the decimals for the token\n    address public immutable token; // the token for the pool\n    address public immutable router; // the token for the pool\n\n    bool public stopSwap; // flag to stop swapping in extreme cases\n\n    // Fee and Liquidity\n    uint256 public totalLiquidity; // the total amount of tokens added on this side of the chain (fees + deposits - withdrawals)\n    uint256 public totalWeight; // total weight for pool percentages\n    uint256 public mintFeeBP; // fee basis points for the mint/deposit\n    uint256 public protocolFeeBalance; // fee balance created from dao fee\n    uint256 public mintFeeBalance; // fee balance created from mint fee\n    uint256 public eqFeePool; // pool rewards in Shared Decimal format. indicate the total budget for reverse swap incentive\n    address public feeLibrary; // address for retrieving fee params for swaps\n\n    // Delta related\n    uint256 public deltaCredit; // credits accumulated from txn\n    bool public batched; // flag to indicate if we want batch processing.\n    bool public defaultSwapMode; // flag for the default mode for swap\n    bool public defaultLPMode; // flag for the default mode for lp\n    uint256 public swapDeltaBP; // basis points of poolCredits to activate Delta in swap\n    uint256 public lpDeltaBP; // basis points of poolCredits to activate Delta in liquidity events\n\n    //---------------------------------------------------------------------------\n    // EVENTS\n    event Mint(address to, uint256 amountLP, uint256 amountSD, uint256 mintFeeAmountSD);\n    event Burn(address from, uint256 amountLP, uint256 amountSD);\n    event RedeemLocalCallback(address _to, uint256 _amountSD, uint256 _amountToMintSD);\n    event Swap(\n        uint16 chainId,\n        uint256 dstPoolId,\n        address from,\n        uint256 amountSD,\n        uint256 eqReward,\n        uint256 eqFee,\n        uint256 protocolFee,\n        uint256 lpFee\n    );\n    event SendCredits(uint16 dstChainId, uint256 dstPoolId, uint256 credits, uint256 idealBalance);\n    event RedeemRemote(uint16 chainId, uint256 dstPoolId, address from, uint256 amountLP, uint256 amountSD);\n    event RedeemLocal(address from, uint256 amountLP, uint256 amountSD, uint16 chainId, uint256 dstPoolId, bytes to);\n    event InstantRedeemLocal(address from, uint256 amountLP, uint256 amountSD, address to);\n    event CreditChainPath(uint16 chainId, uint256 srcPoolId, uint256 amountSD, uint256 idealBalance);\n    event SwapRemote(address to, uint256 amountSD, uint256 protocolFee, uint256 dstFee);\n    event WithdrawRemote(uint16 srcChainId, uint256 srcPoolId, uint256 swapAmount, uint256 mintAmount);\n    event ChainPathUpdate(uint16 dstChainId, uint256 dstPoolId, uint256 weight);\n    event FeesUpdated(uint256 mintFeeBP);\n    event FeeLibraryUpdated(address feeLibraryAddr);\n    event StopSwapUpdated(bool swapStop);\n    event WithdrawProtocolFeeBalance(address to, uint256 amountSD);\n    event WithdrawMintFeeBalance(address to, uint256 amountSD);\n    event DeltaParamUpdated(\n        bool batched,\n        uint256 swapDeltaBP,\n        uint256 lpDeltaBP,\n        bool defaultSwapMode,\n        bool defaultLPMode\n    );\n\n    //---------------------------------------------------------------------------\n    // MODIFIERS\n    modifier onlyRouter() {\n        require(msg.sender == router, \"Stargate: only the router can call this method\");\n        _;\n    }\n\n    constructor(\n        uint256 _poolId,\n        address _router,\n        address _token,\n        uint256 _sharedDecimals,\n        uint256 _localDecimals,\n        address _feeLibrary,\n        string memory _name,\n        string memory _symbol\n    ) LPTokenERC20(_name, _symbol) {\n        require(_token != address(0x0), \"Stargate: _token cannot be 0x0\");\n        require(_router != address(0x0), \"Stargate: _router cannot be 0x0\");\n        poolId = _poolId;\n        router = _router;\n        token = _token;\n        sharedDecimals = _sharedDecimals;\n        decimals = uint8(_sharedDecimals);\n        localDecimals = _localDecimals;\n        convertRate = 10 ** (uint256(localDecimals).sub(sharedDecimals));\n        totalWeight = 0;\n        feeLibrary = _feeLibrary;\n\n        //delta algo related\n        batched = false;\n        defaultSwapMode = true;\n        defaultLPMode = true;\n    }\n\n    function getChainPathsLength() public view returns (uint256) {\n        return chainPaths.length;\n    }\n\n    //---------------------------------------------------------------------------\n    // LOCAL CHAIN FUNCTIONS\n\n    function mint(address _to, uint256 _amountLD) external nonReentrant onlyRouter returns (uint256) {\n        return _mintLocal(_to, _amountLD, true, true);\n    }\n\n    // Local                                    Remote\n    // -------                                  ---------\n    // swap             ->                      swapRemote\n    function swap(\n        uint16 _dstChainId,\n        uint256 _dstPoolId,\n        address _from,\n        uint256 _amountLD,\n        uint256 _minAmountLD,\n        bool newLiquidity\n    ) external nonReentrant onlyRouter returns (SwapObj memory) {\n        require(!stopSwap, \"Stargate: swap func stopped\");\n        ChainPath storage cp = getAndCheckCP(_dstChainId, _dstPoolId);\n        require(cp.ready == true, \"Stargate: counter chainPath is not ready\");\n\n        uint256 amountSD = amountLDtoSD(_amountLD);\n        uint256 minAmountSD = amountLDtoSD(_minAmountLD);\n\n        // request fee params from library\n        SwapObj memory s = IStargateFeeLibrary(feeLibrary).getFees(poolId, _dstPoolId, _dstChainId, _from, amountSD);\n\n        // equilibrium fee and reward. note eqFee/eqReward are separated from swap liquidity\n        eqFeePool = eqFeePool.sub(s.eqReward);\n        // update the new amount the user gets minus the fees\n        s.amount = amountSD.sub(s.eqFee).sub(s.protocolFee).sub(s.lpFee);\n        // users will also get the eqReward\n        require(s.amount.add(s.eqReward) >= minAmountSD, \"Stargate: slippage too high\");\n\n        // behaviours\n        //     - protocolFee: booked, stayed and withdrawn at remote.\n        //     - eqFee: booked, stayed and withdrawn at remote.\n        //     - lpFee: booked and stayed at remote, can be withdrawn anywhere\n\n        s.lkbRemove = amountSD.sub(s.lpFee).add(s.eqReward);\n        // check for transfer solvency.\n        require(cp.balance >= s.lkbRemove, \"Stargate: dst balance too low\");\n        cp.balance = cp.balance.sub(s.lkbRemove);\n\n        if (newLiquidity) {\n            deltaCredit = deltaCredit.add(amountSD).add(s.eqReward);\n        } else if (s.eqReward > 0) {\n            deltaCredit = deltaCredit.add(s.eqReward);\n        }\n\n        // distribute credits on condition.\n        if (!batched || deltaCredit >= totalLiquidity.mul(swapDeltaBP).div(BP_DENOMINATOR)) {\n            _delta(defaultSwapMode);\n        }\n\n        emit Swap(_dstChainId, _dstPoolId, _from, s.amount, s.eqReward, s.eqFee, s.protocolFee, s.lpFee);\n        return s;\n    }\n\n    // Local                                    Remote\n    // -------                                  ---------\n    // sendCredits      ->                      creditChainPath\n    function sendCredits(\n        uint16 _dstChainId,\n        uint256 _dstPoolId\n    ) external nonReentrant onlyRouter returns (CreditObj memory c) {\n        ChainPath storage cp = getAndCheckCP(_dstChainId, _dstPoolId);\n        require(cp.ready == true, \"Stargate: counter chainPath is not ready\");\n        cp.lkb = cp.lkb.add(cp.credits);\n        c.idealBalance = totalLiquidity.mul(cp.weight).div(totalWeight);\n        c.credits = cp.credits;\n        cp.credits = 0;\n        emit SendCredits(_dstChainId, _dstPoolId, c.credits, c.idealBalance);\n    }\n\n    // Local                                    Remote\n    // -------                                  ---------\n    // redeemRemote   ->                        swapRemote\n    function redeemRemote(\n        uint16 _dstChainId,\n        uint256 _dstPoolId,\n        address _from,\n        uint256 _amountLP\n    ) external nonReentrant onlyRouter {\n        require(_from != address(0x0), \"Stargate: _from cannot be 0x0\");\n        uint256 amountSD = _burnLocal(_from, _amountLP);\n        //run Delta\n        if (!batched || deltaCredit > totalLiquidity.mul(lpDeltaBP).div(BP_DENOMINATOR)) {\n            _delta(defaultLPMode);\n        }\n        uint256 amountLD = amountSDtoLD(amountSD);\n        emit RedeemRemote(_dstChainId, _dstPoolId, _from, _amountLP, amountLD);\n    }\n\n    function instantRedeemLocal(\n        address _from,\n        uint256 _amountLP,\n        address _to\n    ) external nonReentrant onlyRouter returns (uint256 amountSD) {\n        require(_from != address(0x0), \"Stargate: _from cannot be 0x0\");\n        uint256 _deltaCredit = deltaCredit; // sload optimization.\n        uint256 _capAmountLP = _amountSDtoLP(_deltaCredit);\n\n        if (_amountLP > _capAmountLP) _amountLP = _capAmountLP;\n\n        amountSD = _burnLocal(_from, _amountLP);\n        deltaCredit = _deltaCredit.sub(amountSD);\n        uint256 amountLD = amountSDtoLD(amountSD);\n        _safeTransfer(token, _to, amountLD);\n        emit InstantRedeemLocal(_from, _amountLP, amountSD, _to);\n    }\n\n    // Local                                    Remote\n    // -------                                  ---------\n    // redeemLocal   ->                         redeemLocalCheckOnRemote\n    // redeemLocalCallback             <-\n    function redeemLocal(\n        address _from,\n        uint256 _amountLP,\n        uint16 _dstChainId,\n        uint256 _dstPoolId,\n        bytes calldata _to\n    ) external nonReentrant onlyRouter returns (uint256 amountSD) {\n        require(_from != address(0x0), \"Stargate: _from cannot be 0x0\");\n\n        // safeguard.\n        require(\n            chainPaths[chainPathIndexLookup[_dstChainId][_dstPoolId]].ready == true,\n            \"Stargate: counter chainPath is not ready\"\n        );\n        amountSD = _burnLocal(_from, _amountLP);\n\n        // run Delta\n        if (!batched || deltaCredit > totalLiquidity.mul(lpDeltaBP).div(BP_DENOMINATOR)) {\n            _delta(false);\n        }\n        emit RedeemLocal(_from, _amountLP, amountSD, _dstChainId, _dstPoolId, _to);\n    }\n\n    //---------------------------------------------------------------------------\n    // REMOTE CHAIN FUNCTIONS\n\n    // Local                                    Remote\n    // -------                                  ---------\n    // sendCredits      ->                      creditChainPath\n    function creditChainPath(\n        uint16 _dstChainId,\n        uint256 _dstPoolId,\n        CreditObj memory _c\n    ) external nonReentrant onlyRouter {\n        ChainPath storage cp = chainPaths[chainPathIndexLookup[_dstChainId][_dstPoolId]];\n        cp.balance = cp.balance.add(_c.credits);\n        if (cp.idealBalance != _c.idealBalance) {\n            cp.idealBalance = _c.idealBalance;\n        }\n        emit CreditChainPath(_dstChainId, _dstPoolId, _c.credits, _c.idealBalance);\n    }\n\n    // Local                                    Remote\n    // -------                                  ---------\n    // swap             ->                      swapRemote\n    function swapRemote(\n        uint16 _srcChainId,\n        uint256 _srcPoolId,\n        address _to,\n        SwapObj memory _s\n    ) external nonReentrant onlyRouter returns (uint256 amountLD) {\n        // booking lpFee\n        totalLiquidity = totalLiquidity.add(_s.lpFee);\n        // booking eqFee\n        eqFeePool = eqFeePool.add(_s.eqFee);\n        // booking stargateFee\n        protocolFeeBalance = protocolFeeBalance.add(_s.protocolFee);\n\n        // update LKB\n        uint256 chainPathIndex = chainPathIndexLookup[_srcChainId][_srcPoolId];\n        chainPaths[chainPathIndex].lkb = chainPaths[chainPathIndex].lkb.sub(_s.lkbRemove);\n\n        // user receives the amount + the srcReward\n        amountLD = amountSDtoLD(_s.amount.add(_s.eqReward));\n        _safeTransfer(token, _to, amountLD);\n        emit SwapRemote(_to, _s.amount.add(_s.eqReward), _s.protocolFee, _s.eqFee);\n    }\n\n    // Local                                    Remote\n    // -------                                  ---------\n    // redeemLocal   ->                         redeemLocalCheckOnRemote\n    // redeemLocalCallback             <-\n    function redeemLocalCallback(\n        uint16 _srcChainId,\n        uint256 _srcPoolId,\n        address _to,\n        uint256 _amountSD,\n        uint256 _amountToMintSD\n    ) external nonReentrant onlyRouter {\n        if (_amountToMintSD > 0) {\n            _mintLocal(_to, amountSDtoLD(_amountToMintSD), false, false);\n        }\n\n        ChainPath storage cp = getAndCheckCP(_srcChainId, _srcPoolId);\n        cp.lkb = cp.lkb.sub(_amountSD);\n\n        uint256 amountLD = amountSDtoLD(_amountSD);\n        _safeTransfer(token, _to, amountLD);\n        emit RedeemLocalCallback(_to, _amountSD, _amountToMintSD);\n    }\n\n    // Local                                    Remote\n    // -------                                  ---------\n    // redeemLocal(amount)   ->               redeemLocalCheckOnRemote\n    // redeemLocalCallback             <-\n    function redeemLocalCheckOnRemote(\n        uint16 _srcChainId,\n        uint256 _srcPoolId,\n        uint256 _amountSD\n    ) external nonReentrant onlyRouter returns (uint256 swapAmount, uint256 mintAmount) {\n        ChainPath storage cp = getAndCheckCP(_srcChainId, _srcPoolId);\n        if (_amountSD > cp.balance) {\n            mintAmount = _amountSD - cp.balance;\n            swapAmount = cp.balance;\n            cp.balance = 0;\n        } else {\n            cp.balance = cp.balance.sub(_amountSD);\n            swapAmount = _amountSD;\n            mintAmount = 0;\n        }\n        emit WithdrawRemote(_srcChainId, _srcPoolId, swapAmount, mintAmount);\n    }\n\n    //---------------------------------------------------------------------------\n    // DAO Calls\n    function createChainPath(uint16 _dstChainId, uint256 _dstPoolId, uint256 _weight) external onlyRouter {\n        for (uint256 i = 0; i < chainPaths.length; ++i) {\n            ChainPath memory cp = chainPaths[i];\n            bool exists = cp.dstChainId == _dstChainId && cp.dstPoolId == _dstPoolId;\n            require(!exists, \"Stargate: cant createChainPath of existing dstChainId and _dstPoolId\");\n        }\n        totalWeight = totalWeight.add(_weight);\n        chainPathIndexLookup[_dstChainId][_dstPoolId] = chainPaths.length;\n        chainPaths.push(ChainPath(false, _dstChainId, _dstPoolId, _weight, 0, 0, 0, 0));\n        emit ChainPathUpdate(_dstChainId, _dstPoolId, _weight);\n    }\n\n    function setWeightForChainPath(uint16 _dstChainId, uint256 _dstPoolId, uint16 _weight) external onlyRouter {\n        ChainPath storage cp = getAndCheckCP(_dstChainId, _dstPoolId);\n        totalWeight = totalWeight.sub(cp.weight).add(_weight);\n        cp.weight = _weight;\n        emit ChainPathUpdate(_dstChainId, _dstPoolId, _weight);\n    }\n\n    function setFee(uint256 _mintFeeBP) external onlyRouter {\n        require(_mintFeeBP <= BP_DENOMINATOR, \"Bridge: cum fees > 100%\");\n        mintFeeBP = _mintFeeBP;\n        emit FeesUpdated(mintFeeBP);\n    }\n\n    function setFeeLibrary(address _feeLibraryAddr) external onlyRouter {\n        require(_feeLibraryAddr != address(0x0), \"Stargate: fee library cant be 0x0\");\n        feeLibrary = _feeLibraryAddr;\n        emit FeeLibraryUpdated(_feeLibraryAddr);\n    }\n\n    function setSwapStop(bool _swapStop) external onlyRouter {\n        stopSwap = _swapStop;\n        emit StopSwapUpdated(_swapStop);\n    }\n\n    function setDeltaParam(\n        bool _batched,\n        uint256 _swapDeltaBP,\n        uint256 _lpDeltaBP,\n        bool _defaultSwapMode,\n        bool _defaultLPMode\n    ) external onlyRouter {\n        require(_swapDeltaBP <= BP_DENOMINATOR && _lpDeltaBP <= BP_DENOMINATOR, \"Stargate: wrong Delta param\");\n        batched = _batched;\n        swapDeltaBP = _swapDeltaBP;\n        lpDeltaBP = _lpDeltaBP;\n        defaultSwapMode = _defaultSwapMode;\n        defaultLPMode = _defaultLPMode;\n        emit DeltaParamUpdated(_batched, _swapDeltaBP, _lpDeltaBP, _defaultSwapMode, _defaultLPMode);\n    }\n\n    function callDelta(bool _fullMode) external onlyRouter {\n        _delta(_fullMode);\n    }\n\n    function activateChainPath(uint16 _dstChainId, uint256 _dstPoolId) external onlyRouter {\n        ChainPath storage cp = getAndCheckCP(_dstChainId, _dstPoolId);\n        require(cp.ready == false, \"Stargate: chainPath is already active\");\n        // this func will only be called once\n        cp.ready = true;\n    }\n\n    function withdrawProtocolFeeBalance(address _to) external onlyRouter {\n        if (protocolFeeBalance > 0) {\n            uint256 amountOfLD = amountSDtoLD(protocolFeeBalance);\n            protocolFeeBalance = 0;\n            _safeTransfer(token, _to, amountOfLD);\n            emit WithdrawProtocolFeeBalance(_to, amountOfLD);\n        }\n    }\n\n    function withdrawMintFeeBalance(address _to) external onlyRouter {\n        if (mintFeeBalance > 0) {\n            uint256 amountOfLD = amountSDtoLD(mintFeeBalance);\n            mintFeeBalance = 0;\n            _safeTransfer(token, _to, amountOfLD);\n            emit WithdrawMintFeeBalance(_to, amountOfLD);\n        }\n    }\n\n    //---------------------------------------------------------------------------\n    // INTERNAL\n    // Conversion Helpers\n    //---------------------------------------------------------------------------\n    function amountLPtoLD(uint256 _amountLP) external view returns (uint256) {\n        return amountSDtoLD(_amountLPtoSD(_amountLP));\n    }\n\n    function _amountLPtoSD(uint256 _amountLP) internal view returns (uint256) {\n        require(totalSupply > 0, \"Stargate: cant convert LPtoSD when totalSupply == 0\");\n        return _amountLP.mul(totalLiquidity).div(totalSupply);\n    }\n\n    function _amountSDtoLP(uint256 _amountSD) internal view returns (uint256) {\n        require(totalLiquidity > 0, \"Stargate: cant convert SDtoLP when totalLiq == 0\");\n        return _amountSD.mul(totalSupply).div(totalLiquidity);\n    }\n\n    function amountSDtoLD(uint256 _amount) internal view returns (uint256) {\n        return _amount.mul(convertRate);\n    }\n\n    function amountLDtoSD(uint256 _amount) internal view returns (uint256) {\n        return _amount.div(convertRate);\n    }\n\n    function getAndCheckCP(uint16 _dstChainId, uint256 _dstPoolId) internal view returns (ChainPath storage) {\n        require(chainPaths.length > 0, \"Stargate: no chainpaths exist\");\n        ChainPath storage cp = chainPaths[chainPathIndexLookup[_dstChainId][_dstPoolId]];\n        require(cp.dstChainId == _dstChainId && cp.dstPoolId == _dstPoolId, \"Stargate: local chainPath does not exist\");\n        return cp;\n    }\n\n    function getChainPath(uint16 _dstChainId, uint256 _dstPoolId) external view returns (ChainPath memory) {\n        ChainPath memory cp = chainPaths[chainPathIndexLookup[_dstChainId][_dstPoolId]];\n        require(cp.dstChainId == _dstChainId && cp.dstPoolId == _dstPoolId, \"Stargate: local chainPath does not exist\");\n        return cp;\n    }\n\n    function _burnLocal(address _from, uint256 _amountLP) internal returns (uint256) {\n        require(totalSupply > 0, \"Stargate: cant burn when totalSupply == 0\");\n        uint256 amountOfLPTokens = balanceOf[_from];\n        require(amountOfLPTokens >= _amountLP, \"Stargate: not enough LP tokens to burn\");\n\n        uint256 amountSD = _amountLP.mul(totalLiquidity).div(totalSupply);\n        //subtract totalLiquidity accordingly\n        totalLiquidity = totalLiquidity.sub(amountSD);\n\n        _burn(_from, _amountLP);\n        emit Burn(_from, _amountLP, amountSD);\n        return amountSD;\n    }\n\n    function _delta(bool fullMode) internal {\n        if (deltaCredit > 0 && totalWeight > 0) {\n            uint256 cpLength = chainPaths.length;\n            uint256[] memory deficit = new uint256[](cpLength);\n            uint256 totalDeficit = 0;\n\n            // algorithm steps 6-9: calculate the total and the amounts required to get to balance state\n            for (uint256 i = 0; i < cpLength; ++i) {\n                ChainPath storage cp = chainPaths[i];\n                // (liquidity * (weight/totalWeight)) - (lkb+credits)\n                uint256 balLiq = totalLiquidity.mul(cp.weight).div(totalWeight);\n                uint256 currLiq = cp.lkb.add(cp.credits);\n                if (balLiq > currLiq) {\n                    // save gas since we know balLiq > currLiq and we know deficit[i] > 0\n                    deficit[i] = balLiq - currLiq;\n                    totalDeficit = totalDeficit.add(deficit[i]);\n                }\n            }\n\n            // indicates how much delta credit is distributed\n            uint256 spent;\n\n            // handle credits with 2 tranches. the [ < totalDeficit] [excessCredit]\n            // run full Delta, allocate all credits\n            if (totalDeficit == 0) {\n                // only fullMode delta will allocate excess credits\n                if (fullMode && deltaCredit > 0) {\n                    // credit ChainPath by weights\n                    for (uint256 i = 0; i < cpLength; ++i) {\n                        ChainPath storage cp = chainPaths[i];\n                        // credits = credits + toBalanceChange + remaining allocation based on weight\n                        uint256 amtToCredit = deltaCredit.mul(cp.weight).div(totalWeight);\n                        spent = spent.add(amtToCredit);\n                        cp.credits = cp.credits.add(amtToCredit);\n                    }\n                } // else do nth\n            } else if (totalDeficit <= deltaCredit) {\n                if (fullMode) {\n                    // algorithm step 13: calculate amount to disperse to bring to balance state or as close as possible\n                    uint256 excessCredit = deltaCredit - totalDeficit;\n                    // algorithm steps 14-16: calculate credits\n                    for (uint256 i = 0; i < cpLength; ++i) {\n                        if (deficit[i] > 0) {\n                            ChainPath storage cp = chainPaths[i];\n                            // credits = credits + deficit + remaining allocation based on weight\n                            uint256 amtToCredit = deficit[i].add(excessCredit.mul(cp.weight).div(totalWeight));\n                            spent = spent.add(amtToCredit);\n                            cp.credits = cp.credits.add(amtToCredit);\n                        }\n                    }\n                } else {\n                    // totalDeficit <= deltaCredit but not running fullMode\n                    // credit chainPaths as is if any deficit, not using all deltaCredit\n                    for (uint256 i = 0; i < cpLength; ++i) {\n                        if (deficit[i] > 0) {\n                            ChainPath storage cp = chainPaths[i];\n                            uint256 amtToCredit = deficit[i];\n                            spent = spent.add(amtToCredit);\n                            cp.credits = cp.credits.add(amtToCredit);\n                        }\n                    }\n                }\n            } else {\n                // totalDeficit > deltaCredit, fullMode or not, normalize the deficit by deltaCredit\n                for (uint256 i = 0; i < cpLength; ++i) {\n                    if (deficit[i] > 0) {\n                        ChainPath storage cp = chainPaths[i];\n                        uint256 proportionalDeficit = deficit[i].mul(deltaCredit).div(totalDeficit);\n                        spent = spent.add(proportionalDeficit);\n                        cp.credits = cp.credits.add(proportionalDeficit);\n                    }\n                }\n            }\n\n            // deduct the amount of credit sent\n            deltaCredit = deltaCredit.sub(spent);\n        }\n    }\n\n    function _mintLocal(\n        address _to,\n        uint256 _amountLD,\n        bool _feesEnabled,\n        bool _creditDelta\n    ) internal returns (uint256 amountSD) {\n        require(totalWeight > 0, \"Stargate: No ChainPaths exist\");\n        amountSD = amountLDtoSD(_amountLD);\n\n        uint256 mintFeeSD = 0;\n        if (_feesEnabled) {\n            mintFeeSD = amountSD.mul(mintFeeBP).div(BP_DENOMINATOR);\n            amountSD = amountSD.sub(mintFeeSD);\n            mintFeeBalance = mintFeeBalance.add(mintFeeSD);\n        }\n\n        if (_creditDelta) {\n            deltaCredit = deltaCredit.add(amountSD);\n        }\n\n        uint256 amountLPTokens = amountSD;\n        if (totalSupply != 0) {\n            amountLPTokens = amountSD.mul(totalSupply).div(totalLiquidity);\n        }\n        totalLiquidity = totalLiquidity.add(amountSD);\n\n        _mint(_to, amountLPTokens);\n        emit Mint(_to, amountLPTokens, amountSD, mintFeeSD);\n\n        // add to credits and call delta. short circuit to save gas\n        if (!batched || deltaCredit > totalLiquidity.mul(lpDeltaBP).div(BP_DENOMINATOR)) {\n            _delta(defaultLPMode);\n        }\n    }\n\n    function _safeTransfer(address _token, address _to, uint256 _value) private {\n        (bool success, bytes memory data) = _token.call(abi.encodeWithSelector(SELECTOR, _to, _value));\n        require(success && (data.length == 0 || abi.decode(data, (bool))), \"Stargate: TRANSFER_FAILED\");\n    }\n}\n"},{"file_path":"contracts/interfaces/ITreasury.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\ninterface ITreasury {\n    function pull(address to_, uint256 amount_) external;\n\n    function migrateTo(address newTreasury_) external;\n}\n"},{"file_path":"contracts/storage/FeeProviderStorage.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IFeeProvider} from \"../interfaces/IFeeProvider.sol\";\nimport {IPoolRegistry} from \"../interfaces/IPoolRegistry.sol\";\nimport {IESMET} from \"../interfaces/external/IESMET.sol\";\n\nabstract contract FeeProviderStorageV1 is IFeeProvider {\n    struct Tier {\n        uint128 min; // esMET min balance needed to be eligible for `discount`\n        uint128 discount; // discount in percentage to apply. Use 18 decimals (e.g. 1e16 = 1%)\n    }\n\n    /**\n     * @notice The fee discount tiers\n     */\n    Tier[] private tiers__DEPRECATED;\n\n    /**\n     * @notice The default fee charged when swapping synthetic tokens\n     * @dev Use 18 decimals (e.g. 1e16 = 1%)\n     */\n    uint256 private defaultSwapFee__DEPRECATED;\n\n    /**\n     * @notice The fee charged when depositing collateral\n     * @dev Use 18 decimals (e.g. 1e16 = 1%)\n     */\n    uint256 public override depositFee;\n\n    /**\n     * @notice The fee charged when minting a synthetic token\n     * @dev Use 18 decimals (e.g. 1e16 = 1%)\n     */\n    uint256 public override issueFee;\n\n    /**\n     * @notice The fee charged when withdrawing collateral\n     * @dev Use 18 decimals (e.g. 1e16 = 1%)\n     */\n    uint256 public override withdrawFee;\n\n    /**\n     * @notice The fee charged when repaying debt\n     * @dev Use 18 decimals (e.g. 1e16 = 1%)\n     */\n    uint256 public override repayFee;\n\n    /**\n     * @notice The fees charged when liquidating a position\n     * @dev Use 18 decimals (e.g. 1e16 = 1%)\n     */\n    LiquidationFees public override liquidationFees;\n\n    /**\n     * @dev The Pool Registry\n     */\n    IPoolRegistry internal _poolRegistry;\n\n    /**\n     * @notice The esMET contract\n     */\n    IESMET public esMET;\n}\n\nabstract contract FeeProviderStorageV2 is FeeProviderStorageV1 {\n    /**\n     * @notice The fees charged when swapping synthetic tokens (by synthIn => synthOut directions)\n     * @dev Use 18 decimals (e.g. 1e16 = 1%)\n     */\n    mapping(address => mapping(address => uint256)) public override swapFees;\n}\n"},{"file_path":"contracts/Operator.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {TransientSlot} from \"./dependencies/openzeppelin/utils/TransientSlot.sol\";\nimport {Address} from \"./dependencies/openzeppelin/utils/Address.sol\";\nimport {ReentrancyGuardTransient} from \"./utils/ReentrancyGuardTransient.sol\";\nimport {IOperator} from \"./interfaces/IOperator.sol\";\n\n/// @title Operator contract\n/// @dev Allows Synth's users to perform calls from their EOAs\ncontract Operator is IOperator, ReentrancyGuardTransient {\n    using TransientSlot for *;\n    using Address for address;\n\n    // keccak256(abi.encode(uint256(keccak256(\"io.metronome.storage.Operator\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant MSG_SENDER_STORAGE = 0x7981994d60f65f1a18561bb9cc3329c34123a74c00a075d350036a66d0ed9a00;\n\n    /// @notice The sender which the operator is executing on behalf of\n    modifier setMsgSender() {\n        MSG_SENDER_STORAGE.asAddress().tstore(msg.sender);\n        _;\n        MSG_SENDER_STORAGE.asAddress().tstore(address(0));\n    }\n\n    /// @notice Get actual `msg.sender` that is executing the call\n    /// @dev It reverts if read outside of a call context\n    function getActualMsgSender() external view returns (address _actualMsgSender) {\n        _actualMsgSender = MSG_SENDER_STORAGE.asAddress().tload();\n        require(_actualMsgSender != address(0), \"not-authenticated\");\n    }\n\n    /// @notice Execute calls on sender's behalf\n    function execute(\n        Call[] calldata calls_\n    ) external payable override nonReentrant setMsgSender returns (bytes[] memory _returnData) {\n        uint256 _length = calls_.length;\n        _returnData = new bytes[](_length);\n\n        uint256 _sumOfValues;\n        Call calldata _call;\n        for (uint256 i; i < _length; ) {\n            _call = calls_[i];\n            uint256 _value = _call.value;\n            unchecked {\n                _sumOfValues += _value;\n            }\n            _returnData[i] = _call.target.functionCallWithValue(_call.callData, _value);\n            unchecked {\n                ++i;\n            }\n        }\n\n        require(msg.value == _sumOfValues, \"value-mismatch\");\n    }\n}\n"},{"file_path":"contracts/ProxyOFT.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {ContextUpgradeable} from \"./dependencies/openzeppelin-upgradeable/utils/ContextUpgradeable.sol\";\nimport {OwnableUpgradeable} from \"./dependencies/openzeppelin-upgradeable/access/OwnableUpgradeable.sol\";\nimport {IOFTCoreUpgradeable, IComposableOFTCoreUpgradeable, OFTCoreUpgradeable, ComposableOFTCoreUpgradeable} from \"./dependencies/@layerzerolabs/solidity-examples/contracts-upgradeable/token/oft/composable/ComposableOFTCoreUpgradeable.sol\";\nimport {BytesLib} from \"./dependencies/@layerzerolabs/solidity-examples/util/BytesLib.sol\";\nimport {Context, SynthContext} from \"./utils/SynthContext.sol\";\nimport {ProxyOFTStorageV2} from \"./storage/ProxyOFTStorage.sol\";\nimport {IPoolRegistry} from \"./interfaces/IPoolRegistry.sol\";\nimport {ISyntheticToken} from \"./interfaces/ISyntheticToken.sol\";\nimport {WadRayMath} from \"./lib/WadRayMath.sol\";\n\nerror AddressIsNull();\nerror SenderIsNotTheOwner();\nerror BridgingIsPaused();\nerror SendAndCallNotAllowed();\nerror DestinationChainNotAllowed();\nerror InvalidToAddress();\nerror FeeIsGreaterThanTheMax();\nerror NewValueIsSameAsCurrent();\n\n/**\n * @title The ProxyOFT contract\n */\ncontract ProxyOFT is SynthContext, ComposableOFTCoreUpgradeable, ProxyOFTStorageV2 {\n    using BytesLib for bytes;\n    using WadRayMath for uint256;\n\n    string public constant VERSION = \"1.4.1\";\n\n    uint256 internal constant MAX_OFT_FEE = 0.25e18; // 25%\n\n    /// @notice Emitted when OFT fee is updated\n    event OftFeeUpdated(uint256 oldOftFee, uint256 newOftFee);\n\n    constructor() {\n        _disableInitializers();\n    }\n\n    /// @inheritdoc Context\n    function _msgSender() internal view virtual override(ContextUpgradeable, SynthContext) returns (address) {\n        return SynthContext._msgSender();\n    }\n\n    /// @inheritdoc Context\n    function _msgData() internal view virtual override(ContextUpgradeable, Context) returns (bytes calldata) {\n        return Context._msgData();\n    }\n\n    function initialize(address lzEndpoint_, ISyntheticToken syntheticToken_) external initializer {\n        if (address(syntheticToken_) == address(0)) revert AddressIsNull();\n        if (address(lzEndpoint_) == address(0)) revert AddressIsNull();\n\n        syntheticToken = syntheticToken_;\n\n        __ComposableOFTCoreUpgradeable_init(lzEndpoint_);\n    }\n\n    /// @inheritdoc IOFTCoreUpgradeable\n    function circulatingSupply() public view override returns (uint) {\n        return syntheticToken.totalSupply();\n    }\n\n    /**\n     * @notice Get other chains Proxy OFT contracts\n     * @param chainId_ the chain to get contract from\n     */\n    function getProxyOFTOf(uint16 chainId_) public view returns (address _proxyOFT) {\n        return trustedRemoteLookup[chainId_].toAddress(0);\n    }\n\n    /// @inheritdoc IOFTCoreUpgradeable\n    function token() public view override returns (address) {\n        return address(syntheticToken);\n    }\n\n    /// @notice Indicates whether the OFT contract requires approval of the `token()` to send.\n    function approvalRequired() external pure virtual returns (bool) {\n        return false;\n    }\n\n    /// @inheritdoc OFTCoreUpgradeable\n    function _debitFrom(\n        address from_,\n        uint16 dstChainId_,\n        bytes memory toAddress_,\n        uint amount_\n    ) internal override returns (uint256 _sent) {\n        IPoolRegistry _poolRegistry = syntheticToken.poolRegistry();\n        if (_msgSender() != from_) revert SenderIsNotTheOwner();\n        if (!_poolRegistry.isBridgingActive()) revert BridgingIsPaused();\n        if (!_poolRegistry.isDestinationChainSupported(dstChainId_)) revert DestinationChainNotAllowed();\n        // Note: All supported destinations are EVM chains, hence the 20-byte address\n        if (toAddress_.length != 20 || toAddress_.toAddress(0) == address(0)) revert InvalidToAddress();\n\n        uint256 _fee;\n        (_sent, _fee) = quoteSendFromOut(amount_);\n        if (_fee > 0) {\n            syntheticToken.seize(from_, _poolRegistry.feeCollector(), _fee);\n        }\n        syntheticToken.burnFor(from_, _sent);\n    }\n\n    /// @inheritdoc OFTCoreUpgradeable\n    function _creditTo(\n        uint16 /*srcChainId_*/,\n        address toAddress_,\n        uint amount_\n    ) internal override returns (uint256 _received) {\n        syntheticToken.mint(toAddress_, amount_);\n        return amount_;\n    }\n\n    /// @inheritdoc ComposableOFTCoreUpgradeable\n    function sendAndCall(\n        address /*from_*/,\n        uint16 /*dstChainId_*/,\n        bytes calldata /*toAddress_*/,\n        uint /*amount_*/,\n        bytes calldata /*payload_*/,\n        uint64 /*dstGasForCall_*/,\n        address payable /*refundAddress_*/,\n        address /*zroPaymentAddress_*/,\n        bytes calldata /*adapterParams_*/\n    ) public payable override(ComposableOFTCoreUpgradeable, IComposableOFTCoreUpgradeable) {\n        // Note: We do not allow sendAndCall functionality in the ProxyOFT\n        // Replace the revert with `_sendAndCall` call to enable.\n        revert SendAndCallNotAllowed();\n    }\n\n    /**\n     * @notice User friendly `sendFrom()` function\n     */\n    function sendFrom(address from_, uint16 dstChainId_, address to_, uint256 amount_) external payable {\n        _send({\n            _from: from_,\n            _dstChainId: dstChainId_,\n            _toAddress: abi.encodePacked(to_),\n            _amount: amount_,\n            _refundAddress: payable(from_),\n            _zroPaymentAddress: address(0),\n            _adapterParams: abi.encodePacked(\n                uint16(1), // LZ_ADAPTER_PARAMS_VERSION\n                syntheticToken.poolRegistry().lzBaseGasLimit()\n            )\n        });\n    }\n\n    /**\n     * @notice User friendly `sendFrom()` function\n     */\n    function estimateSendFee(\n        uint16 dstChainId_,\n        address to_,\n        uint256 amount_\n    ) external view returns (uint256 _nativeFee) {\n        (_nativeFee, ) = this.estimateSendFee({\n            _dstChainId: dstChainId_,\n            _toAddress: abi.encodePacked(to_),\n            _amount: amount_,\n            _useZro: false,\n            _adapterParams: abi.encodePacked(\n                uint16(1), // LZ_ADAPTER_PARAMS_VERSION\n                syntheticToken.poolRegistry().lzBaseGasLimit()\n            )\n        });\n    }\n\n    /**\n     * @notice Quote `amountIn_` needed to receive `amountOut_` on the destination chain\n     * @param amountOut_ Amount to receive on the destination chain\n     * @return _amountIn Amount to send from the source chain\n     * @return _fee Fee to charge on the source chain\n     */\n    function quoteSendFromIn(uint256 amountOut_) external view override returns (uint256 _amountIn, uint256 _fee) {\n        uint256 _oftFee = oftFee;\n        if (_oftFee == 0) return (amountOut_, 0);\n\n        // Note: Round up to ensure that `quoteSendFromOut(_amountIn) >= amountOut_`\n        uint256 _denominator = 1e18 - _oftFee;\n        _amountIn = (amountOut_ * 1e18 + _denominator - 1) / _denominator;\n        _fee = _amountIn.wadMul(_oftFee);\n    }\n\n    /**\n     * @notice Quote `amountOut_` received on the destination chain when sending `amountIn_`\n     * @param amountIn_ Amount to send from the source chain\n     * @return _amountOut Amount to receive on the destination chain\n     * @return _fee Fee to charge on the source chain\n     */\n    function quoteSendFromOut(uint256 amountIn_) public view override returns (uint256 _amountOut, uint256 _fee) {\n        _fee = amountIn_.wadMul(oftFee);\n        _amountOut = amountIn_ - _fee;\n    }\n\n    /// @notice Get pool registry contract\n    function poolRegistry() public view override returns (IPoolRegistry) {\n        return syntheticToken.poolRegistry();\n    }\n\n    /// @inheritdoc OwnableUpgradeable\n    function owner() public view override returns (address) {\n        return syntheticToken.poolRegistry().governor();\n    }\n\n    /// @inheritdoc OwnableUpgradeable\n    function renounceOwnership() public override {\n        revert(\"disabled\");\n    }\n\n    /// @inheritdoc OwnableUpgradeable\n    function transferOwnership(address) public override {\n        revert(\"disabled\");\n    }\n\n    /**\n     * @notice Update OFT fee\n     * @param newOftFee_ The new fee\n     */\n    function updateOftFee(uint256 newOftFee_) external override onlyOwner {\n        if (newOftFee_ > MAX_OFT_FEE) revert FeeIsGreaterThanTheMax();\n        uint256 _current = oftFee;\n        if (newOftFee_ == _current) revert NewValueIsSameAsCurrent();\n        emit OftFeeUpdated(_current, newOftFee_);\n        oftFee = newOftFee_;\n    }\n}\n"},{"file_path":"contracts/utils/Pauseable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IPauseable} from \"../interfaces/IPauseable.sol\";\nimport {Governable} from \"../access/Governable.sol\";\n\nerror IsPaused();\nerror IsShutdown();\nerror IsNotPaused();\nerror IsNotShutdown();\nerror SenderIsNotAuthorized();\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 */\nabstract contract Pauseable is IPauseable, Governable {\n    /// @notice Emitted when contract is turned on\n    event Open(address indexed caller);\n\n    /// @notice Emitted when contract is paused\n    event Paused(address indexed caller);\n\n    /// @notice Emitted when contract is shuted down\n    event Shutdown(address indexed caller);\n\n    /// @notice Emitted when contract is unpaused\n    event Unpaused(address indexed caller);\n\n    bool private _paused;\n    bool private _everythingStopped;\n\n    modifier canShutdown() {\n        if (_msgSender() != governor && !isGuardian(_msgSender())) revert SenderIsNotAuthorized();\n        _;\n    }\n\n    /**\n     * @dev Throws if contract is paused\n     */\n    modifier whenNotPaused() {\n        if (paused()) revert IsPaused();\n        _;\n    }\n\n    /**\n     * @dev Throws if contract is shutdown\n     */\n    modifier whenNotShutdown() {\n        if (everythingStopped()) revert IsShutdown();\n        _;\n    }\n\n    /**\n     * @dev Throws if contract is not paused\n     */\n    modifier whenPaused() {\n        if (!paused()) revert IsNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Throws if contract is not shutdown\n     */\n    modifier whenShutdown() {\n        if (!everythingStopped()) revert IsNotShutdown();\n        _;\n    }\n\n    /**\n     * @dev If inheriting child is using proxy then child contract can use\n     * __Pauseable_init() function to initialization this contract\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function __Pauseable_init() internal onlyInitializing {\n        __Governable_init();\n    }\n\n    /**\n     * @notice Return `true` if contract is shutdown\n     */\n    function everythingStopped() public view virtual returns (bool) {\n        return _everythingStopped;\n    }\n\n    /**\n     * @notice Return `true` if contract is paused\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Open contract operations, if contract is in shutdown state\n     */\n    function open() external virtual whenShutdown onlyGovernor {\n        _everythingStopped = false;\n        emit Open(_msgSender());\n    }\n\n    /**\n     * @dev Suspend deposit feature, if contract is not paused.\n     */\n    function pause() external virtual whenNotPaused onlyGovernor {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Suspend all features (issue, repay, deposit, withdraw, liquidate and swap), if not already shutdown.\n     */\n    function shutdown() external virtual whenNotShutdown canShutdown {\n        _everythingStopped = true;\n        _paused = true;\n        emit Shutdown(_msgSender());\n    }\n\n    /**\n     * @dev Unpause contract operations, allow only if contract is paused and not shutdown.\n     */\n    function unpause() external virtual whenPaused whenNotShutdown onlyGovernor {\n        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n\n    /**\n     * @dev Check if the sender is an authorized guardian\n     */\n    function isGuardian(address) public view virtual returns (bool);\n}\n"},{"file_path":"contracts/interfaces/external/IStargatePool.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\ninterface IStargatePool {\n    function token() external view returns (address _token);\n}\n"},{"file_path":"contracts/interfaces/external/ISwapper.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\ninterface ISwapper {\n    function swapExactInput(\n        address tokenIn_,\n        address tokenOut_,\n        uint256 amountIn_,\n        uint256 amountOutMin_,\n        address receiver_\n    ) external returns (uint256 _amountOut);\n}\n"},{"file_path":"contracts/AMO.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {Address} from \"./dependencies/openzeppelin/utils/Address.sol\";\nimport {Initializable} from \"./dependencies/openzeppelin-upgradeable/proxy/utils/Initializable.sol\";\nimport {SafeERC20} from \"./dependencies/openzeppelin/token/ERC20/utils/SafeERC20.sol\";\nimport {IERC20} from \"./dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {EnumerableSet} from \"./dependencies/openzeppelin/utils/structs/EnumerableSet.sol\";\nimport {SynthContext} from \"./utils/SynthContext.sol\";\nimport {IPoolRegistry} from \"./interfaces/IPoolRegistry.sol\";\nimport {ISyntheticToken} from \"./interfaces/ISyntheticToken.sol\";\nimport {IVPool} from \"./interfaces/external/IVPool.sol\";\nimport {AMOStorage} from \"./storage/AMOStorage.sol\";\nimport {Math} from \"./dependencies/openzeppelin/utils/math/Math.sol\";\n\n/**\n * @title Automated Market Operator\n * @notice Operator will mint/burn SyntheticToken liquidity and deposit/withdraw to/from Vesper pool as needed.\n */\ncontract AMO is SynthContext, Initializable, AMOStorage {\n    using SafeERC20 for IERC20;\n    using SafeERC20 for ISyntheticToken;\n    using EnumerableSet for EnumerableSet.AddressSet;\n\n    string public constant VERSION = \"1.4.1\";\n\n    event MintAndDeposit(ISyntheticToken indexed syntheticToken, IVPool indexed vPool, uint256 amountDeposited);\n    event WithdrawAndBurn(ISyntheticToken indexed syntheticToken, IVPool indexed vPool, uint256 amountBurnt);\n    event Harvest(ISyntheticToken indexed syntheticToken, IVPool indexed vPool, uint256 profit);\n    event KeeperUpdated(address indexed keeper, string indexed ops);\n    event VesperPoolUpdated(ISyntheticToken indexed syntheticToken, IVPool indexed vPool);\n\n    error AddressIsNull();\n    error CallerIsNotAuthorized();\n    error SyntheticTokenDoesNotMatch();\n    error AmountIsZero();\n    error CallerIsNotGovernor();\n    error VesperPoolIsNotAllowed();\n    error AmountToBurnGreaterThanAmoSupply();\n\n    modifier onlyAuthorized() {\n        address _msgSender = _msgSender();\n        if (!isKeeper(_msgSender) && _msgSender != governor()) revert CallerIsNotAuthorized();\n        _;\n    }\n\n    modifier onlyGovernor() {\n        if (_msgSender() != governor()) revert CallerIsNotGovernor();\n        _;\n    }\n\n    constructor() {\n        _disableInitializers();\n    }\n\n    function initialize(IPoolRegistry poolRegistry_) public initializer {\n        if (address(poolRegistry_) == address(0)) revert AddressIsNull();\n\n        _poolRegistry = poolRegistry_;\n    }\n\n    /**\n     * @notice Only 'authorized' role can call this function.\n     * It will mint `amount_` from `syntheticToken_` token and deposit those into `vPool_`.\n     * @param syntheticToken_ Synthetic Token Address\n     * @param vPool_ Vesper pool address where Synthetic token is defined as collateral.\n     * @param amount_ Amount in Synthetic token\n     */\n    function mintAndDeposit(ISyntheticToken syntheticToken_, IVPool vPool_, uint256 amount_) external onlyAuthorized {\n        if (amount_ == 0) revert AmountIsZero();\n        if (vPools[address(syntheticToken_)] != address(vPool_)) revert VesperPoolIsNotAllowed();\n\n        // 1. Mint Synth here\n        syntheticToken_.mint(address(this), amount_);\n\n        // 2. Deposit minted Synth in Vesper pool\n        syntheticToken_.safeApprove(address(vPool_), 0);\n        syntheticToken_.safeApprove(address(vPool_), amount_);\n        vPool_.deposit(amount_);\n\n        emit MintAndDeposit(syntheticToken_, vPool_, amount_);\n    }\n\n    /**\n     * @notice Only 'authorized' role can call this function.\n     * It will calculate `_shares` from `amount_` and withdraw `_shares` from `vPool_` and\n     * burn amount of Synthetic token withdrawn from Vesper.\n     * @param syntheticToken_ Synthetic Token Address\n     * @param vPool_ Vesper pool address where Synthetic token is defined as collateral.\n     * @param amount_ Amount in Synthetic token\n     */\n    function withdrawAndBurn(ISyntheticToken syntheticToken_, IVPool vPool_, uint256 amount_) external onlyAuthorized {\n        if (amount_ == 0) revert AmountIsZero();\n        if (vPools[address(syntheticToken_)] != address(vPool_)) revert VesperPoolIsNotAllowed();\n\n        // 1. Calculate shares to withdraw\n        uint256 _shares = Math.min((amount_ * 1e18) / vPool_.pricePerShare(), vPool_.balanceOf(address(this)));\n\n        // 2. Withdraw synth from Vesper pool\n        uint256 _amountToBurn = _withdrawFromVesper(syntheticToken_, vPool_, _shares);\n        if (_amountToBurn > syntheticToken_.amoSupply()) revert AmountToBurnGreaterThanAmoSupply();\n\n        // 3. Burn synth withdrawn from Vesper pool\n        syntheticToken_.burn(_amountToBurn);\n\n        emit WithdrawAndBurn(syntheticToken_, vPool_, _amountToBurn);\n    }\n\n    /**\n     * @notice Only 'authorized' role can call this function.\n     * It will calculate profit, withdraw profit from Vesper pool and transfer profit to governor.\n     * @param syntheticToken_ Synthetic token address\n     * @param vPool_ Vesper pool address where Synthetic token is defined as collateral.\n     */\n    function harvest(ISyntheticToken syntheticToken_, IVPool vPool_) external onlyAuthorized {\n        if (vPools[address(syntheticToken_)] != address(vPool_)) revert VesperPoolIsNotAllowed();\n\n        // 1. Calculate profit in Synth\n        uint256 _synthInPool = (vPool_.balanceOf(address(this)) * vPool_.pricePerShare()) / 1e18;\n        uint256 _synthDeposited = syntheticToken_.amoSupply();\n        uint256 _profit = _synthInPool > _synthDeposited ? _synthInPool - _synthDeposited : 0;\n\n        if (_profit > 0) {\n            // 2. Calculate profit in Vesper pool shares\n            uint256 _profitInShare = (_profit * 1e18) / vPool_.pricePerShare();\n\n            // 3. Withdraw profit from Vesper pool\n            uint256 _actualProfit = _withdrawFromVesper(syntheticToken_, vPool_, _profitInShare);\n\n            // 4. Transfer profit to governor\n            syntheticToken_.transfer(governor(), _actualProfit);\n            emit Harvest(syntheticToken_, vPool_, _actualProfit);\n        }\n    }\n\n    function _withdrawFromVesper(\n        ISyntheticToken syntheticToken_,\n        IVPool vPool_,\n        uint256 shares_\n    ) private returns (uint256) {\n        // Vesper pool may withdraw less, of course burn less shares too, than requested.\n        // Hence the difference of Synth balance after withdraw and before withdraw is actual Synth withdrawn.\n        uint256 _before = syntheticToken_.balanceOf(address(this));\n        vPool_.withdraw(shares_);\n        return syntheticToken_.balanceOf(address(this)) - _before;\n    }\n\n    /// @inheritdoc SynthContext\n    function poolRegistry() public view override returns (IPoolRegistry) {\n        return _poolRegistry;\n    }\n\n    /**\n     * @notice Governor of this contract is same as PoolRegistry governor.\n     * Governor can perform all authorized actions.\n     */\n    function governor() public view returns (address) {\n        return _poolRegistry.governor();\n    }\n\n    /**\n     * @notice List of keepers. Keeper can perform all authorized actions.\n     */\n    function getKeepers() external view returns (address[] memory) {\n        return keepers.values();\n    }\n\n    /**\n     * @notice Returns whether given address is keeper or not.\n     * @param user_ User address to check\n     */\n    function isKeeper(address user_) public view returns (bool) {\n        return keepers.contains(user_);\n    }\n\n    /**\n     * @notice ERC20 recovery in case of stuck tokens due direct transfers to the contract address.\n     * @param token_ The token to transfer\n     * @param amount_ The amount to send\n     */\n    function sweep(IERC20 token_, uint256 amount_) external onlyGovernor {\n        if (amount_ == 0) revert AmountIsZero();\n\n        if (address(token_) == address(0)) {\n            Address.sendValue(payable(governor()), amount_);\n        } else {\n            token_.safeTransfer(governor(), amount_);\n        }\n    }\n\n    /**\n     * @notice Only 'governor' role can call this function.\n     * This function will remove keeper_ if already exist in list else add in list.\n     * @param keeper_ Keeper address to add/remove.\n     */\n    function updateKeeper(address keeper_) external onlyGovernor {\n        if (keepers.contains(keeper_)) {\n            keepers.remove(keeper_);\n            emit KeeperUpdated(keeper_, \"remove\");\n        } else {\n            keepers.add(keeper_);\n            emit KeeperUpdated(keeper_, \"add\");\n        }\n    }\n\n    /**\n     * @notice Only 'governor' role can call this function.\n     * This function will set a `vPool_` allowed to receive funds for a given synthetic asset\n     * @param syntheticToken_ The Synthetic token\n     * @param vPool_ The Vesper Pool allowed\n     */\n    function updateVesperPool(ISyntheticToken syntheticToken_, IVPool vPool_) external onlyGovernor {\n        if (address(vPool_) != address(0) && vPool_.token() != address(syntheticToken_))\n            revert SyntheticTokenDoesNotMatch();\n\n        vPools[address(syntheticToken_)] = address(vPool_);\n\n        emit VesperPoolUpdated(syntheticToken_, vPool_);\n    }\n}\n"},{"file_path":"contracts/Pool.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {Initializable} from \"./dependencies/openzeppelin-upgradeable/proxy/utils/Initializable.sol\";\nimport {SafeERC20} from \"./dependencies/openzeppelin/token/ERC20/utils/SafeERC20.sol\";\nimport {IERC20} from \"./dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {EnumerableSet} from \"./dependencies/openzeppelin/utils/structs/EnumerableSet.sol\";\nimport {Context, SynthContext} from \"./utils/SynthContext.sol\";\nimport {Pauseable} from \"./utils/Pauseable.sol\";\nimport {ReentrancyGuardDeprecated} from \"./utils/ReentrancyGuardDeprecated.sol\";\nimport {ReentrancyGuardTransient} from \"./utils/ReentrancyGuardTransient.sol\";\nimport {MappedEnumerableSet} from \"./lib/MappedEnumerableSet.sol\";\nimport {WadRayMath} from \"./lib/WadRayMath.sol\";\nimport {IMasterOracle} from \"./interfaces/external/IMasterOracle.sol\";\nimport {ISyntheticToken} from \"./interfaces/ISyntheticToken.sol\";\nimport {IPool} from \"./interfaces/IPool.sol\";\nimport {ISmartFarmingManager} from \"./interfaces/ISmartFarmingManager.sol\";\nimport {IPoolRegistry} from \"./interfaces/IPoolRegistry.sol\";\nimport {ITreasury} from \"./interfaces/ITreasury.sol\";\nimport {IDepositToken} from \"./interfaces/IDepositToken.sol\";\nimport {IRewardsDistributor} from \"./interfaces/IRewardsDistributor.sol\";\nimport {IDebtToken} from \"./interfaces/IDebtToken.sol\";\nimport {IFeeProvider} from \"./interfaces/IFeeProvider.sol\";\nimport {IPauseable} from \"./interfaces/IPauseable.sol\";\nimport {IManageable} from \"./interfaces/IManageable.sol\";\nimport {PoolStorageV4} from \"./storage/PoolStorage.sol\";\n\nerror SyntheticDoesNotExist();\nerror SenderIsNotDebtToken();\nerror SenderIsNotDepositToken();\nerror UserReachedMaxTokens();\nerror PoolRegistryIsNull();\nerror DebtTokenAlreadyExists();\nerror DepositTokenAlreadyExists();\nerror AmountIsZero();\nerror CanNotLiquidateOwnPosition();\nerror PositionIsHealthy();\nerror AmountGreaterThanMaxLiquidable();\nerror RemainingDebtIsLowerThanTheFloor();\nerror AmountIsTooHigh();\nerror DebtTokenDoesNotExist();\nerror DepositTokenDoesNotExist();\nerror SwapFeatureIsInactive();\nerror AmountInIsInvalid();\nerror AddressIsNull();\nerror SyntheticIsNull();\nerror SyntheticIsInUse();\nerror UnderlyingAssetInUse();\nerror ReachedMaxDepositTokens();\nerror RewardDistributorAlreadyExists();\nerror RewardDistributorDoesNotExist();\nerror TotalSupplyIsNotZero();\nerror NewValueIsSameAsCurrent();\nerror MaxLiquidableTooHigh();\nerror CollateralFactorTooHigh();\nerror InvalidDepositToken();\n\n/**\n * @title Pool contract\n */\ncontract Pool is\n    SynthContext,\n    Initializable,\n    ReentrancyGuardDeprecated,\n    ReentrancyGuardTransient,\n    Pauseable,\n    PoolStorageV4\n{\n    using SafeERC20 for IERC20;\n    using SafeERC20 for ISyntheticToken;\n    using WadRayMath for uint256;\n    using EnumerableSet for EnumerableSet.AddressSet;\n    using MappedEnumerableSet for MappedEnumerableSet.AddressSet;\n\n    string public constant VERSION = \"1.4.1\";\n\n    /**\n     * @notice Maximum tokens per pool a user may have\n     */\n    uint256 public constant MAX_TOKENS_PER_USER = 30;\n\n    // Note: Upper bound on `collateralFactor * (1 + liquidationFees)`. The `< 1e36` form only\n    // guarantees liquidation *eventually* helps; at exactly 1e36 it closes 0 wei of the health\n    // gap. This leaves a margin so every liquidation closes >= 2% of the amount repaid.\n    uint256 internal constant MAX_CF_TIMES_LIQUIDATION_FEES = 0.98e36;\n\n    /// @notice Emitted when protocol liquidation fee is updated\n    event DebtFloorUpdated(uint256 oldDebtFloorInUsd, uint256 newDebtFloorInUsd);\n\n    /// @notice Emitted when debt token is enabled\n    event DebtTokenAdded(IDebtToken indexed debtToken);\n\n    /// @notice Emitted when debt token is disabled\n    event DebtTokenRemoved(IDebtToken indexed debtToken);\n\n    /// @notice Emitted when deposit token is enabled\n    event DepositTokenAdded(address indexed depositToken);\n\n    /// @notice Emitted when deposit token is disabled\n    event DepositTokenRemoved(IDepositToken indexed depositToken);\n\n    /// @notice Emitted when fee provider contract is updated\n    event FeeProviderUpdated(IFeeProvider indexed oldFeeProvider, IFeeProvider indexed newFeeProvider);\n\n    /// @notice Emitted when maxLiquidable (liquidation cap) is updated\n    event MaxLiquidableUpdated(uint256 oldMaxLiquidable, uint256 newMaxLiquidable);\n\n    /// @notice Emitted when a position is liquidated\n    event PositionLiquidated(\n        address indexed liquidator,\n        address indexed account,\n        ISyntheticToken indexed syntheticToken,\n        uint256 amountRepaid,\n        uint256 depositSeized,\n        uint256 fee\n    );\n\n    /// @notice Emitted when rewards distributor contract is added\n    event RewardsDistributorAdded(IRewardsDistributor indexed _distributor);\n\n    /// @notice Emitted when rewards distributor contract is removed\n    event RewardsDistributorRemoved(IRewardsDistributor _distributor);\n\n    /// @notice Emitted when SmartFarmingManager contract is updated\n    event SmartFarmingManagerUpdated(\n        ISmartFarmingManager oldSmartFarmingManager,\n        ISmartFarmingManager newSmartFarmingManager\n    );\n\n    /// @notice Emitted when the swap active flag is updated\n    event SwapActiveUpdated(bool newActive);\n\n    /// @notice Emitted when synthetic token is swapped\n    event SyntheticTokenSwapped(\n        address indexed account,\n        ISyntheticToken indexed syntheticTokenIn,\n        ISyntheticToken indexed syntheticTokenOut,\n        uint256 amountIn,\n        uint256 amountOut,\n        uint256 fee\n    );\n\n    /// @notice Emitted when treasury contract is updated\n    event TreasuryUpdated(ITreasury indexed oldTreasury, ITreasury indexed newTreasury);\n\n    /**\n     * @dev Throws if token addition will reach the `account_`'s max\n     */\n    modifier onlyIfAdditionWillNotReachMaxTokens(address account_) {\n        if (debtTokensOfAccount.length(account_) + depositTokensOfAccount.length(account_) >= MAX_TOKENS_PER_USER) {\n            revert UserReachedMaxTokens();\n        }\n        _;\n    }\n\n    /**\n     * @dev Throws if deposit token doesn't exist\n     */\n    modifier onlyIfDepositTokenExists(IDepositToken depositToken_) {\n        if (!doesDepositTokenExist(depositToken_)) revert DepositTokenDoesNotExist();\n        _;\n    }\n\n    /**\n     * @dev Throws if synthetic token doesn't exist\n     */\n    modifier onlyIfSyntheticTokenExists(ISyntheticToken syntheticToken_) {\n        if (!doesSyntheticTokenExist(syntheticToken_)) revert SyntheticDoesNotExist();\n        _;\n    }\n\n    constructor() {\n        _disableInitializers();\n    }\n\n    /// @inheritdoc Context\n    function _msgSender() internal view virtual override(Context, SynthContext) returns (address) {\n        return SynthContext._msgSender();\n    }\n\n    function initialize(IPoolRegistry poolRegistry_) public initializer {\n        if (address(poolRegistry_) == address(0)) revert PoolRegistryIsNull();\n        __Pauseable_init();\n\n        _poolRegistry = poolRegistry_;\n        isSwapActive = true;\n        maxLiquidable = 0.5e18; // 50%\n    }\n\n    /**\n     * @dev Returns the sum of the liquidator incentive and protocol fee of a fee provider\n     */\n    function _liquidationFees(IFeeProvider feeProvider_) private view returns (uint256) {\n        (uint128 _liquidatorIncentive, uint128 _protocolFee) = feeProvider_.liquidationFees();\n        return uint256(_liquidatorIncentive) + _protocolFee;\n    }\n\n    /**\n     * @dev Throws if `_msgSender()` isn't a debt token\n     */\n    function _revertIfSenderIsNotDebtToken(address sender_) private view {\n        if (!doesDebtTokenExist(IDebtToken(sender_))) revert SenderIsNotDebtToken();\n    }\n\n    /**\n     * @dev Throws if `_msgSender()` isn't a deposit token\n     */\n    function _revertIfSenderIsNotDepositToken(address sender_) private view {\n        if (!doesDepositTokenExist(IDepositToken(sender_))) revert SenderIsNotDepositToken();\n    }\n\n    /**\n     * @notice Add a debt token to the per-account list\n     * @dev This function is called from `DebtToken` when user's balance changes from `0`\n     * @dev The caller should ensure to not pass `address(0)` as `_account`\n     * @param account_ The account address\n     */\n    function addToDebtTokensOfAccount(address account_) external onlyIfAdditionWillNotReachMaxTokens(account_) {\n        address _debtToken = _msgSender();\n        _revertIfSenderIsNotDebtToken(_debtToken);\n        if (!debtTokensOfAccount.add(account_, _debtToken)) revert DebtTokenAlreadyExists();\n    }\n\n    /**\n     * @notice Add a deposit token to the per-account list\n     * @dev This function is called from `DepositToken` when user's balance changes from `0`\n     * @dev The caller should ensure to not pass `address(0)` as `_account`\n     * @param account_ The account address\n     */\n    function addToDepositTokensOfAccount(address account_) external onlyIfAdditionWillNotReachMaxTokens(account_) {\n        address _depositToken = _msgSender();\n        _revertIfSenderIsNotDepositToken(_depositToken);\n        if (!depositTokensOfAccount.add(account_, _depositToken)) revert DepositTokenAlreadyExists();\n    }\n\n    /**\n     * @notice Get account's debt by querying latest prices from oracles\n     * @param account_ The account to check\n     * @return _debtInUsd The debt value in USD\n     */\n    function debtOf(address account_) public view override returns (uint256 _debtInUsd) {\n        IMasterOracle _masterOracle = masterOracle();\n        uint256 _length = debtTokensOfAccount.length(account_);\n        for (uint256 i; i < _length; ++i) {\n            IDebtToken _debtToken = IDebtToken(debtTokensOfAccount.at(account_, i));\n            _debtInUsd += _masterOracle.quoteTokenToUsd(\n                address(_debtToken.syntheticToken()),\n                _debtToken.balanceOf(account_)\n            );\n        }\n    }\n\n    /**\n     * @notice Returns whether the debt position from an account is healthy\n     * @param account_ The account to check\n     * @return _isHealthy Whether the account's position is healthy\n     * @return _depositInUsd The total collateral deposited in USD\n     * @return _debtInUsd The total debt in USD\n     * @return _issuableLimitInUsd The max amount of debt (is USD) that can be created (considering collateral factors)\n     * @return _issuableInUsd The amount of debt (is USD) that is free (i.e. can be used to issue synthetic tokens)\n     */\n    function debtPositionOf(\n        address account_\n    )\n        public\n        view\n        override\n        returns (\n            bool _isHealthy,\n            uint256 _depositInUsd,\n            uint256 _debtInUsd,\n            uint256 _issuableLimitInUsd,\n            uint256 _issuableInUsd\n        )\n    {\n        _debtInUsd = debtOf(account_);\n        (_depositInUsd, _issuableLimitInUsd) = depositOf(account_);\n        _isHealthy = _debtInUsd <= _issuableLimitInUsd;\n        _issuableInUsd = _debtInUsd < _issuableLimitInUsd ? _issuableLimitInUsd - _debtInUsd : 0;\n    }\n\n    /**\n     * @notice Get account's total collateral deposited by querying latest prices from oracles\n     * @param account_ The account to check\n     * @return _depositInUsd The total deposit value in USD among all collaterals\n     * @return _issuableLimitInUsd The max value in USD that can be used to issue synthetic tokens\n     */\n    function depositOf(\n        address account_\n    ) public view override returns (uint256 _depositInUsd, uint256 _issuableLimitInUsd) {\n        IMasterOracle _masterOracle = masterOracle();\n        uint256 _length = depositTokensOfAccount.length(account_);\n        for (uint256 i; i < _length; ++i) {\n            IDepositToken _depositToken = IDepositToken(depositTokensOfAccount.at(account_, i));\n            uint256 _amountInUsd = _masterOracle.quoteTokenToUsd(\n                address(_depositToken.underlying()),\n                _depositToken.balanceOf(account_)\n            );\n            _depositInUsd += _amountInUsd;\n            _issuableLimitInUsd += _amountInUsd.wadMul(_depositToken.collateralFactor());\n        }\n    }\n\n    /**\n     * @inheritdoc Pauseable\n     */\n    function everythingStopped() public view override(IPauseable, Pauseable) returns (bool) {\n        return super.everythingStopped() || _poolRegistry.everythingStopped();\n    }\n\n    /**\n     * @notice Returns fee collector address\n     */\n    function feeCollector() external view override returns (address) {\n        return _poolRegistry.feeCollector();\n    }\n\n    /**\n     * @notice Get all debt tokens\n     * @dev WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees.\n     */\n    function getDebtTokens() external view override returns (address[] memory) {\n        return debtTokens.values();\n    }\n\n    /**\n     * @notice Get all debt tokens\n     * @dev WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees.\n     */\n    function getDebtTokensOfAccount(address account_) external view override returns (address[] memory) {\n        return debtTokensOfAccount.values(account_);\n    }\n\n    /**\n     * @notice Get all deposit tokens\n     * @dev WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees.\n     */\n    function getDepositTokens() external view override returns (address[] memory) {\n        return depositTokens.values();\n    }\n\n    /**\n     * @notice Get deposit tokens of an account\n     * @dev WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees.\n     */\n    function getDepositTokensOfAccount(address account_) external view override returns (address[] memory) {\n        return depositTokensOfAccount.values(account_);\n    }\n\n    /**\n     * @notice Get all rewards distributors\n     */\n    function getRewardsDistributors() external view override returns (address[] memory) {\n        return rewardsDistributors.values();\n    }\n\n    /**\n     * @notice Check if token is part of the debt offerings\n     * @param debtToken_ Asset to check\n     * @return true if exist\n     */\n    function doesDebtTokenExist(IDebtToken debtToken_) public view override returns (bool) {\n        return debtTokens.contains(address(debtToken_));\n    }\n\n    /**\n     * @notice Check if collateral is supported\n     * @param depositToken_ Asset to check\n     * @return true if exist\n     */\n    function doesDepositTokenExist(IDepositToken depositToken_) public view override returns (bool) {\n        return depositTokens.contains(address(depositToken_));\n    }\n\n    /**\n     * @notice Check if token is part of the synthetic offerings\n     * @param syntheticToken_ Asset to check\n     * @return true if exist\n     */\n    function doesSyntheticTokenExist(ISyntheticToken syntheticToken_) public view override returns (bool) {\n        return address(debtTokenOf[syntheticToken_]) != address(0);\n    }\n\n    /**\n     * @notice Quote synth  `_amountToRepay` in order to seize `totalToSeized_`\n     * @param syntheticToken_ Synth for repayment\n     * @param totalToSeize_ Collateral total amount to size\n     * @param depositToken_ Collateral's deposit token\n     * @return _amountToRepay Synth amount to burn\n     * @return _toLiquidator Seized amount to the liquidator\n     * @return _fee The fee amount to collect\n     */\n    function quoteLiquidateIn(\n        ISyntheticToken syntheticToken_,\n        uint256 totalToSeize_,\n        IDepositToken depositToken_\n    ) public view override returns (uint256 _amountToRepay, uint256 _toLiquidator, uint256 _fee) {\n        (uint128 _liquidatorIncentive, uint128 _protocolFee) = feeProvider.liquidationFees();\n        uint256 _totalFees = _protocolFee + _liquidatorIncentive;\n        uint256 _repayAmountInCollateral = totalToSeize_;\n\n        if (_totalFees > 0) {\n            _repayAmountInCollateral = _repayAmountInCollateral.wadDiv(1e18 + _totalFees);\n        }\n\n        _amountToRepay = masterOracle().quote(\n            address(depositToken_.underlying()),\n            address(syntheticToken_),\n            _repayAmountInCollateral\n        );\n\n        if (_protocolFee > 0) {\n            _fee = _repayAmountInCollateral.wadMul(_protocolFee);\n        }\n\n        if (_liquidatorIncentive > 0) {\n            _toLiquidator = _repayAmountInCollateral.wadMul(1e18 + _liquidatorIncentive);\n        }\n    }\n\n    /**\n     * @notice Quote max allowed synth to repay\n     * @dev I.e. Considers the min amount between collateral's balance and `maxLiquidable` param\n     * @param syntheticToken_ Synth for repayment\n     * @param account_ The account to liquidate\n     * @param depositToken_ Collateral's deposit token\n     * @return _maxAmountToRepay Synth amount to burn\n     */\n    function quoteLiquidateMax(\n        ISyntheticToken syntheticToken_,\n        address account_,\n        IDepositToken depositToken_\n    ) external view override returns (uint256 _maxAmountToRepay) {\n        (bool _isHealthy, , , , ) = debtPositionOf(account_);\n        if (_isHealthy) {\n            return 0;\n        }\n\n        (uint256 _amountToRepay, , ) = quoteLiquidateIn(\n            syntheticToken_,\n            depositToken_.balanceOf(account_),\n            depositToken_\n        );\n\n        _maxAmountToRepay = debtTokenOf[syntheticToken_].balanceOf(account_).wadMul(maxLiquidable);\n\n        if (_amountToRepay < _maxAmountToRepay) {\n            _maxAmountToRepay = _amountToRepay;\n        }\n    }\n\n    /**\n     * @notice Quote collateral  `totalToSeized_` by repaying `amountToRepay_`\n     * @param syntheticToken_ Synth for repayment\n     * @param amountToRepay_ Synth amount to burn\n     * @param depositToken_ Collateral's deposit token\n     * @return _totalToSeize Collateral total amount to size\n     * @return _toLiquidator Seized amount to the liquidator\n     * @return _fee The fee amount to collect\n     */\n    function quoteLiquidateOut(\n        ISyntheticToken syntheticToken_,\n        uint256 amountToRepay_,\n        IDepositToken depositToken_\n    ) public view override returns (uint256 _totalToSeize, uint256 _toLiquidator, uint256 _fee) {\n        _toLiquidator = masterOracle().quote(\n            address(syntheticToken_),\n            address(depositToken_.underlying()),\n            amountToRepay_\n        );\n\n        (uint128 _liquidatorIncentive, uint128 _protocolFee) = feeProvider.liquidationFees();\n\n        if (_protocolFee > 0) {\n            _fee = _toLiquidator.wadMul(_protocolFee);\n        }\n        if (_liquidatorIncentive > 0) {\n            _toLiquidator += _toLiquidator.wadMul(_liquidatorIncentive);\n        }\n\n        _totalToSeize = _fee + _toLiquidator;\n    }\n\n    /**\n     * @notice Quote `_amountIn` to get `amountOut_`\n     * @param syntheticTokenIn_ Synth in\n     * @param syntheticTokenOut_ Synth out\n     * @param amountOut_ Amount out\n     * @return _amountIn Amount in\n     * @return _fee Fee to charge in `syntheticTokenOut_`\n     */\n    function quoteSwapIn(\n        ISyntheticToken syntheticTokenIn_,\n        ISyntheticToken syntheticTokenOut_,\n        uint256 amountOut_\n    ) external view override returns (uint256 _amountIn, uint256 _fee) {\n        uint256 _swapFee = feeProvider.swapFees(address(syntheticTokenIn_), address(syntheticTokenOut_));\n        if (_swapFee > 0) {\n            amountOut_ = amountOut_.wadDiv(1e18 - _swapFee);\n            _fee = amountOut_.wadMul(_swapFee);\n        }\n\n        _amountIn = _poolRegistry.masterOracle().quote(\n            address(syntheticTokenOut_),\n            address(syntheticTokenIn_),\n            amountOut_\n        );\n    }\n\n    /**\n     * @notice Quote `amountOut_` get from `amountIn_`\n     * @param syntheticTokenIn_ Synth in\n     * @param syntheticTokenOut_ Synth out\n     * @param amountIn_ Amount in\n     * @return _amountOut Amount out\n     * @return _fee Fee to charge in `syntheticTokenOut_`\n     */\n    function quoteSwapOut(\n        ISyntheticToken syntheticTokenIn_,\n        ISyntheticToken syntheticTokenOut_,\n        uint256 amountIn_\n    ) public view override returns (uint256 _amountOut, uint256 _fee) {\n        _amountOut = _poolRegistry.masterOracle().quote(\n            address(syntheticTokenIn_),\n            address(syntheticTokenOut_),\n            amountIn_\n        );\n\n        uint256 _swapFee = feeProvider.swapFees(address(syntheticTokenIn_), address(syntheticTokenOut_));\n\n        if (_swapFee > 0) {\n            _fee = _amountOut.wadMul(_swapFee);\n            _amountOut -= _fee;\n        }\n    }\n\n    /**\n     * @notice Burn synthetic token, unlock deposit token and send liquidator incentive\n     * @param syntheticToken_ The msAsset to use for repayment\n     * @param account_ The account with an unhealthy position\n     * @param amountToRepay_ The amount to repay in synthetic token\n     * @param depositToken_ The collateral to seize from\n     * @return _totalSeized Total deposit amount seized from the liquidated account\n     * @return _toLiquidator Share of `_totalSeized` sent to the liquidator\n     * @return _fee Share of `_totalSeized` collected as fee\n     */\n    function liquidate(\n        ISyntheticToken syntheticToken_,\n        address account_,\n        uint256 amountToRepay_,\n        IDepositToken depositToken_\n    )\n        external\n        override\n        whenNotShutdown\n        nonReentrant\n        onlyIfSyntheticTokenExists(syntheticToken_)\n        onlyIfDepositTokenExists(depositToken_)\n        returns (uint256 _totalSeized, uint256 _toLiquidator, uint256 _fee)\n    {\n        address _msgSender = _msgSender();\n\n        if (amountToRepay_ == 0) revert AmountIsZero();\n        if (_msgSender == account_) revert CanNotLiquidateOwnPosition();\n\n        IDebtToken _debtToken = debtTokenOf[syntheticToken_];\n        _debtToken.accrueInterest();\n\n        (bool _isHealthy, , , , ) = debtPositionOf(account_);\n\n        if (_isHealthy) {\n            revert PositionIsHealthy();\n        }\n\n        uint256 _debtTokenBalance = _debtToken.balanceOf(account_);\n\n        if (amountToRepay_.wadDiv(_debtTokenBalance) > maxLiquidable) {\n            revert AmountGreaterThanMaxLiquidable();\n        }\n\n        if (debtFloorInUsd > 0) {\n            uint256 _newDebtInUsd = masterOracle().quoteTokenToUsd(\n                address(syntheticToken_),\n                _debtTokenBalance - amountToRepay_\n            );\n            if (_newDebtInUsd > 0 && _newDebtInUsd < debtFloorInUsd) {\n                revert RemainingDebtIsLowerThanTheFloor();\n            }\n        }\n\n        (_totalSeized, _toLiquidator, _fee) = quoteLiquidateOut(syntheticToken_, amountToRepay_, depositToken_);\n\n        if (_totalSeized > depositToken_.balanceOf(account_)) {\n            revert AmountIsTooHigh();\n        }\n\n        syntheticToken_.burnFor(_msgSender, amountToRepay_);\n        _debtToken.burnFor(account_, amountToRepay_);\n        depositToken_.seize(account_, _msgSender, _toLiquidator);\n\n        if (_fee > 0) {\n            depositToken_.seize(account_, _poolRegistry.feeCollector(), _fee);\n        }\n\n        emit PositionLiquidated(_msgSender, account_, syntheticToken_, amountToRepay_, _totalSeized, _fee);\n    }\n\n    /**\n     * @notice Get MasterOracle contract\n     */\n    function masterOracle() public view override returns (IMasterOracle) {\n        return _poolRegistry.masterOracle();\n    }\n\n    /**\n     * @inheritdoc Pauseable\n     */\n    function paused() public view override(IPauseable, Pauseable) returns (bool) {\n        return super.paused() || _poolRegistry.paused();\n    }\n\n    /**\n     * @notice Remove a debt token from the per-account list\n     * @dev This function is called from `DebtToken` when user's balance changes to `0`\n     * @dev The caller should ensure to not pass `address(0)` as `_account`\n     * @param account_ The account address\n     */\n    function removeFromDebtTokensOfAccount(address account_) external {\n        address _debtToken = _msgSender();\n        _revertIfSenderIsNotDebtToken(_debtToken);\n        if (!debtTokensOfAccount.remove(account_, _debtToken)) revert DebtTokenDoesNotExist();\n    }\n\n    /**\n     * @notice Remove a deposit token from the per-account list\n     * @dev This function is called from `DepositToken` when user's balance changes to `0`\n     * @dev The caller should ensure to not pass `address(0)` as `_account`\n     * @param account_ The account address\n     */\n    function removeFromDepositTokensOfAccount(address account_) external {\n        address _depositToken = _msgSender();\n        _revertIfSenderIsNotDepositToken(_depositToken);\n        if (!depositTokensOfAccount.remove(account_, _depositToken)) revert DepositTokenDoesNotExist();\n    }\n\n    /**\n     * @notice Swap synthetic tokens\n     * @param syntheticTokenIn_ Synthetic token to sell\n     * @param syntheticTokenOut_ Synthetic token to buy\n     * @param amountIn_ Amount to swap\n     */\n    function swap(\n        ISyntheticToken syntheticTokenIn_,\n        ISyntheticToken syntheticTokenOut_,\n        uint256 amountIn_\n    )\n        external\n        override\n        whenNotShutdown\n        nonReentrant\n        onlyIfSyntheticTokenExists(syntheticTokenIn_)\n        onlyIfSyntheticTokenExists(syntheticTokenOut_)\n        returns (uint256 _amountOut, uint256 _fee)\n    {\n        address _msgSender = _msgSender();\n\n        if (!isSwapActive) revert SwapFeatureIsInactive();\n        if (amountIn_ == 0 || amountIn_ > syntheticTokenIn_.balanceOf(_msgSender)) revert AmountInIsInvalid();\n\n        syntheticTokenIn_.burnFor(_msgSender, amountIn_);\n\n        (_amountOut, _fee) = quoteSwapOut(syntheticTokenIn_, syntheticTokenOut_, amountIn_);\n\n        if (_fee > 0) {\n            syntheticTokenOut_.mint(_poolRegistry.feeCollector(), _fee);\n        }\n\n        syntheticTokenOut_.mint(_msgSender, _amountOut);\n\n        emit SyntheticTokenSwapped(_msgSender, syntheticTokenIn_, syntheticTokenOut_, amountIn_, _amountOut, _fee);\n    }\n\n    /// @inheritdoc SynthContext\n    function poolRegistry() public view override(IPool, SynthContext) returns (IPoolRegistry) {\n        return _poolRegistry;\n    }\n\n    /**\n     * @notice Add debt token to offerings\n     * @dev Must keep `debtTokenOf` mapping updated\n     */\n    function addDebtToken(IDebtToken debtToken_) external onlyGovernor {\n        if (address(debtToken_) == address(0)) revert AddressIsNull();\n        ISyntheticToken _syntheticToken = debtToken_.syntheticToken();\n        if (address(_syntheticToken) == address(0)) revert SyntheticIsNull();\n        if (address(debtTokenOf[_syntheticToken]) != address(0)) revert SyntheticIsInUse();\n\n        if (!debtTokens.add(address(debtToken_))) revert DebtTokenAlreadyExists();\n\n        debtTokenOf[_syntheticToken] = debtToken_;\n\n        emit DebtTokenAdded(debtToken_);\n    }\n\n    /**\n     * @notice Add deposit token (i.e. collateral) to Synth\n     */\n    function addDepositToken(address depositToken_) external onlyGovernor {\n        if (depositToken_ == address(0)) revert AddressIsNull();\n        if (IManageable(depositToken_).pool() != IPool(address(this))) revert InvalidDepositToken();\n        IERC20 _underlying = IDepositToken(depositToken_).underlying();\n        if (address(depositTokenOf[_underlying]) != address(0)) revert UnderlyingAssetInUse();\n        // Note: The `CF * (1 + liquidationFees) < 1` invariant must hold, with a margin (see the constant)\n        if (\n            IDepositToken(depositToken_).collateralFactor() * (1e18 + _liquidationFees(feeProvider)) >=\n            MAX_CF_TIMES_LIQUIDATION_FEES\n        ) {\n            revert CollateralFactorTooHigh();\n        }\n        // Note: Fee collector collects deposit tokens as fee\n        if (depositTokens.length() >= MAX_TOKENS_PER_USER) revert ReachedMaxDepositTokens();\n\n        if (!depositTokens.add(depositToken_)) revert DepositTokenAlreadyExists();\n\n        depositTokenOf[_underlying] = IDepositToken(depositToken_);\n\n        emit DepositTokenAdded(depositToken_);\n    }\n\n    /**\n     * @notice Add a RewardsDistributor contract\n     */\n    function addRewardsDistributor(IRewardsDistributor distributor_) external onlyGovernor {\n        if (address(distributor_) == address(0)) revert AddressIsNull();\n        if (!rewardsDistributors.add(address(distributor_))) revert RewardDistributorAlreadyExists();\n        emit RewardsDistributorAdded(distributor_);\n    }\n\n    /**\n     * @notice Remove debt token from offerings\n     * @dev Must keep `debtTokenOf` mapping updated\n     */\n    function removeDebtToken(IDebtToken debtToken_) external onlyGovernor {\n        if (debtToken_.totalSupply() > 0) revert TotalSupplyIsNotZero();\n        if (!debtTokens.remove(address(debtToken_))) revert DebtTokenDoesNotExist();\n\n        delete debtTokenOf[debtToken_.syntheticToken()];\n\n        emit DebtTokenRemoved(debtToken_);\n    }\n\n    /**\n     * @notice Remove deposit token (i.e. collateral) from Synth\n     */\n    function removeDepositToken(IDepositToken depositToken_) external onlyGovernor {\n        if (depositToken_.totalSupply() > 0) revert TotalSupplyIsNotZero();\n\n        if (!depositTokens.remove(address(depositToken_))) revert DepositTokenDoesNotExist();\n        delete depositTokenOf[depositToken_.underlying()];\n\n        emit DepositTokenRemoved(depositToken_);\n    }\n\n    /**\n     * @notice Remove a RewardsDistributor contract\n     */\n    function removeRewardsDistributor(IRewardsDistributor distributor_) external onlyGovernor {\n        if (address(distributor_) == address(0)) revert AddressIsNull();\n        if (!rewardsDistributors.remove(address(distributor_))) revert RewardDistributorDoesNotExist();\n\n        emit RewardsDistributorRemoved(distributor_);\n    }\n\n    /**\n     * @notice Turn swap on/off\n     */\n    function toggleIsSwapActive() external onlyGovernor {\n        bool _newIsSwapActive = !isSwapActive;\n        emit SwapActiveUpdated(_newIsSwapActive);\n        isSwapActive = _newIsSwapActive;\n    }\n\n    /**\n     * @notice Update debt floor\n     */\n    function updateDebtFloor(uint256 newDebtFloorInUsd_) external onlyGovernor {\n        uint256 _currentDebtFloorInUsd = debtFloorInUsd;\n        if (newDebtFloorInUsd_ == _currentDebtFloorInUsd) revert NewValueIsSameAsCurrent();\n        emit DebtFloorUpdated(_currentDebtFloorInUsd, newDebtFloorInUsd_);\n        debtFloorInUsd = newDebtFloorInUsd_;\n    }\n\n    /**\n     * @notice Update maxLiquidable (liquidation cap)\n     */\n    function updateMaxLiquidable(uint256 newMaxLiquidable_) external onlyGovernor {\n        if (newMaxLiquidable_ > 1e18) revert MaxLiquidableTooHigh();\n        uint256 _currentMaxLiquidable = maxLiquidable;\n        if (newMaxLiquidable_ == _currentMaxLiquidable) revert NewValueIsSameAsCurrent();\n        emit MaxLiquidableUpdated(_currentMaxLiquidable, newMaxLiquidable_);\n        maxLiquidable = newMaxLiquidable_;\n    }\n\n    /**\n     * @notice Update treasury contract - will migrate funds to the new contract\n     */\n    function updateTreasury(ITreasury newTreasury_) external onlyGovernor {\n        if (address(newTreasury_) == address(0)) revert AddressIsNull();\n        ITreasury _currentTreasury = treasury;\n        if (newTreasury_ == _currentTreasury) revert NewValueIsSameAsCurrent();\n\n        if (address(_currentTreasury) != address(0)) {\n            _currentTreasury.migrateTo(address(newTreasury_));\n        }\n\n        emit TreasuryUpdated(_currentTreasury, newTreasury_);\n        treasury = newTreasury_;\n    }\n\n    /**\n     * @notice Update FeeProvider contract\n     */\n    function updateFeeProvider(IFeeProvider feeProvider_) external onlyGovernor {\n        if (address(feeProvider_) == address(0)) revert AddressIsNull();\n        IFeeProvider _current = feeProvider;\n        if (feeProvider_ == _current) revert NewValueIsSameAsCurrent();\n        uint256 _fees = _liquidationFees(feeProvider_);\n        // Note: Validate only when the new provider charges more. Lowering fees can never break the\n        // invariant, a like-for-like swap must not be blocked by collateral already above the bound,\n        // and a fresh pool has no current provider to compare against (nor any deposit token yet).\n        if (address(_current) != address(0) && _fees > _liquidationFees(_current)) {\n            uint256 _length = depositTokens.length();\n            for (uint256 i; i < _length; ++i) {\n                if (\n                    IDepositToken(depositTokens.at(i)).collateralFactor() * (1e18 + _fees) >=\n                    MAX_CF_TIMES_LIQUIDATION_FEES\n                ) revert CollateralFactorTooHigh();\n            }\n        }\n        emit FeeProviderUpdated(_current, feeProvider_);\n        feeProvider = feeProvider_;\n    }\n\n    /**\n     * @notice Update SmartFarmingManager contract\n     */\n    function updateSmartFarmingManager(ISmartFarmingManager newSmartFarmingManager_) external onlyGovernor {\n        if (address(newSmartFarmingManager_) == address(0)) revert AddressIsNull();\n        ISmartFarmingManager _current = smartFarmingManager;\n        if (newSmartFarmingManager_ == _current) revert NewValueIsSameAsCurrent();\n\n        emit SmartFarmingManagerUpdated(_current, newSmartFarmingManager_);\n        smartFarmingManager = newSmartFarmingManager_;\n    }\n\n    /**\n     * @inheritdoc Pauseable\n     */\n    function isGuardian(address sender_) public view override returns (bool) {\n        return _poolRegistry.isGuardian(sender_);\n    }\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/utils/Context.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (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"},{"file_path":"contracts/access/Governable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {Initializable} from \"../dependencies/openzeppelin-upgradeable/proxy/utils/Initializable.sol\";\nimport {Context} from \"../dependencies/openzeppelin/utils/Context.sol\";\nimport {TokenHolder} from \"../utils/TokenHolder.sol\";\nimport {IGovernable} from \"../interfaces/IGovernable.sol\";\n\nerror SenderIsNotGovernor();\nerror ProposedGovernorIsNull();\nerror SenderIsNotTheProposedGovernor();\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (governor) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the governor account will be the one that deploys the contract. This\n * can later be changed with {transferGovernorship}.\n *\n */\nabstract contract Governable is IGovernable, Context, TokenHolder, Initializable {\n    /**\n     * @notice The governor\n     * @dev By default the contract deployer is the initial governor\n     */\n    address public governor;\n\n    /**\n     * @notice The proposed governor\n     * @dev It will be empty (address(0)) if there isn't a proposed governor\n     */\n    address public proposedGovernor;\n\n    event UpdatedGovernor(address indexed previousGovernor, address indexed proposedGovernor);\n\n    constructor() {\n        address _msgSender = _msgSender();\n        governor = _msgSender;\n        emit UpdatedGovernor(address(0), _msgSender);\n    }\n\n    /**\n     * @dev If inheriting child is using proxy then child contract can use\n     * __Governable_init() function to initialization this contract\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function __Governable_init() internal onlyInitializing {\n        address _msgSender = _msgSender();\n        governor = _msgSender;\n        emit UpdatedGovernor(address(0), _msgSender);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the governor.\n     */\n    modifier onlyGovernor() {\n        if (governor != _msgSender()) revert SenderIsNotGovernor();\n        _;\n    }\n\n    /// @inheritdoc TokenHolder\n    // solhint-disable-next-line no-empty-blocks\n    function _requireCanSweep() internal view override onlyGovernor {}\n\n    /**\n     * @notice Transfers governorship of the contract to a new account (`proposedGovernor`).\n     * @dev Can only be called by the current owner.\n     * @param proposedGovernor_ The new proposed governor\n     */\n    function transferGovernorship(address proposedGovernor_) external onlyGovernor {\n        if (proposedGovernor_ == address(0)) revert ProposedGovernorIsNull();\n        proposedGovernor = proposedGovernor_;\n    }\n\n    /**\n     * @notice Allows new governor to accept governorship of the contract.\n     */\n    function acceptGovernorship() external {\n        address _proposedGovernor = proposedGovernor;\n        if (_msgSender() != _proposedGovernor) revert SenderIsNotTheProposedGovernor();\n        emit UpdatedGovernor(governor, _proposedGovernor);\n        governor = _proposedGovernor;\n        proposedGovernor = address(0);\n    }\n}\n"},{"file_path":"contracts/VesperGateway.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {SafeERC20} from \"./dependencies/openzeppelin/token/ERC20/utils/SafeERC20.sol\";\nimport {IERC20} from \"./dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {SynthContext} from \"./utils/SynthContext.sol\";\nimport {ReentrancyGuardTransient} from \"./utils/ReentrancyGuardTransient.sol\";\nimport {TokenHolder} from \"./utils/TokenHolder.sol\";\nimport {IVPool} from \"./interfaces/external/IVPool.sol\";\nimport {IPoolRegistry} from \"./interfaces/IPoolRegistry.sol\";\nimport {IVesperGateway} from \"./interfaces/IVesperGateway.sol\";\nimport {IDepositToken} from \"./interfaces/IDepositToken.sol\";\nimport {IPool} from \"./interfaces/IPool.sol\";\n\nerror SenderIsNotGovernor();\nerror UnregisteredPool();\n\n/**\n * @title Helper contract to easily support vTokens as collateral\n */\ncontract VesperGateway is SynthContext, ReentrancyGuardTransient, TokenHolder, IVesperGateway {\n    using SafeERC20 for IERC20;\n    using SafeERC20 for IDepositToken;\n    using SafeERC20 for IVPool;\n\n    IPoolRegistry internal immutable _poolRegistry;\n\n    modifier onlyGovernor() {\n        if (_poolRegistry.governor() != _msgSender()) revert SenderIsNotGovernor();\n        _;\n    }\n\n    constructor(IPoolRegistry poolRegistry_) {\n        _poolRegistry = poolRegistry_;\n    }\n\n    /**\n     * @notice Deposit `vToken` as collateral using underlying asset.\n     * @param pool_ The Pool contract\n     * @param vToken_ The vToken to deposit\n     * @param amount_ The amount of `underlying` asset to deposit\n     */\n    function deposit(IPool pool_, IVPool vToken_, uint256 amount_) external override {\n        if (!_poolRegistry.isPoolRegistered(address(pool_))) revert UnregisteredPool();\n\n        address _msgSender = _msgSender();\n\n        // 1. Get `underlying` asset\n        IERC20 _underlying = IERC20(vToken_.token());\n        _underlying.safeTransferFrom(_msgSender, address(this), amount_);\n\n        // 2. Deposit `underlying` to `VPool`\n        _underlying.safeApprove(address(vToken_), 0);\n        _underlying.safeApprove(address(vToken_), amount_);\n        uint256 _balanceBefore = vToken_.balanceOf(address(this));\n        vToken_.deposit(amount_);\n        uint256 _vTokenAmount = vToken_.balanceOf(address(this)) - _balanceBefore;\n\n        // 3. Deposit `VPool` to `Synth` and send `msdTokens` to the `_msgSender()`\n        IDepositToken _depositToken = pool_.depositTokenOf(vToken_);\n        vToken_.safeApprove(address(_depositToken), 0);\n        vToken_.safeApprove(address(_depositToken), _vTokenAmount);\n        _depositToken.deposit(_vTokenAmount, _msgSender);\n    }\n\n    /**\n     * @notice Withdraws the `vToken` deposit of _msgSender().\n     * @param pool_ The Pool contract\n     * @param vToken_ The vToken to withdraw\n     * @param amount_ The amount of deposit tokens to withdraw and receive underlying\n     */\n    function withdraw(IPool pool_, IVPool vToken_, uint256 amount_) external override nonReentrant {\n        if (!_poolRegistry.isPoolRegistered(address(pool_))) revert UnregisteredPool();\n\n        address _msgSender = _msgSender();\n\n        // 1. Get `msdTokens`\n        IDepositToken _depositToken = pool_.depositTokenOf(vToken_);\n        _depositToken.safeTransferFrom(_msgSender, address(this), amount_);\n\n        // 2. Withdraw `vTokens` from `Synth`\n        (uint256 _vTokenAmount, ) = _depositToken.withdraw(amount_, address(this));\n\n        // 3. Withdraw `underlying` from `VPool`\n        IERC20 _underlying = IERC20(vToken_.token());\n        uint256 _balanceBefore = _underlying.balanceOf(address(this));\n        vToken_.withdraw(_vTokenAmount);\n        uint256 _underlyingAmount = _underlying.balanceOf(address(this)) - _balanceBefore;\n\n        // 4. Transfer `underlying` to the `_msgSender()`\n        _underlying.safeTransfer(_msgSender, _underlyingAmount);\n    }\n\n    /// @inheritdoc SynthContext\n    function poolRegistry() public view override returns (IPoolRegistry) {\n        return _poolRegistry;\n    }\n\n    /// @inheritdoc TokenHolder\n    // solhint-disable-next-line no-empty-blocks\n    function _requireCanSweep() internal view override onlyGovernor {}\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/token/oft/composable/ComposableOFT.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../../../../../openzeppelin/token/ERC20/ERC20.sol\";\nimport \"./IComposableOFT.sol\";\nimport \"./ComposableOFTCore.sol\";\n\ncontract ComposableOFT is ComposableOFTCore, ERC20, IComposableOFT {\n    constructor(\n        string memory _name,\n        string memory _symbol,\n        address _lzEndpoint\n    ) ERC20(_name, _symbol) ComposableOFTCore(_lzEndpoint) {}\n\n    function supportsInterface(\n        bytes4 interfaceId\n    ) public view virtual override(ComposableOFTCore, IERC165) returns (bool) {\n        return\n            interfaceId == type(IComposableOFT).interfaceId ||\n            interfaceId == type(IOFT).interfaceId ||\n            interfaceId == type(IERC20).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n\n    function circulatingSupply() public view virtual override returns (uint) {\n        return totalSupply();\n    }\n\n    function token() public view virtual override returns (address) {\n        return address(this);\n    }\n\n    function _debitFrom(address _from, uint16, bytes memory, uint _amount) internal virtual override returns (uint) {\n        address spender = _msgSender();\n        if (_from != spender) _spendAllowance(_from, spender, _amount);\n        _burn(_from, _amount);\n        return _amount;\n    }\n\n    function _creditTo(uint16, address _toAddress, uint _amount) internal virtual override returns (uint) {\n        _mint(_toAddress, _amount);\n        return _amount;\n    }\n}\n"},{"file_path":"contracts/PoolRegistry.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {Initializable} from \"./dependencies/openzeppelin-upgradeable/proxy/utils/Initializable.sol\";\nimport {ReentrancyGuardDeprecated} from \"./utils/ReentrancyGuardDeprecated.sol\";\nimport {ReentrancyGuardTransient} from \"./utils/ReentrancyGuardTransient.sol\";\nimport {WadRayMath} from \"./lib/WadRayMath.sol\";\nimport {PoolRegistryStorageV5} from \"./storage/PoolRegistryStorage.sol\";\nimport {IPool} from \"./interfaces/IPool.sol\";\nimport {Pauseable} from \"./utils/Pauseable.sol\";\nimport {EnumerableSet} from \"./dependencies/openzeppelin/utils/structs/EnumerableSet.sol\";\nimport {IMasterOracle} from \"./interfaces/external/IMasterOracle.sol\";\nimport {ISwapper} from \"./interfaces/external/ISwapper.sol\";\nimport {IPoolRegistry} from \"./interfaces/IPoolRegistry.sol\";\nimport {IOperator} from \"./interfaces/IOperator.sol\";\nimport {ISyntheticToken} from \"./interfaces/ISyntheticToken.sol\";\n\nerror AddressIsNull();\nerror OracleIsNull();\nerror FeeCollectorIsNull();\nerror NativeTokenGatewayIsNull();\nerror AlreadyRegistered();\nerror UnregisteredPool();\nerror NewValueIsSameAsCurrent();\nerror UnregisteredGuardian();\n\n/**\n * @title PoolRegistry contract\n */\ncontract PoolRegistry is\n    Initializable,\n    ReentrancyGuardDeprecated,\n    ReentrancyGuardTransient,\n    Pauseable,\n    PoolRegistryStorageV5\n{\n    using WadRayMath for uint256;\n    using EnumerableSet for EnumerableSet.AddressSet;\n\n    string public constant VERSION = \"1.4.1\";\n\n    /// @notice Emitted when fee collector is updated\n    event FeeCollectorUpdated(address indexed oldFeeCollector, address indexed newFeeCollector);\n\n    /// @notice Emitted when master oracle contract is updated\n    event MasterOracleUpdated(IMasterOracle indexed oldOracle, IMasterOracle indexed newOracle);\n\n    /// @notice Emitted when native token gateway is updated\n    event NativeTokenGatewayUpdated(address indexed oldGateway, address indexed newGateway);\n\n    /// @notice Emitted when a pool is registered\n    event PoolRegistered(uint256 indexed id, address indexed pool);\n\n    /// @notice Emitted when a pool is unregistered\n    event PoolUnregistered(uint256 indexed id, address indexed pool);\n\n    /// @notice Emitted when Swapper contract is updated\n    event SwapperUpdated(ISwapper oldSwapFee, ISwapper newSwapFee);\n\n    /// @notice Emitted when a guardian is added\n    event GuardianAdded(address indexed guardian);\n\n    /// @notice Emitted when a guardian is removed\n    event GuardianRemoved(address indexed guardian);\n\n    /// @notice Emitted when Operator contract is updated\n    event OperatorUpdated(IOperator oldOperator, IOperator newOperator);\n\n    /// @notice Emitted when Lz base gas limit updated\n    event LzBaseGasLimitUpdated(uint256 oldLzBaseGasLimit, uint256 newLzBaseGasLimit);\n\n    /// @notice Emitted when flag for pause bridge transfer is toggled\n    event BridgingIsActiveUpdated(bool newIsActive);\n\n    /// @notice Emitted when flag for support chain is toggled\n    event DestinationChainIsActiveUpdated(uint16 chainId, bool newIsSupported);\n\n    constructor() {\n        _disableInitializers();\n    }\n\n    function initialize(IMasterOracle masterOracle_, address feeCollector_) external initializer {\n        if (address(masterOracle_) == address(0)) revert OracleIsNull();\n        if (feeCollector_ == address(0)) revert FeeCollectorIsNull();\n\n        __Pauseable_init();\n\n        masterOracle = masterOracle_;\n        feeCollector = feeCollector_;\n\n        nextPoolId = 1;\n    }\n\n    /**\n     * @notice Check if any pool has the token as part of its offerings\n     * @param syntheticToken_ Asset to check\n     * @return _exists Return true if exists\n     */\n    function doesSyntheticTokenExist(ISyntheticToken syntheticToken_) external view returns (bool _exists) {\n        uint256 _length = pools.length();\n        for (uint256 i; i < _length; ++i) {\n            if (IPool(pools.at(i)).doesSyntheticTokenExist(syntheticToken_)) {\n                return true;\n            }\n        }\n    }\n\n    /**\n     * @notice Get all pools\n     * @dev WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees.\n     */\n    function getPools() external view override returns (address[] memory) {\n        return pools.values();\n    }\n\n    /**\n     * @notice Check if pool is registered\n     * @param pool_ Pool to check\n     * @return true if exists\n     */\n    function isPoolRegistered(address pool_) external view override returns (bool) {\n        return pools.contains(pool_);\n    }\n\n    /**\n     * @inheritdoc Pauseable\n     */\n    function isGuardian(address sender_) public view override(IPoolRegistry, Pauseable) returns (bool) {\n        return guardians.contains(sender_);\n    }\n\n    /**\n     * @notice Register pool\n     */\n    function registerPool(address pool_) external override onlyGovernor {\n        if (pool_ == address(0)) revert AddressIsNull();\n        if (!pools.add(pool_)) revert AlreadyRegistered();\n        uint256 _id = idOfPool[pool_];\n        if (_id == 0) {\n            _id = nextPoolId++;\n            idOfPool[pool_] = _id;\n        }\n        emit PoolRegistered(_id, pool_);\n    }\n\n    /**\n     * @notice Unregister pool\n     */\n    function unregisterPool(address pool_) external override onlyGovernor {\n        if (!pools.remove(pool_)) revert UnregisteredPool();\n        emit PoolUnregistered(idOfPool[pool_], pool_);\n    }\n\n    /**\n     * @notice Add guardian\n     */\n    function addGuardian(address guardian_) external onlyGovernor {\n        if (guardian_ == address(0)) revert AddressIsNull();\n        if (!guardians.add(guardian_)) revert AlreadyRegistered();\n        emit GuardianAdded(guardian_);\n    }\n\n    /**\n     * @notice Remove guardian\n     */\n    function removeGuardian(address guardian_) external onlyGovernor {\n        if (!guardians.remove(guardian_)) revert UnregisteredGuardian();\n        emit GuardianRemoved(guardian_);\n    }\n\n    /**\n     * @notice Get all guardians\n     * @dev WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees.\n     */\n    function getGuardians() external view returns (address[] memory) {\n        return guardians.values();\n    }\n\n    /**\n     * @notice Update fee collector\n     */\n    function updateFeeCollector(address newFeeCollector_) external override onlyGovernor {\n        if (newFeeCollector_ == address(0)) revert FeeCollectorIsNull();\n        address _currentFeeCollector = feeCollector;\n        if (newFeeCollector_ == _currentFeeCollector) revert NewValueIsSameAsCurrent();\n        emit FeeCollectorUpdated(_currentFeeCollector, newFeeCollector_);\n        feeCollector = newFeeCollector_;\n    }\n\n    /**\n     * @notice Update master oracle contract\n     */\n    function updateMasterOracle(IMasterOracle newMasterOracle_) external onlyGovernor {\n        if (address(newMasterOracle_) == address(0)) revert OracleIsNull();\n        IMasterOracle _currentMasterOracle = masterOracle;\n        if (newMasterOracle_ == _currentMasterOracle) revert NewValueIsSameAsCurrent();\n        emit MasterOracleUpdated(_currentMasterOracle, newMasterOracle_);\n        masterOracle = newMasterOracle_;\n    }\n\n    /**\n     * @notice Update native token gateway\n     */\n    function updateNativeTokenGateway(address newGateway_) external onlyGovernor {\n        if (address(newGateway_) == address(0)) revert NativeTokenGatewayIsNull();\n        address _currentGateway = nativeTokenGateway;\n        if (newGateway_ == _currentGateway) revert NewValueIsSameAsCurrent();\n        emit NativeTokenGatewayUpdated(_currentGateway, newGateway_);\n        nativeTokenGateway = newGateway_;\n    }\n\n    /**\n     * @notice Update Swapper contract\n     */\n    function updateSwapper(ISwapper newSwapper_) external onlyGovernor {\n        if (address(newSwapper_) == address(0)) revert AddressIsNull();\n        ISwapper _currentSwapper = swapper;\n        if (newSwapper_ == _currentSwapper) revert NewValueIsSameAsCurrent();\n\n        emit SwapperUpdated(_currentSwapper, newSwapper_);\n        swapper = newSwapper_;\n    }\n\n    /**\n     * @notice Update Operator contract\n     */\n    function updateOperator(IOperator newOperator_) external onlyGovernor {\n        IOperator _currentOperator = operator;\n        if (newOperator_ == _currentOperator) revert NewValueIsSameAsCurrent();\n\n        emit OperatorUpdated(_currentOperator, newOperator_);\n        operator = newOperator_;\n    }\n\n    /**\n     * @notice Update Lz base gas limit\n     */\n    function updateLzBaseGasLimit(uint256 newLzBaseGasLimit_) external onlyGovernor {\n        uint256 _currentBaseGasLimit = lzBaseGasLimit;\n        if (newLzBaseGasLimit_ == _currentBaseGasLimit) revert NewValueIsSameAsCurrent();\n        emit LzBaseGasLimitUpdated(_currentBaseGasLimit, newLzBaseGasLimit_);\n        lzBaseGasLimit = newLzBaseGasLimit_;\n    }\n\n    /**\n     * @notice Pause/Unpause bridge transfers\n     */\n    function toggleBridgingIsActive() external onlyGovernor {\n        bool _newIsBridgingActive = !isBridgingActive;\n        emit BridgingIsActiveUpdated(_newIsBridgingActive);\n        isBridgingActive = _newIsBridgingActive;\n    }\n\n    /**\n     * @notice Allow/Disallow destination chain\n     * @dev Use LZ chain id\n     */\n    function toggleDestinationChainIsActive(uint16 chainId_) external onlyGovernor {\n        bool _isDestinationChainSupported = !isDestinationChainSupported[chainId_];\n        emit DestinationChainIsActiveUpdated(chainId_, _isDestinationChainSupported);\n        isDestinationChainSupported[chainId_] = _isDestinationChainSupported;\n    }\n}\n"},{"file_path":"contracts/storage/SyntheticTokenStorage.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IPoolRegistry} from \"../interfaces/IPoolRegistry.sol\";\nimport {IProxyOFT} from \"../interfaces/IProxyOFT.sol\";\nimport {ISyntheticToken} from \"../interfaces/ISyntheticToken.sol\";\n\nabstract contract SyntheticTokenStorageV1 is ISyntheticToken {\n    /**\n     * @notice The name of the token\n     */\n    string public override name;\n\n    /**\n     * @notice The symbol of the token\n     */\n    string public override symbol;\n\n    /**\n     * @dev The amount of tokens owned by `account`\n     */\n    mapping(address => uint256) public override balanceOf;\n\n    /**\n     * @dev The remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}\n     */\n    mapping(address => mapping(address => uint256)) public override allowance;\n\n    /**\n     * @dev Amount of tokens in existence\n     */\n    uint256 public override totalSupply;\n\n    /**\n     * @notice The supply cap\n     */\n    uint256 public override maxTotalSupply;\n\n    /**\n     * @dev The Pool Registry\n     */\n    IPoolRegistry internal _poolRegistry;\n\n    /**\n     * @notice If true, disables msAsset minting globally\n     */\n    bool public override isActive;\n\n    /**\n     * @notice The decimals of the token\n     */\n    uint8 public override decimals;\n\n    /**\n     * @notice The ProxyOFT contract\n     */\n    IProxyOFT public override proxyOFT;\n\n    /**\n     * @notice Track amount received cross-chain\n     */\n    uint256 public totalBridgedIn;\n\n    /**\n     * @notice Track amount sent cross-chain\n     */\n    uint256 public totalBridgedOut;\n\n    /**\n     * @notice Maximum allowed bridged-in (mint-related) supply\n     */\n    uint256 public maxBridgedInSupply;\n\n    /**\n     * @notice Maximum allowed bridged-out (burn-related) supply\n     */\n    uint256 public maxBridgedOutSupply;\n}\n\nabstract contract SyntheticTokenStorageV2 is SyntheticTokenStorageV1 {\n    /**\n     * @notice Automated Market Operator, it can be a contract, safe or EOA\n     */\n    address public amo;\n\n    /**\n     * @notice Maximum Synth AMO can mint. It can be updated by admin/governor.\n     */\n    uint256 public maxAmoSupply;\n\n    /**\n     * @notice Synth minted by AMO so far. It will be reduced when Synths are burnt by AMO.\n     */\n    uint256 public amoSupply;\n}\n"},{"file_path":"contracts/dependencies/stargate-protocol/interfaces/IStargateRouter.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.9;\n\ninterface IStargateRouter {\n    struct lzTxObj {\n        uint256 dstGasForCall;\n        uint256 dstNativeAmount;\n        bytes dstNativeAddr;\n    }\n\n    function addLiquidity(uint256 _poolId, uint256 _amountLD, address _to) external;\n\n    function swap(\n        uint16 _dstChainId,\n        uint256 _srcPoolId,\n        uint256 _dstPoolId,\n        address payable _refundAddress,\n        uint256 _amountLD,\n        uint256 _minAmountLD,\n        lzTxObj memory _lzTxParams,\n        bytes calldata _to,\n        bytes calldata _payload\n    ) external payable;\n\n    function redeemRemote(\n        uint16 _dstChainId,\n        uint256 _srcPoolId,\n        uint256 _dstPoolId,\n        address payable _refundAddress,\n        uint256 _amountLP,\n        uint256 _minAmountLD,\n        bytes calldata _to,\n        lzTxObj memory _lzTxParams\n    ) external payable;\n\n    function instantRedeemLocal(uint16 _srcPoolId, uint256 _amountLP, address _to) external returns (uint256);\n\n    function redeemLocal(\n        uint16 _dstChainId,\n        uint256 _srcPoolId,\n        uint256 _dstPoolId,\n        address payable _refundAddress,\n        uint256 _amountLP,\n        bytes calldata _to,\n        lzTxObj memory _lzTxParams\n    ) external payable;\n\n    function sendCredits(\n        uint16 _dstChainId,\n        uint256 _srcPoolId,\n        uint256 _dstPoolId,\n        address payable _refundAddress\n    ) external payable;\n\n    function quoteLayerZeroFee(\n        uint16 _dstChainId,\n        uint8 _functionType,\n        bytes calldata _toAddress,\n        bytes calldata _transferAndCallPayload,\n        lzTxObj memory _lzTxParams\n    ) external view returns (uint256, uint256);\n\n    function clearCachedSwap(uint16 _srcChainId, bytes calldata _srcAddress, uint256 _nonce) external;\n\n    function factory() external view returns (address);\n\n    function bridge() external view returns (address);\n\n    function cachedSwapLookup(\n        uint16 _chainId_,\n        bytes calldata _srcAddress,\n        uint256 _nonce\n    ) external view returns (address token, uint256 amountLD, address to, bytes memory payload);\n}\n"},{"file_path":"contracts/interfaces/external/IESMET.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IERC20} from \"../../dependencies/openzeppelin/token/ERC20/IERC20.sol\";\n\ninterface IESMET is IERC20 {\n    struct LockPosition {\n        uint256 lockedAmount; // MET locked\n        uint256 boostedAmount; // based on the `lockPeriod`\n        uint256 unlockTime; // now + `lockPeriod`\n    }\n\n    function positions(uint256) external view returns (LockPosition memory);\n\n    function MINIMUM_LOCK_PERIOD() external view returns (uint256);\n\n    function MAXIMUM_LOCK_PERIOD() external view returns (uint256);\n\n    function balanceOf(address account_) external view returns (uint256);\n\n    function lock(uint256 amount_, uint256 lockPeriod_) external;\n\n    function lockFor(address to_, uint256 amount_, uint256 lockPeriod_) external;\n}\n"},{"file_path":"contracts/storage/DepositTokenStorage.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IERC20} from \"../dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {IDepositToken} from \"../interfaces/IDepositToken.sol\";\n\nabstract contract DepositTokenStorageV1 is IDepositToken {\n    /**\n     * @dev The amount of tokens owned by `account`\n     */\n    mapping(address => uint256) public override balanceOf;\n\n    /**\n     * @dev The remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}\n     */\n    mapping(address => mapping(address => uint256)) public override allowance;\n\n    /**\n     * @notice The name of the token\n     */\n    string public override name;\n\n    /**\n     * @notice The symbol of the token\n     */\n    string public override symbol;\n\n    /**\n     * @dev Amount of tokens in existence\n     */\n    uint256 public override totalSupply;\n\n    /**\n     * @notice The supply cap (in USD)\n     */\n    uint256 public override maxTotalSupply;\n\n    /**\n     * @notice Collateral factor for the deposit token\n     * @dev Use 18 decimals (e.g. 0.66e18 = 66%)\n     */\n    uint256 public override collateralFactor;\n\n    /**\n     * @notice Deposit underlying asset (e.g. MET)\n     */\n    IERC20 public override underlying;\n\n    /**\n     * @notice If a collateral isn't active, it disables minting new tokens\n     */\n    bool public override isActive;\n\n    /**\n     * @notice The decimals of the token\n     */\n    uint8 public override decimals;\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/contracts-upgradeable/interfaces/ILayerZeroEndpointUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.2;\n\nimport \"./ILayerZeroUserApplicationConfigUpgradeable.sol\";\n\ninterface ILayerZeroEndpointUpgradeable is ILayerZeroUserApplicationConfigUpgradeable {\n    // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n    // @param _dstChainId - the destination chain identifier\n    // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n    // @param _payload - a custom bytes payload to send to the destination contract\n    // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n    // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n    // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n    function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n    // @notice used by the messaging library to publish verified payload\n    // @param _srcChainId - the source chain identifier\n    // @param _srcAddress - the source contract (as bytes) at the source chain\n    // @param _dstAddress - the address on destination chain\n    // @param _nonce - the unbound message ordering nonce\n    // @param _gasLimit - the gas limit for external contract execution\n    // @param _payload - verified payload to send to the destination contract\n    function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n    // @notice get the inboundNonce of a lzApp from a source chain which could be EVM or non-EVM chain\n    // @param _srcChainId - the source chain identifier\n    // @param _srcAddress - the source chain contract address\n    function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n    // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n    // @param _srcAddress - the source chain contract address\n    function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n    // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n    // @param _dstChainId - the destination chain identifier\n    // @param _userApplication - the user app address on this EVM chain\n    // @param _payload - the custom message to send over LayerZero\n    // @param _payInZRO - if false, user app pays the protocol fee in native token\n    // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n    function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n    // @notice get this Endpoint's immutable source identifier\n    function getChainId() external view returns (uint16);\n\n    // @notice the interface to retry failed message on this Endpoint destination\n    // @param _srcChainId - the source chain identifier\n    // @param _srcAddress - the source chain contract address\n    // @param _payload - the payload to be retried\n    function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n    // @notice query if any STORED payload (message blocking) at the endpoint.\n    // @param _srcChainId - the source chain identifier\n    // @param _srcAddress - the source chain contract address\n    function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n    // @notice query if the _libraryAddress is valid for sending msgs.\n    // @param _userApplication - the user app address on this EVM chain\n    function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n    // @notice query if the _libraryAddress is valid for receiving msgs.\n    // @param _userApplication - the user app address on this EVM chain\n    function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n    // @notice query if the non-reentrancy guard for send() is on\n    // @return true if the guard is on. false otherwise\n    function isSendingPayload() external view returns (bool);\n\n    // @notice query if the non-reentrancy guard for receive() is on\n    // @return true if the guard is on. false otherwise\n    function isReceivingPayload() external view returns (bool);\n\n    // @notice get the configuration of the LayerZero messaging library of the specified version\n    // @param _version - messaging library version\n    // @param _chainId - the chainId for the pending config change\n    // @param _userApplication - the contract address of the user application\n    // @param _configType - type of configuration. every messaging library has its own convention.\n    function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n    // @notice get the send() LayerZero messaging library version\n    // @param _userApplication - the contract address of the user application\n    function getSendVersion(address _userApplication) external view returns (uint16);\n\n    // @notice get the lzReceive() LayerZero messaging library version\n    // @param _userApplication - the contract address of the user application\n    function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n"},{"file_path":"contracts/DepositToken.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IERC20} from \"./dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {SafeERC20} from \"./dependencies/openzeppelin/token/ERC20/utils/SafeERC20.sol\";\nimport {Initializable} from \"./dependencies/openzeppelin-upgradeable/proxy/utils/Initializable.sol\";\nimport {Math} from \"./dependencies/openzeppelin/utils/math/Math.sol\";\nimport {Manageable, SenderIsNotPool} from \"./access/Manageable.sol\";\nimport {ReentrancyGuardDeprecated} from \"./utils/ReentrancyGuardDeprecated.sol\";\nimport {ReentrancyGuardTransient} from \"./utils/ReentrancyGuardTransient.sol\";\nimport {TokenHolder} from \"./utils/TokenHolder.sol\";\nimport {WadRayMath} from \"./lib/WadRayMath.sol\";\nimport {IRewardsDistributor} from \"./interfaces/IRewardsDistributor.sol\";\nimport {IPool} from \"./interfaces/IPool.sol\";\nimport {DepositTokenStorageV1} from \"./storage/DepositTokenStorage.sol\";\n\nerror CollateralIsInexistent();\nerror DepositTokenIsInactive();\nerror NotEnoughFreeBalance();\nerror UnderlyingAssetIsNull();\nerror PoolIsNull();\nerror SymbolIsNull();\nerror DecimalsIsNull();\nerror CollateralFactorTooHigh();\nerror CollateralFactorTooLow();\nerror DecreasedAllowanceBelowZero();\nerror AmountIsZero();\nerror BeneficiaryIsNull();\nerror AmountExceedsAllowance();\nerror RecipientIsNull();\nerror ApproveFromTheZeroAddress();\nerror ApproveToTheZeroAddress();\nerror BurnFromTheZeroAddress();\nerror BurnAmountExceedsBalance();\nerror MintToTheZeroAddress();\nerror SurpassMaxDepositSupply();\nerror TransferFromTheZeroAddress();\nerror TransferToTheZeroAddress();\nerror TransferAmountExceedsBalance();\nerror NewValueIsSameAsCurrent();\nerror SenderIsNotSmartFarmingManager();\nerror TreasuryCanNotDeposit();\n\n/**\n * @title Represents the users' deposits\n */\ncontract DepositToken is\n    Initializable,\n    ReentrancyGuardDeprecated,\n    ReentrancyGuardTransient,\n    TokenHolder,\n    Manageable,\n    DepositTokenStorageV1\n{\n    using SafeERC20 for IERC20;\n    using WadRayMath for uint256;\n\n    string public constant VERSION = \"1.4.1\";\n\n    // Note: Upper bound on `collateralFactor * (1 + liquidationFees)`. The `< 1e36` form only\n    // guarantees liquidation *eventually* helps; at exactly 1e36 it closes 0 wei of the health\n    // gap. This leaves a margin so every liquidation closes >= 2% of the amount repaid.\n    uint256 internal constant MAX_CF_TIMES_LIQUIDATION_FEES = 0.98e36;\n\n    /// @notice Emitted when collateral is deposited\n    event CollateralDeposited(\n        address indexed from,\n        address indexed account,\n        uint256 amount,\n        uint256 deposited,\n        uint256 fee\n    );\n\n    /// @notice Emitted when CF is updated\n    event CollateralFactorUpdated(uint256 oldCollateralFactor, uint256 newCollateralFactor);\n\n    /// @notice Emitted when collateral is withdrawn\n    event CollateralWithdrawn(\n        address indexed account,\n        address indexed to,\n        uint256 amount,\n        uint256 withdrawn,\n        uint256 fee\n    );\n\n    /// @notice Emitted when active flag is updated\n    event DepositTokenActiveUpdated(bool newActive);\n\n    /// @notice Emitted when max total supply is updated\n    event MaxTotalSupplyUpdated(uint256 oldMaxTotalSupply, uint256 newMaxTotalSupply);\n\n    /**\n     * @dev Throws if sender is SmartFarmingManager\n     */\n    modifier onlyIfSmartFarmingManager() {\n        if (_msgSender() != address(pool.smartFarmingManager())) revert SenderIsNotSmartFarmingManager();\n        _;\n    }\n\n    /**\n     * @dev Throws if sender can't seize\n     */\n    modifier onlyIfCanSeize() {\n        if (_msgSender() != address(pool)) revert SenderIsNotPool();\n        _;\n    }\n\n    /**\n     * @dev Throws if deposit token doesn't exist\n     */\n    modifier onlyIfDepositTokenExists() {\n        if (!pool.doesDepositTokenExist(this)) revert CollateralIsInexistent();\n        _;\n    }\n\n    /**\n     * @dev Throws if deposit token isn't enabled\n     */\n    modifier onlyIfDepositTokenIsActive() {\n        if (!isActive) revert DepositTokenIsInactive();\n        _;\n    }\n\n    /**\n     * @notice Update reward contracts' states\n     * @dev Should be called before balance changes (i.e. mint/burn)\n     */\n    modifier updateRewardsBeforeMintOrBurn(address account_) {\n        address[] memory _rewardsDistributors = pool.getRewardsDistributors();\n        uint256 _length = _rewardsDistributors.length;\n        for (uint256 i; i < _length; ++i) {\n            IRewardsDistributor(_rewardsDistributors[i]).updateBeforeMintOrBurn(this, account_);\n        }\n        _;\n    }\n\n    /**\n     * @notice Update reward contracts' states\n     * @dev Should be called before balance changes (i.e. transfer)\n     */\n    modifier updateRewardsBeforeTransfer(address sender_, address recipient_) {\n        address[] memory _rewardsDistributors = pool.getRewardsDistributors();\n        uint256 _length = _rewardsDistributors.length;\n        for (uint256 i; i < _length; ++i) {\n            IRewardsDistributor(_rewardsDistributors[i]).updateBeforeTransfer(this, sender_, recipient_);\n        }\n        _;\n    }\n\n    constructor() {\n        _disableInitializers();\n    }\n\n    function initialize(\n        IERC20 underlying_,\n        IPool pool_,\n        string calldata name_,\n        string calldata symbol_,\n        uint8 decimals_,\n        uint128 collateralFactor_,\n        uint256 maxTotalSupply_\n    ) external initializer {\n        if (address(underlying_) == address(0)) revert UnderlyingAssetIsNull();\n        if (address(pool_) == address(0)) revert PoolIsNull();\n        if (bytes(symbol_).length == 0) revert SymbolIsNull();\n        if (decimals_ == 0) revert DecimalsIsNull();\n        if (collateralFactor_ == 0) revert CollateralFactorTooLow();\n        if (collateralFactor_ >= 1e18) revert CollateralFactorTooHigh();\n\n        __Manageable_init(pool_);\n\n        name = name_;\n        symbol = symbol_;\n        underlying = underlying_;\n        isActive = true;\n        decimals = decimals_;\n        collateralFactor = collateralFactor_;\n        maxTotalSupply = maxTotalSupply_;\n    }\n\n    /**\n     * @notice Requires that amount is lower than the account's unlocked balance\n     */\n    function _revertIfLocked(address account_, uint256 amount_) private view {\n        if (unlockedBalanceOf(account_) < amount_) revert NotEnoughFreeBalance();\n    }\n\n    /**\n     * @notice Set `amount` as the allowance of `spender` over the caller's tokens\n     */\n    function approve(address spender_, uint256 amount_) external override returns (bool) {\n        _approve(_msgSender(), spender_, amount_);\n        return true;\n    }\n\n    /**\n     * @notice Atomically decrease the allowance granted to `spender` by the caller\n     */\n    function decreaseAllowance(address spender_, uint256 subtractedValue_) external returns (bool) {\n        address _msgSender = _msgSender();\n        uint256 _currentAllowance = allowance[_msgSender][spender_];\n        if (_currentAllowance < subtractedValue_) revert DecreasedAllowanceBelowZero();\n        unchecked {\n            _approve(_msgSender, spender_, _currentAllowance - subtractedValue_);\n        }\n        return true;\n    }\n\n    /**\n     * @notice Deposit collateral and mint msdTOKEN (tokenized deposit position)\n     * @param amount_ The amount of collateral tokens to deposit\n     * @param onBehalfOf_ The account to deposit to\n     * @return _deposited The amount deposited after fees\n     */\n    function deposit(\n        uint256 amount_,\n        address onBehalfOf_\n    ) external override whenNotPaused nonReentrant onlyIfDepositTokenExists returns (uint256 _deposited, uint256 _fee) {\n        if (amount_ == 0) revert AmountIsZero();\n        if (onBehalfOf_ == address(0)) revert BeneficiaryIsNull();\n\n        IPool _pool = pool;\n        IERC20 _underlying = underlying;\n        address _msgSender = _msgSender();\n        address _treasury = address(_pool.treasury());\n\n        if (_msgSender == _treasury) revert TreasuryCanNotDeposit();\n\n        uint256 _balanceBefore = _underlying.balanceOf(_treasury);\n        _underlying.safeTransferFrom(_msgSender, _treasury, amount_);\n        amount_ = _underlying.balanceOf(_treasury) - _balanceBefore;\n\n        (_deposited, _fee) = quoteDepositOut(amount_);\n        if (_fee > 0) {\n            _mint(_pool.feeCollector(), _fee);\n        }\n\n        _mint(onBehalfOf_, _deposited);\n\n        emit CollateralDeposited(_msgSender, onBehalfOf_, amount_, _deposited, _fee);\n    }\n\n    /**\n     * @notice Burn msdTOKEN, withdraw collateral and transfer to `_msgSender()` (i.e. SmartFarmingManager)\n     * @param account_ The account where deposit token will be burnt from\n     * @param amount_ The amount of collateral to withdraw\n     * @return _withdrawn The amount withdrawn after fees\n     */\n    function flashWithdraw(\n        address account_,\n        uint256 amount_\n    ) external override onlyIfSmartFarmingManager returns (uint256 _withdrawn, uint256 _fee) {\n        return _withdraw({account_: account_, amount_: amount_, to_: _msgSender()});\n    }\n\n    /**\n     * @notice Atomically increase the allowance granted to `spender` by the caller\n     */\n    function increaseAllowance(address spender_, uint256 addedValue_) external returns (bool) {\n        address _msgSender = _msgSender();\n        _approve(_msgSender, spender_, allowance[_msgSender][spender_] + addedValue_);\n        return true;\n    }\n\n    /**\n     * @notice Get the locked balance\n     * @param account_ The account to check\n     * @return _lockedBalance The locked amount\n     */\n    function lockedBalanceOf(address account_) external view override returns (uint256 _lockedBalance) {\n        unchecked {\n            return balanceOf[account_] - unlockedBalanceOf(account_);\n        }\n    }\n\n    /**\n     * @notice Quote gross `_amount` to deposit `amountToDeposit_` collateral\n     * @param amountToDeposit_ Collateral to deposit\n     * @return _amount Gross amount\n     * @return _fee Fee amount to collect\n     */\n    function quoteDepositIn(uint256 amountToDeposit_) external view override returns (uint256 _amount, uint256 _fee) {\n        uint256 _depositFee = pool.feeProvider().depositFee();\n        if (_depositFee == 0) {\n            return (amountToDeposit_, _fee);\n        }\n\n        _amount = amountToDeposit_.wadDiv(1e18 - _depositFee);\n        _fee = _amount - amountToDeposit_;\n    }\n\n    /**\n     * @notice Quote collateral `_amountToDeposit` by using gross `amount_`\n     * @param amount_ Gross amount\n     * @return _amountToDeposit Collateral to deposit\n     * @return _fee Fee amount to collect\n     */\n    function quoteDepositOut(uint256 amount_) public view override returns (uint256 _amountToDeposit, uint256 _fee) {\n        uint256 _depositFee = pool.feeProvider().depositFee();\n        if (_depositFee == 0) {\n            return (amount_, _fee);\n        }\n\n        _fee = amount_.wadMul(_depositFee);\n        _amountToDeposit = amount_ - _fee;\n    }\n\n    /**\n     * @notice Quote gross `_amount` to withdraw `amountToWithdraw_` collateral\n     * @param amountToWithdraw_ Collateral to withdraw\n     * @return _amount Gross amount\n     * @return _fee Fee amount to collect\n     */\n    function quoteWithdrawIn(uint256 amountToWithdraw_) external view override returns (uint256 _amount, uint256 _fee) {\n        uint256 _withdrawFee = pool.feeProvider().withdrawFee();\n        if (_withdrawFee == 0) {\n            return (amountToWithdraw_, _fee);\n        }\n\n        _amount = amountToWithdraw_.wadDiv(1e18 - _withdrawFee);\n        _fee = _amount - amountToWithdraw_;\n    }\n\n    /**\n     * @notice Quote collateral `_amountToWithdraw` by using gross `_amount`\n     * @param amount_ Gross amount\n     * @return _amountToWithdraw Collateral to withdraw\n     * @return _fee Fee amount to collect\n     */\n    function quoteWithdrawOut(uint256 amount_) public view override returns (uint256 _amountToWithdraw, uint256 _fee) {\n        uint256 _withdrawFee = pool.feeProvider().withdrawFee();\n        if (_withdrawFee == 0) {\n            return (amount_, _fee);\n        }\n\n        _fee = amount_.wadMul(_withdrawFee);\n        _amountToWithdraw = amount_ - _fee;\n    }\n\n    /**\n     * @notice Seize tokens\n     * @dev Same as _transfer\n     * @param from_ The account to seize from\n     * @param to_ The beneficiary account\n     * @param amount_ The amount to seize\n     */\n    function seize(address from_, address to_, uint256 amount_) external override onlyIfCanSeize {\n        _transfer(from_, to_, amount_);\n    }\n\n    /// @inheritdoc IERC20\n    function transfer(address to_, uint256 amount_) external override returns (bool) {\n        address _msgSender = _msgSender();\n        _revertIfLocked(_msgSender, amount_);\n\n        _transfer(_msgSender, to_, amount_);\n        return true;\n    }\n\n    /// @inheritdoc IERC20\n    function transferFrom(\n        address sender_,\n        address recipient_,\n        uint256 amount_\n    ) external override nonReentrant returns (bool) {\n        _revertIfLocked(sender_, amount_);\n\n        address _msgSender = _msgSender();\n        uint256 _currentAllowance = allowance[sender_][_msgSender];\n        if (_currentAllowance != type(uint256).max) {\n            if (_currentAllowance < amount_) revert AmountExceedsAllowance();\n            unchecked {\n                _approve(sender_, _msgSender, _currentAllowance - amount_);\n            }\n        }\n\n        _transfer(sender_, recipient_, amount_);\n\n        return true;\n    }\n\n    /**\n     * @notice Get the unlocked balance (i.e. transferable, withdrawable)\n     * @param account_ The account to check\n     * @return _unlockedBalance The amount that user can transfer or withdraw\n     */\n    function unlockedBalanceOf(address account_) public view override returns (uint256 _unlockedBalance) {\n        IPool _pool = pool;\n\n        (, , uint256 _debtInUsd, , uint256 _issuableInUsd) = _pool.debtPositionOf(account_);\n\n        if (_debtInUsd == 0) {\n            return balanceOf[account_];\n        }\n\n        if (_issuableInUsd > 0) {\n            _unlockedBalance = Math.min(\n                balanceOf[account_],\n                _pool.masterOracle().quoteUsdToToken(address(underlying), _issuableInUsd.wadDiv(collateralFactor))\n            );\n        }\n    }\n\n    /**\n     * @notice Burn msdTOKEN and withdraw collateral\n     * @param amount_ The amount of collateral to withdraw\n     * @param to_ The account that will receive withdrawn collateral\n     * @return _withdrawn The amount withdrawn after fees\n     */\n    function withdraw(uint256 amount_, address to_) external override returns (uint256 _withdrawn, uint256 _fee) {\n        if (to_ == address(0)) revert RecipientIsNull();\n        address _msgSender = _msgSender();\n        _revertIfLocked(_msgSender, amount_);\n\n        return _withdraw({account_: _msgSender, amount_: amount_, to_: to_});\n    }\n\n    /**\n     * @notice Burn msdTOKEN and withdraw collateral from a given account\n     * @param from_ The account to withdraw from\n     * @param amount_ The amount of collateral to withdraw\n     * @return _withdrawn The amount withdrawn after fees\n     */\n    function withdrawFrom(\n        address from_,\n        uint256 amount_\n    ) external override onlyIfSmartFarmingManager returns (uint256 _withdrawn, uint256 _fee) {\n        _revertIfLocked(from_, amount_);\n\n        return _withdraw({account_: from_, amount_: amount_, to_: _msgSender()});\n    }\n\n    /**\n     * @notice Set `amount` as the allowance of `spender` over the caller's tokens\n     */\n    function _approve(address owner_, address spender_, uint256 amount_) private {\n        if (owner_ == address(0)) revert ApproveFromTheZeroAddress();\n        if (spender_ == address(0)) revert ApproveToTheZeroAddress();\n\n        allowance[owner_][spender_] = amount_;\n        emit Approval(owner_, spender_, amount_);\n    }\n\n    /**\n     * @notice Destroy `amount` tokens from `account`, reducing the\n     * total supply\n     */\n    function _burn(address _account, uint256 _amount) private updateRewardsBeforeMintOrBurn(_account) {\n        if (_account == address(0)) revert BurnFromTheZeroAddress();\n\n        uint256 _balanceBefore = balanceOf[_account];\n        if (_balanceBefore < _amount) revert BurnAmountExceedsBalance();\n        uint256 _balanceAfter;\n        unchecked {\n            _balanceAfter = _balanceBefore - _amount;\n            totalSupply -= _amount;\n        }\n\n        balanceOf[_account] = _balanceAfter;\n\n        emit Transfer(_account, address(0), _amount);\n\n        // Remove this token from the deposit tokens list if the sender's balance goes to zero\n        if (_amount > 0 && _balanceAfter == 0) {\n            pool.removeFromDepositTokensOfAccount(_account);\n        }\n    }\n\n    /**\n     * @notice Create `amount` tokens and assigns them to `account`, increasing\n     * the total supply\n     */\n    function _mint(\n        address account_,\n        uint256 amount_\n    ) private onlyIfDepositTokenIsActive updateRewardsBeforeMintOrBurn(account_) {\n        if (account_ == address(0)) revert MintToTheZeroAddress();\n\n        totalSupply += amount_;\n        if (totalSupply > maxTotalSupply) revert SurpassMaxDepositSupply();\n\n        uint256 _balanceBefore = balanceOf[account_];\n        unchecked {\n            balanceOf[account_] = _balanceBefore + amount_;\n        }\n\n        emit Transfer(address(0), account_, amount_);\n\n        // Add this token to the deposit tokens list if the recipient is receiving it for the 1st time\n        if (_balanceBefore == 0 && amount_ > 0) {\n            pool.addToDepositTokensOfAccount(account_);\n        }\n    }\n\n    /// @inheritdoc TokenHolder\n    // solhint-disable-next-line no-empty-blocks\n    function _requireCanSweep() internal view override onlyGovernor {}\n\n    /**\n     * @notice Move `amount` of tokens from `sender` to `recipient`\n     */\n    function _transfer(\n        address sender_,\n        address recipient_,\n        uint256 amount_\n    ) private updateRewardsBeforeTransfer(sender_, recipient_) {\n        if (sender_ == address(0)) revert TransferFromTheZeroAddress();\n        if (recipient_ == address(0)) revert TransferToTheZeroAddress();\n\n        uint256 _senderBalanceBefore = balanceOf[sender_];\n        if (_senderBalanceBefore < amount_) revert TransferAmountExceedsBalance();\n        uint256 _recipientBalanceBefore = balanceOf[recipient_];\n\n        unchecked {\n            balanceOf[sender_] = _senderBalanceBefore - amount_;\n            balanceOf[recipient_] += amount_;\n        }\n\n        emit Transfer(sender_, recipient_, amount_);\n\n        // Add this token to the deposit tokens list if the recipient is receiving it for the 1st time\n        if (_recipientBalanceBefore == 0 && amount_ > 0) {\n            pool.addToDepositTokensOfAccount(recipient_);\n        }\n\n        // Remove this token from the deposit tokens list if the sender's balance goes to zero\n        if (amount_ > 0 && balanceOf[sender_] == 0) {\n            pool.removeFromDepositTokensOfAccount(sender_);\n        }\n    }\n\n    /**\n     * @notice Burn msdTOKEN, withdraw collateral and transfer to `_msgSender()` (i.e. Pool)\n     * @dev This function doesn't check if the amount is unlocked!\n     * @param account_ The account where deposit token will be burnt from\n     * @param amount_ The amount of collateral to withdraw\n     * @param to_ The account that will receive withdrawn collateral\n     * @return _withdrawn The amount withdrawn after fees\n     */\n    function _withdraw(\n        address account_,\n        uint256 amount_,\n        address to_\n    ) private whenNotShutdown nonReentrant onlyIfDepositTokenExists returns (uint256 _withdrawn, uint256 _fee) {\n        if (amount_ == 0) revert AmountIsZero();\n\n        IPool _pool = pool;\n\n        (_withdrawn, _fee) = quoteWithdrawOut(amount_);\n        if (_fee > 0) {\n            _transfer(account_, _pool.feeCollector(), _fee);\n        }\n\n        _burn(account_, _withdrawn);\n        _pool.treasury().pull(to_, _withdrawn);\n\n        emit CollateralWithdrawn(account_, to_, amount_, _withdrawn, _fee);\n    }\n\n    /**\n     * @notice Enable/Disable the Deposit Token\n     */\n    function toggleIsActive() external override onlyGovernor {\n        bool _newIsActive = !isActive;\n        emit DepositTokenActiveUpdated(_newIsActive);\n        isActive = _newIsActive;\n    }\n\n    /**\n     * @notice Update collateral factor\n     * @param newCollateralFactor_ The new CF value\n     */\n    function updateCollateralFactor(uint128 newCollateralFactor_) external override onlyGovernor {\n        if (newCollateralFactor_ == 0) revert CollateralFactorTooLow();\n        if (newCollateralFactor_ >= 1e18) revert CollateralFactorTooHigh();\n        // Note: The `CF * (1 + liquidationFees) < 1` invariant must hold, with a margin (see the constant)\n        (uint256 _liquidatorIncentive, uint256 _protocolFee) = pool.feeProvider().liquidationFees();\n        if (newCollateralFactor_ * (1e18 + _liquidatorIncentive + _protocolFee) >= MAX_CF_TIMES_LIQUIDATION_FEES) {\n            revert CollateralFactorTooHigh();\n        }\n        uint256 _currentCollateralFactor = collateralFactor;\n        if (newCollateralFactor_ == _currentCollateralFactor) revert NewValueIsSameAsCurrent();\n        emit CollateralFactorUpdated(_currentCollateralFactor, newCollateralFactor_);\n        collateralFactor = newCollateralFactor_;\n    }\n\n    /**\n     * @notice Update max total supply\n     * @param newMaxTotalSupply_ The new max total supply\n     */\n    function updateMaxTotalSupply(uint256 newMaxTotalSupply_) external override onlyGovernor {\n        uint256 _currentMaxTotalSupply = maxTotalSupply;\n        if (newMaxTotalSupply_ == _currentMaxTotalSupply) revert NewValueIsSameAsCurrent();\n        emit MaxTotalSupplyUpdated(_currentMaxTotalSupply, newMaxTotalSupply_);\n        maxTotalSupply = newMaxTotalSupply_;\n    }\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/token/ERC20/extensions/IERC20Metadata.sol","source_code":"// SPDX-License-Identifier: MIT\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":"contracts/dependencies/openzeppelin/utils/cryptography/MerkleProof.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Trees proofs.\n *\n * The proofs can be generated using the JavaScript library\n * https://github.com/miguelmota/merkletreejs[merkletreejs].\n * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.\n *\n * See `test/utils/cryptography/MerkleProof.test.js` for some examples.\n */\nlibrary MerkleProof {\n    /**\n     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n     * defined by `root`. For this, a `proof` must be provided, containing\n     * sibling hashes on the branch from the leaf to the root of the tree. Each\n     * pair of leaves and each pair of pre-images are assumed to be sorted.\n     */\n    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n        bytes32 computedHash = leaf;\n\n        for (uint256 i = 0; i < proof.length; i++) {\n            bytes32 proofElement = proof[i];\n\n            if (computedHash <= proofElement) {\n                // Hash(current computed hash + current element of the proof)\n                computedHash = keccak256(abi.encodePacked(computedHash, proofElement));\n            } else {\n                // Hash(current element of the proof + current computed hash)\n                computedHash = keccak256(abi.encodePacked(proofElement, computedHash));\n            }\n        }\n\n        // Check if the computed hash (root) is equal to the provided root\n        return computedHash == root;\n    }\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/token/oft/IOFT.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\nimport \"./IOFTCore.sol\";\nimport \"../../../../openzeppelin/token/ERC20/IERC20.sol\";\n\n/**\n * @dev Interface of the OFT standard\n */\ninterface IOFT is IOFTCore, IERC20 {\n\n}\n"},{"file_path":"contracts/storage/AMOStorage.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {EnumerableSet} from \"../dependencies/openzeppelin/utils/structs/EnumerableSet.sol\";\nimport {IPoolRegistry} from \"../interfaces/IPoolRegistry.sol\";\n\ncontract AMOStorage {\n    /**\n     * @notice The Pool Registry\n     */\n    IPoolRegistry internal _poolRegistry;\n\n    /**\n     * @dev Direct deposit keepers\n     */\n    EnumerableSet.AddressSet internal keepers;\n\n    /**\n     * @dev Authorized Vesper Pools\n     */\n    mapping(address => address) public vPools;\n}\n"},{"file_path":"contracts/mock/PoolMock.sol","source_code":"// SPDX-License-Identifier: MIT\n\n// solhint-disable no-unused-vars\n// solhint-disable avoid-low-level-calls\n// solhint-disable use-forbidden-name\n// solhint-disable no-empty-blocks\n\npragma solidity 0.8.24;\n\nimport {IERC20} from \"../dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {WadRayMath} from \"../lib/WadRayMath.sol\";\nimport {Pauseable} from \"../utils/Pauseable.sol\";\nimport {IPool} from \"../interfaces/IPool.sol\";\nimport {ITreasury} from \"../interfaces/ITreasury.sol\";\nimport {ISyntheticToken} from \"../interfaces/ISyntheticToken.sol\";\nimport {IDebtToken} from \"../interfaces/IDebtToken.sol\";\nimport {IDepositToken} from \"../interfaces/IDepositToken.sol\";\nimport {IPoolRegistry} from \"../interfaces/IPoolRegistry.sol\";\nimport {ISmartFarmingManager} from \"../interfaces/ISmartFarmingManager.sol\";\nimport {IMasterOracle} from \"../interfaces/external/IMasterOracle.sol\";\nimport {IFeeProvider} from \"../interfaces/IFeeProvider.sol\";\nimport {Governable} from \"../access/Governable.sol\";\n\ncontract PoolMock is IPool, Governable, Pauseable {\n    using WadRayMath for uint256;\n\n    ITreasury public treasury;\n    ISyntheticToken public syntheticToken;\n    IDebtToken public debtToken;\n    IDepositToken public depositToken;\n    IMasterOracle public masterOracle;\n    IPoolRegistry public poolRegistry;\n    IFeeProvider public feeProvider;\n    ISmartFarmingManager public smartFarmingManager;\n    uint256 public debtFloorInUsd;\n    uint256 public maxLiquidable;\n    bool public isSwapActive;\n\n    constructor(\n        IDepositToken _depositToken,\n        IMasterOracle _masterOracle,\n        ISyntheticToken _syntheticToken,\n        IDebtToken _debtToken,\n        IPoolRegistry _poolRegistry,\n        IFeeProvider _feeProvider\n    ) {\n        depositToken = _depositToken;\n        masterOracle = _masterOracle;\n        syntheticToken = _syntheticToken;\n        debtToken = _debtToken;\n        poolRegistry = _poolRegistry;\n        feeProvider = _feeProvider;\n    }\n\n    function feeCollector() external view returns (address) {\n        return poolRegistry.feeCollector();\n    }\n\n    function getDepositTokens() external pure override returns (address[] memory) {\n        revert(\"mock-does-not-implement\");\n    }\n\n    function getDebtTokens() external pure override returns (address[] memory) {\n        revert(\"mock-does-not-implement\");\n    }\n\n    function debtOf(address _account) public view override returns (uint256 _debtInUsd) {\n        if (address(syntheticToken) != address(0)) {\n            uint256 _debtBalance = debtToken.balanceOf(_account);\n            return masterOracle.quoteTokenToUsd(address(syntheticToken), _debtBalance);\n        }\n    }\n\n    function depositOf(address) external pure override returns (uint256, uint256) {\n        revert(\"mock-does-not-implement\");\n    }\n\n    function debtPositionOf(\n        address _account\n    )\n        public\n        view\n        override\n        returns (\n            bool _isHealthy,\n            uint256 _depositInUsd,\n            uint256 _debtInUsd,\n            uint256 _issuableLimitInUsd,\n            uint256 _issuableInUsd\n        )\n    {\n        _isHealthy = true;\n        uint256 _deposit = depositToken.balanceOf(_account);\n        _depositInUsd = masterOracle.quoteTokenToUsd(address(depositToken.underlying()), _deposit);\n        _debtInUsd = debtOf(_account);\n        _issuableLimitInUsd = _depositInUsd.wadMul(depositToken.collateralFactor());\n        _issuableInUsd = _debtInUsd < _issuableLimitInUsd ? _issuableLimitInUsd - _debtInUsd : 0;\n    }\n\n    function liquidate(\n        ISyntheticToken,\n        address,\n        uint256,\n        IDepositToken\n    ) external pure override returns (uint256, uint256, uint256) {\n        revert(\"mock-does-not-implement\");\n    }\n\n    function quoteLiquidateIn(\n        ISyntheticToken,\n        uint256,\n        IDepositToken\n    ) external pure returns (uint256, uint256, uint256) {\n        revert(\"mock-does-not-implement\");\n    }\n\n    function quoteLiquidateMax(ISyntheticToken, address, IDepositToken) external pure returns (uint256) {\n        revert(\"mock-does-not-implement\");\n    }\n\n    function quoteLiquidateOut(\n        ISyntheticToken,\n        uint256,\n        IDepositToken\n    ) external pure returns (uint256, uint256, uint256) {\n        revert(\"mock-does-not-implement\");\n    }\n\n    function quoteSwapIn(ISyntheticToken, ISyntheticToken, uint256) external pure override returns (uint256, uint256) {\n        revert(\"mock-does-not-implement\");\n    }\n\n    function quoteSwapOut(ISyntheticToken, ISyntheticToken, uint256) public pure override returns (uint256, uint256) {\n        revert(\"mock-does-not-implement\");\n    }\n\n    function swap(ISyntheticToken, ISyntheticToken, uint256) external pure override returns (uint256, uint256) {\n        revert(\"mock-does-not-implement\");\n    }\n\n    function updateDebtFloor(uint256 _newDebtFloorInUsd) external {\n        debtFloorInUsd = _newDebtFloorInUsd;\n    }\n\n    function doesSyntheticTokenExist(ISyntheticToken _syntheticToken) external view override returns (bool) {\n        return address(_syntheticToken) == address(syntheticToken);\n    }\n\n    function doesDebtTokenExist(IDebtToken) external pure returns (bool) {\n        return true;\n    }\n\n    function doesDepositTokenExist(IDepositToken) external pure override returns (bool) {\n        return true;\n    }\n\n    function updateTreasury(ITreasury _treasury) external {\n        treasury = _treasury;\n    }\n\n    function debtTokenOf(ISyntheticToken) external view override returns (IDebtToken) {\n        return debtToken;\n    }\n\n    function depositTokenOf(IERC20) external view override returns (IDepositToken) {\n        return depositToken;\n    }\n\n    function addToDepositTokensOfAccount(address) external pure override {}\n\n    function removeFromDepositTokensOfAccount(address) external pure override {}\n\n    function addToDebtTokensOfAccount(address) external pure override {}\n\n    function removeFromDebtTokensOfAccount(address) external pure override {}\n\n    function getDepositTokensOfAccount(address) external pure override returns (address[] memory) {\n        revert(\"mock-does-not-implement\");\n    }\n\n    function getDebtTokensOfAccount(address) external pure override returns (address[] memory) {\n        revert(\"mock-does-not-implement\");\n    }\n\n    function getRewardsDistributors() external pure override returns (address[] memory _rewardsDistributors) {}\n\n    function isGuardian(address /*sender_*/) public view override returns (bool) {\n        revert(\"mock-does-not-implement\");\n    }\n\n    function isBridgingActive() external view returns (bool) {\n        revert(\"mock-does-not-implement\");\n    }\n}\n"},{"file_path":"contracts/lib/MappedEnumerableSet.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\n/**\n * @dev EnumerableSet fork to support `address => address[]` mapping\n * @dev Forked from OZ 4.3.2\n */\nlibrary MappedEnumerableSet {\n    struct Set {\n        // Storage of set values\n        address[] _values;\n        // Position of the value in the `values` array, plus 1 because index 0\n        // means a value is not in the set.\n        mapping(address => uint256) _indexes;\n    }\n\n    struct AddressSet {\n        mapping(address => Set) _ofAddress;\n    }\n\n    function _add(AddressSet storage set, address _key, address value) private returns (bool) {\n        if (!_contains(set, _key, value)) {\n            set._ofAddress[_key]._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._ofAddress[_key]._indexes[value] = set._ofAddress[_key]._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    function _remove(AddressSet storage set, address _key, address value) private returns (bool) {\n        // We read and store the value's index to prevent multiple reads from the same storage slot\n        uint256 valueIndex = set._ofAddress[_key]._indexes[value];\n\n        if (valueIndex != 0) {\n            // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 toDeleteIndex = valueIndex - 1;\n            uint256 lastIndex = set._ofAddress[_key]._values.length - 1;\n\n            if (lastIndex != toDeleteIndex) {\n                address lastvalue = set._ofAddress[_key]._values[lastIndex];\n\n                // Move the last value to the index where the value to delete is\n                set._ofAddress[_key]._values[toDeleteIndex] = lastvalue;\n                // Update the index for the moved value\n                set._ofAddress[_key]._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex\n            }\n\n            // Delete the slot where the moved value was stored\n            set._ofAddress[_key]._values.pop();\n\n            // Delete the index for the deleted slot\n            delete set._ofAddress[_key]._indexes[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    function _contains(AddressSet storage set, address _key, address value) private view returns (bool) {\n        return set._ofAddress[_key]._indexes[value] != 0;\n    }\n\n    function _length(AddressSet storage set, address _key) private view returns (uint256) {\n        return set._ofAddress[_key]._values.length;\n    }\n\n    function _at(AddressSet storage set, address _key, uint256 index) private view returns (address) {\n        return set._ofAddress[_key]._values[index];\n    }\n\n    function _values(AddressSet storage set, address _key) private view returns (address[] memory) {\n        return set._ofAddress[_key]._values;\n    }\n\n    function add(AddressSet storage set, address key, address value) internal returns (bool) {\n        return _add(set, key, value);\n    }\n\n    function remove(AddressSet storage set, address key, address value) internal returns (bool) {\n        return _remove(set, key, value);\n    }\n\n    function contains(AddressSet storage set, address key, address value) internal view returns (bool) {\n        return _contains(set, key, value);\n    }\n\n    function length(AddressSet storage set, address key) internal view returns (uint256) {\n        return _length(set, key);\n    }\n\n    function at(AddressSet storage set, address key, uint256 index) internal view returns (address) {\n        return _at(set, key, index);\n    }\n\n    function values(AddressSet storage set, address key) internal view returns (address[] memory) {\n        address[] memory store = _values(set, key);\n        address[] memory result;\n\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n}\n"},{"file_path":"contracts/dependencies/openzeppelin-upgradeable/utils/introspection/ERC165Upgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165Upgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {\n    function __ERC165_init() internal onlyInitializing {\n    }\n\n    function __ERC165_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IERC165Upgradeable).interfaceId;\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":"contracts/dependencies/stargate-protocol/interfaces/IStargateComposer.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.9;\n\nimport \"./IStargateRouter.sol\";\n\ninterface IStargateComposer {\n    function swap(\n        uint16 _dstChainId,\n        uint256 _srcPoolId,\n        uint256 _dstPoolId,\n        address payable _refundAddress,\n        uint256 _amountLD,\n        uint256 _minAmountLD,\n        IStargateRouter.lzTxObj memory _lzTxParams,\n        bytes calldata _to,\n        bytes calldata _payload\n    ) external payable;\n\n    function factory() external view returns (address);\n\n    function stargateBridge() external view returns (address);\n\n    function stargateRouter() external view returns (IStargateRouter);\n\n    function quoteLayerZeroFee(\n        uint16 _dstChainId,\n        uint8 _functionType,\n        bytes calldata _toAddress,\n        bytes calldata _transferAndCallPayload,\n        IStargateRouter.lzTxObj memory _lzTxParams\n    ) external view returns (uint256, uint256);\n\n    function peers(uint16 _chainId) external view returns (address);\n\n    function payloadHashes(\n        uint16 _srcChainId,\n        bytes calldata _srcAddress,\n        uint256 _nonce\n    ) external view returns (bytes32);\n\n    function clearCachedSwap(\n        uint16 _srcChainId,\n        bytes calldata _srcAddress,\n        uint64 _nonce,\n        address _receiver,\n        bytes calldata _sgReceiveCallData\n    ) external;\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/contracts-upgradeable/token/oft/composable/IOFTReceiverUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\ninterface IOFTReceiverUpgradeable {\n    /**\n     * @dev Called by the OFT contract when tokens are received from source chain.\n     * @param _srcChainId The chain id of the source chain.\n     * @param _srcAddress The address of the OFT token contract on the source chain.\n     * @param _nonce The nonce of the transaction on the source chain.\n     * @param _from The address of the account who calls the sendAndCall() on the source chain.\n     * @param _amount The amount of tokens to transfer.\n     * @param _payload Additional data with no specified format.\n     */\n    function onOFTReceived(\n        uint16 _srcChainId,\n        bytes calldata _srcAddress,\n        uint64 _nonce,\n        bytes calldata _from,\n        uint _amount,\n        bytes calldata _payload\n    ) external;\n}\n"},{"file_path":"contracts/storage/PoolStorage.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IERC20} from \"../dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {EnumerableSet} from \"../dependencies/openzeppelin/utils/structs/EnumerableSet.sol\";\nimport {MappedEnumerableSet} from \"../lib/MappedEnumerableSet.sol\";\nimport {ISwapper} from \"../interfaces/external/ISwapper.sol\";\nimport {IPool} from \"../interfaces/IPool.sol\";\nimport {ISmartFarmingManager} from \"../interfaces/ISmartFarmingManager.sol\";\nimport {IPoolRegistry} from \"../interfaces/IPoolRegistry.sol\";\nimport {ITreasury} from \"../interfaces/ITreasury.sol\";\nimport {IDepositToken} from \"../interfaces/IDepositToken.sol\";\nimport {IRewardsDistributor} from \"../interfaces/IRewardsDistributor.sol\";\nimport {ISyntheticToken} from \"../interfaces/ISyntheticToken.sol\";\nimport {IDebtToken} from \"../interfaces/IDebtToken.sol\";\nimport {IFeeProvider} from \"../interfaces/IFeeProvider.sol\";\n\n// solhint-disable var-name-mixedcase, max-states-count\nabstract contract PoolStorageV1 is IPool {\n    /**\n     * @notice The debt floor (in USD) for each synthetic token\n     * This parameters is used to keep incentive for liquidators (i.e. cover gas and provide enough profit)\n     */\n    uint256 public override debtFloorInUsd;\n\n    uint256 private depositFee__DEPRECATED;\n\n    uint256 private issueFee__DEPRECATED;\n\n    uint256 private withdrawFee__DEPRECATED;\n\n    uint256 private repayFee__DEPRECATED;\n\n    uint256 private swapFee__DEPRECATED;\n\n    uint256 private liquidationFees__DEPRECATED;\n\n    /**\n     * @notice The max percent of the debt allowed to liquidate\n     * @dev Use 18 decimals (e.g. 1e16 = 1%)\n     */\n    uint256 public override maxLiquidable;\n\n    /**\n     * @notice PoolRegistry\n     */\n    IPoolRegistry internal _poolRegistry;\n\n    /**\n     * @notice Swap feature on/off flag\n     */\n    bool public override isSwapActive;\n\n    /**\n     * @notice Treasury contract\n     */\n    ITreasury public override treasury;\n\n    /**\n     * @notice Represents collateral's deposits\n     */\n    EnumerableSet.AddressSet internal depositTokens;\n\n    /**\n     * @notice Get the deposit token's address from given underlying asset\n     */\n    mapping(IERC20 => IDepositToken) public override depositTokenOf;\n\n    /**\n     * @notice Available debt tokens\n     */\n    EnumerableSet.AddressSet internal debtTokens;\n\n    /**\n     * @notice Per-account deposit tokens (i.e. tokens that user has balance > 0)\n     */\n    MappedEnumerableSet.AddressSet internal depositTokensOfAccount;\n\n    /**\n     * @notice Per-account debt tokens (i.e. tokens that user has balance > 0)\n     */\n    MappedEnumerableSet.AddressSet internal debtTokensOfAccount;\n\n    /**\n     * @notice RewardsDistributor contracts\n     */\n    IRewardsDistributor[] internal rewardsDistributors__DEPRECATED;\n\n    /**\n     * @notice Get the debt token's address from given synthetic asset\n     */\n    mapping(ISyntheticToken => IDebtToken) public override debtTokenOf;\n}\n\nabstract contract PoolStorageV2 is PoolStorageV1 {\n    ISwapper private swapper__DEPRECATED;\n\n    /**\n     * @notice FeeProvider contract\n     */\n    IFeeProvider public override feeProvider;\n\n    /**\n     * @notice RewardsDistributor contracts\n     */\n    EnumerableSet.AddressSet internal rewardsDistributors;\n}\n\nabstract contract PoolStorageV3 is PoolStorageV2 {\n    /**\n     * @notice SmartFarmingManager contract\n     */\n    ISmartFarmingManager public smartFarmingManager;\n}\n\nabstract contract PoolStorageV4 is PoolStorageV3 {\n    /**\n     * @notice Flag that pause/unpause pool's cross-chain activities\n     */\n    bool private isBridgingActive_DEPRECATED;\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/util/ExcessivelySafeCall.sol","source_code":"// SPDX-License-Identifier: MIT OR Apache-2.0\npragma solidity >=0.7.6;\n\nlibrary ExcessivelySafeCall {\n    uint256 constant LOW_28_MASK = 0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\n\n    /// @notice Use when you _really_ really _really_ don't trust the called\n    /// contract. This prevents the called contract from causing reversion of\n    /// the caller in as many ways as we can.\n    /// @dev The main difference between this and a solidity low-level call is\n    /// that we limit the number of bytes that the callee can cause to be\n    /// copied to caller memory. This prevents stupid things like malicious\n    /// contracts returning 10,000,000 bytes causing a local OOG when copying\n    /// to memory.\n    /// @param _target The address to call\n    /// @param _gas The amount of gas to forward to the remote contract\n    /// @param _maxCopy The maximum number of bytes of returndata to copy\n    /// to memory.\n    /// @param _calldata The data to send to the remote contract\n    /// @return success and returndata, as `.call()`. Returndata is capped to\n    /// `_maxCopy` bytes.\n    function excessivelySafeCall(\n        address _target,\n        uint256 _gas,\n        uint16 _maxCopy,\n        bytes memory _calldata\n    ) internal returns (bool, bytes memory) {\n        // set up for assembly call\n        uint256 _toCopy;\n        bool _success;\n        bytes memory _returnData = new bytes(_maxCopy);\n        // dispatch message to recipient\n        // by assembly calling \"handle\" function\n        // we call via assembly to avoid memcopying a very large returndata\n        // returned by a malicious contract\n        assembly {\n            _success := call(\n                _gas, // gas\n                _target, // recipient\n                0, // ether value\n                add(_calldata, 0x20), // inloc\n                mload(_calldata), // inlen\n                0, // outloc\n                0 // outlen\n            )\n            // limit our copy to 256 bytes\n            _toCopy := returndatasize()\n            if gt(_toCopy, _maxCopy) {\n                _toCopy := _maxCopy\n            }\n            // Store the length of the copied bytes\n            mstore(_returnData, _toCopy)\n            // copy the bytes from returndata[0:_toCopy]\n            returndatacopy(add(_returnData, 0x20), 0, _toCopy)\n        }\n        return (_success, _returnData);\n    }\n\n    /// @notice Use when you _really_ really _really_ don't trust the called\n    /// contract. This prevents the called contract from causing reversion of\n    /// the caller in as many ways as we can.\n    /// @dev The main difference between this and a solidity low-level call is\n    /// that we limit the number of bytes that the callee can cause to be\n    /// copied to caller memory. This prevents stupid things like malicious\n    /// contracts returning 10,000,000 bytes causing a local OOG when copying\n    /// to memory.\n    /// @param _target The address to call\n    /// @param _gas The amount of gas to forward to the remote contract\n    /// @param _maxCopy The maximum number of bytes of returndata to copy\n    /// to memory.\n    /// @param _calldata The data to send to the remote contract\n    /// @return success and returndata, as `.call()`. Returndata is capped to\n    /// `_maxCopy` bytes.\n    function excessivelySafeStaticCall(\n        address _target,\n        uint256 _gas,\n        uint16 _maxCopy,\n        bytes memory _calldata\n    ) internal view returns (bool, bytes memory) {\n        // set up for assembly call\n        uint256 _toCopy;\n        bool _success;\n        bytes memory _returnData = new bytes(_maxCopy);\n        // dispatch message to recipient\n        // by assembly calling \"handle\" function\n        // we call via assembly to avoid memcopying a very large returndata\n        // returned by a malicious contract\n        assembly {\n            _success := staticcall(\n                _gas, // gas\n                _target, // recipient\n                add(_calldata, 0x20), // inloc\n                mload(_calldata), // inlen\n                0, // outloc\n                0 // outlen\n            )\n            // limit our copy to 256 bytes\n            _toCopy := returndatasize()\n            if gt(_toCopy, _maxCopy) {\n                _toCopy := _maxCopy\n            }\n            // Store the length of the copied bytes\n            mstore(_returnData, _toCopy)\n            // copy the bytes from returndata[0:_toCopy]\n            returndatacopy(add(_returnData, 0x20), 0, _toCopy)\n        }\n        return (_success, _returnData);\n    }\n\n    /**\n     * @notice Swaps function selectors in encoded contract calls\n     * @dev Allows reuse of encoded calldata for functions with identical\n     * argument types but different names. It simply swaps out the first 4 bytes\n     * for the new selector. This function modifies memory in place, and should\n     * only be used with caution.\n     * @param _newSelector The new 4-byte selector\n     * @param _buf The encoded contract args\n     */\n    function swapSelector(bytes4 _newSelector, bytes memory _buf) internal pure {\n        require(_buf.length >= 4);\n        uint256 _mask = LOW_28_MASK;\n        assembly {\n            // load the first word of\n            let _word := mload(add(_buf, 0x20))\n            // mask out the top 4 bytes\n            // /x\n            _word := and(_word, _mask)\n            _word := or(_newSelector, _word)\n            mstore(add(_buf, 0x20), _word)\n        }\n    }\n}\n"},{"file_path":"contracts/interfaces/IDebtToken.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IERC20Metadata} from \"../dependencies/openzeppelin/token/ERC20/extensions/IERC20Metadata.sol\";\nimport {ISyntheticToken} from \"./ISyntheticToken.sol\";\n\ninterface IDebtToken is IERC20Metadata {\n    function lastTimestampAccrued() external view returns (uint256);\n\n    function isActive() external view returns (bool);\n\n    function syntheticToken() external view returns (ISyntheticToken);\n\n    function accrueInterest() external;\n\n    function debtIndex() external returns (uint256 debtIndex_);\n\n    function burnFor(address from_, uint256 amount_) external;\n\n    function issue(uint256 amount_, address to_) external returns (uint256 _issued, uint256 _fee);\n\n    function flashIssue(address to_, uint256 amount_) external returns (uint256 _issued, uint256 _fee);\n\n    function mint(address to_, uint256 amount_) external;\n\n    function repay(address onBehalfOf_, uint256 amount_) external returns (uint256 _repaid, uint256 _fee);\n\n    function repayAll(address onBehalfOf_) external returns (uint256 _repaid, uint256 _fee);\n\n    function quoteIssueIn(uint256 amountToIssue_) external view returns (uint256 _amount, uint256 _fee);\n\n    function quoteIssueOut(uint256 amount_) external view returns (uint256 _amountToIssue, uint256 _fee);\n\n    function quoteRepayIn(uint256 amountToRepay_) external view returns (uint256 _amount, uint256 _fee);\n\n    function quoteRepayOut(uint256 amount_) external view returns (uint256 _amountToRepay, uint256 _fee);\n\n    function updateMaxTotalSupply(uint256 newMaxTotalSupply_) external;\n\n    function updateInterestRate(uint256 newInterestRate_) external;\n\n    function maxTotalSupply() external view returns (uint256);\n\n    function interestRate() external view returns (uint256);\n\n    function interestRatePerSecond() external view returns (uint256);\n\n    function toggleIsActive() external;\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/proxy/utils/Initializable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/Address.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 * ```\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\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. Equivalent to `reinitializer(1)`.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = _setInitializedVersion(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     * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n     * initialization step. This is essential to configure modules that are added through upgrades and that require\n     * initialization.\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    modifier reinitializer(uint8 version) {\n        bool isTopLevelCall = _setInitializedVersion(version);\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(version);\n        }\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    function _disableInitializers() internal virtual {\n        _setInitializedVersion(type(uint8).max);\n    }\n\n    function _setInitializedVersion(uint8 version) private returns (bool) {\n        // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n        // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level\n        // of initializers, because in other contexts the contract may have been reentered.\n        if (_initializing) {\n            require(\n                version == 1 && !Address.isContract(address(this)),\n                \"Initializable: contract is already initialized\"\n            );\n            return false;\n        } else {\n            require(_initialized < version, \"Initializable: contract is already initialized\");\n            _initialized = version;\n            return true;\n        }\n    }\n}\n"},{"file_path":"contracts/interfaces/INativeTokenGateway.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IPool} from \"./IPool.sol\";\n\ninterface INativeTokenGateway {\n    function deposit(IPool pool_) external payable;\n\n    function withdraw(IPool pool_, uint256 amount_) external;\n}\n"},{"file_path":"contracts/interfaces/IOperator.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\ninterface IOperator {\n    struct Call {\n        address target;\n        uint256 value;\n        bytes callData;\n    }\n\n    function getActualMsgSender() external view returns (address);\n\n    function execute(Call[] calldata calls_) external payable returns (bytes[] memory _returnData);\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/contracts-upgradeable/token/oft/IOFTCoreUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.2;\n\nimport \"../../../../../openzeppelin-upgradeable/utils/introspection/IERC165Upgradeable.sol\";\n\n/**\n * @dev Interface of the IOFT core standard\n */\ninterface IOFTCoreUpgradeable is IERC165Upgradeable {\n    /**\n     * @dev estimate send token `_tokenId` to (`_dstChainId`, `_toAddress`)\n     * _dstChainId - L0 defined chain id to send tokens too\n     * _toAddress - dynamic bytes array which contains the address to whom you are sending tokens to on the dstChain\n     * _amount - amount of the tokens to transfer\n     * _useZro - indicates to use zro to pay L0 fees\n     * _adapterParam - flexible bytes array to indicate messaging adapter services in L0\n     */\n    function estimateSendFee(\n        uint16 _dstChainId,\n        bytes calldata _toAddress,\n        uint _amount,\n        bool _useZro,\n        bytes calldata _adapterParams\n    ) external view returns (uint nativeFee, uint zroFee);\n\n    /**\n     * @dev send `_amount` amount of token to (`_dstChainId`, `_toAddress`) from `_from`\n     * `_from` the owner of token\n     * `_dstChainId` the destination chain identifier\n     * `_toAddress` can be any size depending on the `dstChainId`.\n     * `_amount` the quantity of tokens in wei\n     * `_refundAddress` the address LayerZero refunds if too much message fee is sent\n     * `_zroPaymentAddress` set to address(0x0) if not paying in ZRO (LayerZero Token)\n     * `_adapterParams` is a flexible bytes array to indicate messaging adapter services\n     */\n    function sendFrom(\n        address _from,\n        uint16 _dstChainId,\n        bytes calldata _toAddress,\n        uint _amount,\n        address payable _refundAddress,\n        address _zroPaymentAddress,\n        bytes calldata _adapterParams\n    ) external payable;\n\n    /**\n     * @dev returns the circulating amount of tokens on current chain\n     */\n    function circulatingSupply() external view returns (uint);\n\n    /**\n     * @dev returns the address of the ERC20 token\n     */\n    function token() external view returns (address);\n\n    /**\n     * @dev Emitted when `_amount` tokens are moved from the `_sender` to (`_dstChainId`, `_toAddress`)\n     * `_nonce` is the outbound nonce\n     */\n    event SendToChain(uint16 indexed _dstChainId, address indexed _from, bytes _toAddress, uint _amount);\n\n    /**\n     * @dev Emitted when `_amount` tokens are received from `_srcChainId` into the `_toAddress` on the local chain.\n     * `_nonce` is the inbound nonce.\n     */\n    event ReceiveFromChain(uint16 indexed _srcChainId, address indexed _to, uint _amount);\n\n    event SetUseCustomAdapterParams(bool _useCustomAdapterParams);\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/access/Ownable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.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 Ownable is Context {\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    constructor() {\n        _transferOwnership(_msgSender());\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 called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n        _;\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing 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"},{"file_path":"contracts/mock/PoolRewardsMock.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IERC20} from \"../dependencies/openzeppelin/token/ERC20/IERC20.sol\";\n\ncontract PoolRewardsMock {\n    address[] public rewardTokens;\n\n    function updateReward(address) external {}\n\n    function getRewardTokens() external view returns (address[] memory) {\n        return rewardTokens;\n    }\n\n    function claimReward(address) external {\n        for (uint256 i; i < rewardTokens.length; ++i) {\n            uint256 _balance = IERC20(rewardTokens[i]).balanceOf(address(this));\n            if (_balance > 0) {\n                IERC20(rewardTokens[i]).transfer(msg.sender, _balance);\n            }\n        }\n    }\n\n    function setRewardTokens(address[] memory rewardTokens_) external {\n        rewardTokens = rewardTokens_;\n    }\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/token/oft/composable/ComposableProxyOFT.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./ComposableOFTCore.sol\";\nimport \"../../../../../openzeppelin/token/ERC20/utils/SafeERC20.sol\";\n\ncontract ComposableProxyOFT is ComposableOFTCore {\n    using SafeERC20 for IERC20;\n\n    IERC20 internal immutable innerToken;\n\n    constructor(address _lzEndpoint, address _proxyToken) ComposableOFTCore(_lzEndpoint) {\n        innerToken = IERC20(_proxyToken);\n    }\n\n    function circulatingSupply() public view virtual override returns (uint) {\n        unchecked {\n            return innerToken.totalSupply() - innerToken.balanceOf(address(this));\n        }\n    }\n\n    function token() public view virtual override returns (address) {\n        return address(innerToken);\n    }\n\n    function _debitFrom(address _from, uint16, bytes memory, uint _amount) internal virtual override returns (uint) {\n        require(_from == _msgSender(), \"ComposableProxyOFT: owner is not send caller\");\n        uint before = innerToken.balanceOf(address(this));\n        innerToken.safeTransferFrom(_from, address(this), _amount);\n        return innerToken.balanceOf(address(this)) - before;\n    }\n\n    function _creditTo(uint16, address _toAddress, uint _amount) internal virtual override returns (uint) {\n        uint before = innerToken.balanceOf(_toAddress);\n        innerToken.safeTransfer(_toAddress, _amount);\n        return innerToken.balanceOf(_toAddress) - before;\n    }\n}\n"},{"file_path":"contracts/Treasury.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {Initializable} from \"./dependencies/openzeppelin-upgradeable/proxy/utils/Initializable.sol\";\nimport {IERC20} from \"./dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {ReentrancyGuardDeprecated} from \"./utils/ReentrancyGuardDeprecated.sol\";\nimport {ReentrancyGuardTransient} from \"./utils/ReentrancyGuardTransient.sol\";\nimport {SafeERC20} from \"./dependencies/openzeppelin/token/ERC20/utils/SafeERC20.sol\";\nimport {Manageable} from \"./access/Manageable.sol\";\nimport {IVPool} from \"./interfaces/external/IVPool.sol\";\nimport {IPoolRewards} from \"./interfaces/external/IPoolRewards.sol\";\nimport {IDepositToken} from \"./interfaces/IDepositToken.sol\";\nimport {IPool} from \"./interfaces/IPool.sol\";\nimport {TreasuryStorageV1} from \"./storage/TreasuryStorage.sol\";\n\nerror SenderIsNotDepositToken();\nerror AddressIsNull();\nerror RecipientIsNull();\nerror AmountIsZero();\n\n/**\n * @title Treasury contract\n */\ncontract Treasury is Initializable, ReentrancyGuardDeprecated, ReentrancyGuardTransient, Manageable, TreasuryStorageV1 {\n    using SafeERC20 for IERC20;\n    using SafeERC20 for IDepositToken;\n\n    string public constant VERSION = \"1.4.1\";\n\n    constructor() {\n        _disableInitializers();\n    }\n\n    function initialize(IPool pool_) external initializer {\n        __Manageable_init(pool_);\n    }\n\n    /**\n     * @notice Transfer all funds to another contract\n     * @dev This function can become too expensive depending on the length of the arrays\n     * @param newTreasury_ The new treasury\n     */\n    function migrateTo(address newTreasury_) external override onlyPool {\n        if (newTreasury_ == address(0)) revert AddressIsNull();\n\n        address[] memory _depositTokens = pool.getDepositTokens();\n        uint256 _len = _depositTokens.length;\n\n        for (uint256 i; i < _len; ++i) {\n            IERC20 _underlying = IDepositToken(_depositTokens[i]).underlying();\n\n            uint256 _underlyingBalance = _underlying.balanceOf(address(this));\n\n            if (_underlyingBalance > 0) {\n                _underlying.safeTransfer(newTreasury_, _underlyingBalance);\n            }\n        }\n    }\n\n    /**\n     * @notice Pull token from the Treasury\n     * @param to_ The transfer recipient\n     * @param amount_ The transfer amount\n     */\n    function pull(address to_, uint256 amount_) external override nonReentrant {\n        address _msgSender = _msgSender();\n        if (!pool.doesDepositTokenExist(IDepositToken(_msgSender))) revert SenderIsNotDepositToken();\n        if (to_ == address(0)) revert RecipientIsNull();\n        if (amount_ == 0) revert AmountIsZero();\n        IDepositToken(_msgSender).underlying().safeTransfer(to_, amount_);\n    }\n\n    /**\n     * @notice Claim and withdraw rewards from Vesper\n     * @param vPool_ The Vesper pool to collect rewards from\n     * @param to_ The transfer recipient\n     */\n    function claimFromVesper(IVPool vPool_, address to_) external onlyGovernor {\n        IPoolRewards _rewards = IPoolRewards(vPool_.poolRewards());\n        _rewards.updateReward(address(this));\n        _rewards.claimReward(address(this));\n\n        IPool _pool = pool;\n        address[] memory _rewardTokens = _rewards.getRewardTokens();\n        uint256 _len = _rewardTokens.length;\n        for (uint256 i; i < _len; ++i) {\n            IERC20 _token = IERC20(_rewardTokens[i]);\n            uint256 _amount = _token.balanceOf(address(this));\n\n            // Note: If the reward token is a collateral, transfer the surpass balance only\n            IDepositToken _depositToken = _pool.depositTokenOf(_token);\n            if (address(_depositToken) != address(0)) {\n                _amount -= _depositToken.totalSupply();\n            }\n\n            if (_amount > 0) {\n                _token.safeTransfer(to_, _amount);\n            }\n        }\n    }\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/interfaces/ILayerZeroUserApplicationConfig.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n    // @notice set the configuration of the LayerZero messaging library of the specified version\n    // @param _version - messaging library version\n    // @param _chainId - the chainId for the pending config change\n    // @param _configType - type of configuration. every messaging library has its own convention.\n    // @param _config - configuration in the bytes. can encode arbitrary content.\n    function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n    // @notice set the send() LayerZero messaging library version to _version\n    // @param _version - new messaging library version\n    function setSendVersion(uint16 _version) external;\n\n    // @notice set the lzReceive() LayerZero messaging library version to _version\n    // @param _version - new messaging library version\n    function setReceiveVersion(uint16 _version) external;\n\n    // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n    // @param _srcChainId - the chainId of the source chain\n    // @param _srcAddress - the contract address of the source contract at the source chain\n    function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/lzApp/LzApp.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../../../openzeppelin/access/Ownable.sol\";\nimport \"../interfaces/ILayerZeroReceiver.sol\";\nimport \"../interfaces/ILayerZeroUserApplicationConfig.sol\";\nimport \"../interfaces/ILayerZeroEndpoint.sol\";\nimport \"../util/BytesLib.sol\";\n\n/*\n * a generic LzReceiver implementation\n */\nabstract contract LzApp is Ownable, ILayerZeroReceiver, ILayerZeroUserApplicationConfig {\n    using BytesLib for bytes;\n\n    // ua can not send payload larger than this by default, but it can be changed by the ua owner\n    uint public constant DEFAULT_PAYLOAD_SIZE_LIMIT = 10000;\n\n    ILayerZeroEndpoint public immutable lzEndpoint;\n    mapping(uint16 => bytes) public trustedRemoteLookup;\n    mapping(uint16 => mapping(uint16 => uint)) public minDstGasLookup;\n    mapping(uint16 => uint) public payloadSizeLimitLookup;\n    address public precrime;\n\n    event SetPrecrime(address precrime);\n    event SetTrustedRemote(uint16 _remoteChainId, bytes _path);\n    event SetTrustedRemoteAddress(uint16 _remoteChainId, bytes _remoteAddress);\n    event SetMinDstGas(uint16 _dstChainId, uint16 _type, uint _minDstGas);\n\n    constructor(address _endpoint) {\n        lzEndpoint = ILayerZeroEndpoint(_endpoint);\n    }\n\n    function lzReceive(\n        uint16 _srcChainId,\n        bytes calldata _srcAddress,\n        uint64 _nonce,\n        bytes calldata _payload\n    ) public virtual override {\n        // lzReceive must be called by the endpoint for security\n        require(_msgSender() == address(lzEndpoint), \"LzApp: invalid endpoint caller\");\n\n        bytes memory trustedRemote = trustedRemoteLookup[_srcChainId];\n        // if will still block the message pathway from (srcChainId, srcAddress). should not receive message from untrusted remote.\n        require(\n            _srcAddress.length == trustedRemote.length &&\n                trustedRemote.length > 0 &&\n                keccak256(_srcAddress) == keccak256(trustedRemote),\n            \"LzApp: invalid source sending contract\"\n        );\n\n        _blockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);\n    }\n\n    // abstract function - the default behaviour of LayerZero is blocking. See: NonblockingLzApp if you dont need to enforce ordered messaging\n    function _blockingLzReceive(\n        uint16 _srcChainId,\n        bytes memory _srcAddress,\n        uint64 _nonce,\n        bytes memory _payload\n    ) internal virtual;\n\n    function _lzSend(\n        uint16 _dstChainId,\n        bytes memory _payload,\n        address payable _refundAddress,\n        address _zroPaymentAddress,\n        bytes memory _adapterParams,\n        uint _nativeFee\n    ) internal virtual {\n        bytes memory trustedRemote = trustedRemoteLookup[_dstChainId];\n        require(trustedRemote.length != 0, \"LzApp: destination chain is not a trusted source\");\n        _checkPayloadSize(_dstChainId, _payload.length);\n        lzEndpoint.send{value: _nativeFee}(\n            _dstChainId,\n            trustedRemote,\n            _payload,\n            _refundAddress,\n            _zroPaymentAddress,\n            _adapterParams\n        );\n    }\n\n    function _checkGasLimit(\n        uint16 _dstChainId,\n        uint16 _type,\n        bytes memory _adapterParams,\n        uint _extraGas\n    ) internal view virtual {\n        uint providedGasLimit = _getGasLimit(_adapterParams);\n        uint minGasLimit = minDstGasLookup[_dstChainId][_type] + _extraGas;\n        require(minGasLimit > 0, \"LzApp: minGasLimit not set\");\n        require(providedGasLimit >= minGasLimit, \"LzApp: gas limit is too low\");\n    }\n\n    function _getGasLimit(bytes memory _adapterParams) internal pure virtual returns (uint gasLimit) {\n        require(_adapterParams.length >= 34, \"LzApp: invalid adapterParams\");\n        assembly {\n            gasLimit := mload(add(_adapterParams, 34))\n        }\n    }\n\n    function _checkPayloadSize(uint16 _dstChainId, uint _payloadSize) internal view virtual {\n        uint payloadSizeLimit = payloadSizeLimitLookup[_dstChainId];\n        if (payloadSizeLimit == 0) {\n            // use default if not set\n            payloadSizeLimit = DEFAULT_PAYLOAD_SIZE_LIMIT;\n        }\n        require(_payloadSize <= payloadSizeLimit, \"LzApp: payload size is too large\");\n    }\n\n    //---------------------------UserApplication config----------------------------------------\n    function getConfig(\n        uint16 _version,\n        uint16 _chainId,\n        address,\n        uint _configType\n    ) external view returns (bytes memory) {\n        return lzEndpoint.getConfig(_version, _chainId, address(this), _configType);\n    }\n\n    // generic config for LayerZero user Application\n    function setConfig(\n        uint16 _version,\n        uint16 _chainId,\n        uint _configType,\n        bytes calldata _config\n    ) external override onlyOwner {\n        lzEndpoint.setConfig(_version, _chainId, _configType, _config);\n    }\n\n    function setSendVersion(uint16 _version) external override onlyOwner {\n        lzEndpoint.setSendVersion(_version);\n    }\n\n    function setReceiveVersion(uint16 _version) external override onlyOwner {\n        lzEndpoint.setReceiveVersion(_version);\n    }\n\n    function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external override onlyOwner {\n        lzEndpoint.forceResumeReceive(_srcChainId, _srcAddress);\n    }\n\n    // _path = abi.encodePacked(remoteAddress, localAddress)\n    // this function set the trusted path for the cross-chain communication\n    function setTrustedRemote(uint16 _remoteChainId, bytes calldata _path) external onlyOwner {\n        trustedRemoteLookup[_remoteChainId] = _path;\n        emit SetTrustedRemote(_remoteChainId, _path);\n    }\n\n    function setTrustedRemoteAddress(uint16 _remoteChainId, bytes calldata _remoteAddress) external onlyOwner {\n        trustedRemoteLookup[_remoteChainId] = abi.encodePacked(_remoteAddress, address(this));\n        emit SetTrustedRemoteAddress(_remoteChainId, _remoteAddress);\n    }\n\n    function getTrustedRemoteAddress(uint16 _remoteChainId) external view returns (bytes memory) {\n        bytes memory path = trustedRemoteLookup[_remoteChainId];\n        require(path.length != 0, \"LzApp: no trusted path record\");\n        return path.slice(0, path.length - 20); // the last 20 bytes should be address(this)\n    }\n\n    function setPrecrime(address _precrime) external onlyOwner {\n        precrime = _precrime;\n        emit SetPrecrime(_precrime);\n    }\n\n    function setMinDstGas(uint16 _dstChainId, uint16 _packetType, uint _minGas) external onlyOwner {\n        require(_minGas > 0, \"LzApp: invalid minGas\");\n        minDstGasLookup[_dstChainId][_packetType] = _minGas;\n        emit SetMinDstGas(_dstChainId, _packetType, _minGas);\n    }\n\n    // if the size is 0, it means default size limit\n    function setPayloadSizeLimit(uint16 _dstChainId, uint _size) external onlyOwner {\n        payloadSizeLimitLookup[_dstChainId] = _size;\n    }\n\n    //--------------------------- VIEW FUNCTION ----------------------------------------\n    function isTrustedRemote(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool) {\n        bytes memory trustedSource = trustedRemoteLookup[_srcChainId];\n        return keccak256(trustedSource) == keccak256(_srcAddress);\n    }\n}\n"},{"file_path":"contracts/interfaces/external/IStargateFactory.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\ninterface IStargateFactory {\n    function getPool(uint256 _id) external view returns (address _pool);\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967Upgrade {\n    // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n    /**\n     * @dev Storage slot with the address of the current implementation.\n     * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n     * validated in the constructor.\n     */\n    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n    /**\n     * @dev Emitted when the implementation is upgraded.\n     */\n    event Upgraded(address indexed implementation);\n\n    /**\n     * @dev Returns the current implementation address.\n     */\n    function _getImplementation() internal view returns (address) {\n        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the EIP1967 implementation slot.\n     */\n    function _setImplementation(address newImplementation) private {\n        require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n    }\n\n    /**\n     * @dev Perform implementation upgrade\n     *\n     * Emits an {Upgraded} event.\n     */\n    function _upgradeTo(address newImplementation) internal {\n        _setImplementation(newImplementation);\n        emit Upgraded(newImplementation);\n    }\n\n    /**\n     * @dev Perform implementation upgrade with additional setup call.\n     *\n     * Emits an {Upgraded} event.\n     */\n    function _upgradeToAndCall(\n        address newImplementation,\n        bytes memory data,\n        bool forceCall\n    ) internal {\n        _upgradeTo(newImplementation);\n        if (data.length > 0 || forceCall) {\n            Address.functionDelegateCall(newImplementation, data);\n        }\n    }\n\n    /**\n     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n     *\n     * Emits an {Upgraded} event.\n     */\n    function _upgradeToAndCallUUPS(\n        address newImplementation,\n        bytes memory data,\n        bool forceCall\n    ) internal {\n        // Upgrades from old implementations will perform a rollback test. This test requires the new\n        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n        // this special case will break upgrade paths from old UUPS implementation to new ones.\n        if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n            _setImplementation(newImplementation);\n        } else {\n            try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n                require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n            } catch {\n                revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n            }\n            _upgradeToAndCall(newImplementation, data, forceCall);\n        }\n    }\n\n    /**\n     * @dev Storage slot with the admin of the contract.\n     * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n     * validated in the constructor.\n     */\n    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n    /**\n     * @dev Emitted when the admin account has changed.\n     */\n    event AdminChanged(address previousAdmin, address newAdmin);\n\n    /**\n     * @dev Returns the current admin.\n     */\n    function _getAdmin() internal view returns (address) {\n        return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the EIP1967 admin slot.\n     */\n    function _setAdmin(address newAdmin) private {\n        require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n        StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n    }\n\n    /**\n     * @dev Changes the admin of the proxy.\n     *\n     * Emits an {AdminChanged} event.\n     */\n    function _changeAdmin(address newAdmin) internal {\n        emit AdminChanged(_getAdmin(), newAdmin);\n        _setAdmin(newAdmin);\n    }\n\n    /**\n     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n     */\n    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n    /**\n     * @dev Emitted when the beacon is upgraded.\n     */\n    event BeaconUpgraded(address indexed beacon);\n\n    /**\n     * @dev Returns the current beacon.\n     */\n    function _getBeacon() internal view returns (address) {\n        return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new beacon in the EIP1967 beacon slot.\n     */\n    function _setBeacon(address newBeacon) private {\n        require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n        require(\n            Address.isContract(IBeacon(newBeacon).implementation()),\n            \"ERC1967: beacon implementation is not a contract\"\n        );\n        StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n    }\n\n    /**\n     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n     *\n     * Emits a {BeaconUpgraded} event.\n     */\n    function _upgradeBeaconToAndCall(\n        address newBeacon,\n        bytes memory data,\n        bool forceCall\n    ) internal {\n        _setBeacon(newBeacon);\n        emit BeaconUpgraded(newBeacon);\n        if (data.length > 0 || forceCall) {\n            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n        }\n    }\n}\n"},{"file_path":"contracts/FeeProvider.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {Initializable} from \"./dependencies/openzeppelin-upgradeable/proxy/utils/Initializable.sol\";\nimport {SynthContext} from \"./utils/SynthContext.sol\";\nimport {FeeProviderStorageV2} from \"./storage/FeeProviderStorage.sol\";\nimport {IPoolRegistry} from \"./interfaces/IPoolRegistry.sol\";\nimport {IPool} from \"./interfaces/IPool.sol\";\nimport {IDepositToken} from \"./interfaces/IDepositToken.sol\";\nimport {IESMET} from \"./interfaces/external/IESMET.sol\";\nimport {WadRayMath} from \"./lib/WadRayMath.sol\";\n\nerror SenderIsNotGovernor();\nerror PoolRegistryIsNull();\nerror NewValueIsSameAsCurrent();\nerror FeeIsGreaterThanTheMax();\nerror LiquidationFeesTooHigh();\n\n/**\n * @title FeeProvider contract\n */\ncontract FeeProvider is SynthContext, Initializable, FeeProviderStorageV2 {\n    using WadRayMath for uint256;\n\n    string public constant VERSION = \"1.4.1\";\n\n    uint256 internal constant MAX_FEE_VALUE = 0.25e18; // 25%\n\n    // Note: Upper bound on `collateralFactor * (1 + liquidationFees)`. The `< 1e36` form only\n    // guarantees liquidation *eventually* helps; at exactly 1e36 it closes 0 wei of the health\n    // gap. This leaves a margin so every liquidation closes >= 2% of the amount repaid.\n    uint256 internal constant MAX_CF_TIMES_LIQUIDATION_FEES = 0.98e36;\n\n    /// @notice Emitted when deposit fee is updated\n    event DepositFeeUpdated(uint256 oldDepositFee, uint256 newDepositFee);\n\n    /// @notice Emitted when issue fee is updated\n    event IssueFeeUpdated(uint256 oldIssueFee, uint256 newIssueFee);\n\n    /// @notice Emitted when liquidator incentive is updated\n    event LiquidatorIncentiveUpdated(uint256 oldLiquidatorIncentive, uint256 newLiquidatorIncentive);\n\n    /// @notice Emitted when protocol liquidation fee is updated\n    event ProtocolLiquidationFeeUpdated(uint256 oldProtocolLiquidationFee, uint256 newProtocolLiquidationFee);\n\n    /// @notice Emitted when repay fee is updated\n    event RepayFeeUpdated(uint256 oldRepayFee, uint256 newRepayFee);\n\n    /// @notice Emitted when swap fee is updated\n    event SwapFeeUpdated(address synthIn, address synthOut, uint256 oldSwapFee, uint256 newSwapFee);\n\n    /// @notice Emitted when withdraw fee is updated\n    event WithdrawFeeUpdated(uint256 oldWithdrawFee, uint256 newWithdrawFee);\n\n    /**\n     * @notice Throws if caller isn't the governor\n     */\n    modifier onlyGovernor() {\n        if (_msgSender() != _poolRegistry.governor()) revert SenderIsNotGovernor();\n        _;\n    }\n\n    constructor() {\n        _disableInitializers();\n    }\n\n    function initialize(IPoolRegistry poolRegistry_, IESMET esMET_) public initializer {\n        if (address(poolRegistry_) == address(0)) revert PoolRegistryIsNull();\n\n        _poolRegistry = poolRegistry_;\n        esMET = esMET_;\n\n        liquidationFees = LiquidationFees({\n            liquidatorIncentive: 1e17, // 10%\n            protocolFee: 5e16 // 5%\n        });\n    }\n\n    function _revertIfLiquidationFeesAreTooHigh(uint256 newLiquidationFees_) private view {\n        address[] memory _pools = _poolRegistry.getPools();\n        uint256 _poolsLength = _pools.length;\n        for (uint256 i; i < _poolsLength; ++i) {\n            IPool _pool = IPool(_pools[i]);\n            if (address(_pool.feeProvider()) != address(this)) continue;\n\n            address[] memory _depositTokens = _pool.getDepositTokens();\n            uint256 _depositTokensLength = _depositTokens.length;\n            for (uint256 j; j < _depositTokensLength; ++j) {\n                uint256 _collateralFactor = IDepositToken(_depositTokens[j]).collateralFactor();\n                // Note: The `CF * (1 + liquidationFees) < 1` invariant must hold, with a margin (see the constant)\n                if (_collateralFactor * (1e18 + newLiquidationFees_) >= MAX_CF_TIMES_LIQUIDATION_FEES) {\n                    revert LiquidationFeesTooHigh();\n                }\n            }\n        }\n    }\n\n    /// @inheritdoc SynthContext\n    function poolRegistry() public view override returns (IPoolRegistry) {\n        return _poolRegistry;\n    }\n\n    /**\n     * @notice Update deposit fee\n     */\n    function updateDepositFee(uint256 newDepositFee_) external onlyGovernor {\n        if (newDepositFee_ > MAX_FEE_VALUE) revert FeeIsGreaterThanTheMax();\n        uint256 _currentDepositFee = depositFee;\n        if (newDepositFee_ == _currentDepositFee) revert NewValueIsSameAsCurrent();\n        emit DepositFeeUpdated(_currentDepositFee, newDepositFee_);\n        depositFee = newDepositFee_;\n    }\n\n    /**\n     * @notice Update issue fee\n     */\n    function updateIssueFee(uint256 newIssueFee_) external onlyGovernor {\n        if (newIssueFee_ > MAX_FEE_VALUE) revert FeeIsGreaterThanTheMax();\n        uint256 _currentIssueFee = issueFee;\n        if (newIssueFee_ == _currentIssueFee) revert NewValueIsSameAsCurrent();\n        emit IssueFeeUpdated(_currentIssueFee, newIssueFee_);\n        issueFee = newIssueFee_;\n    }\n\n    /**\n     * @notice Update liquidator incentive\n     * @dev liquidatorIncentive + protocolFee can't surpass max\n     */\n    function updateLiquidatorIncentive(uint128 newLiquidatorIncentive_) external onlyGovernor {\n        LiquidationFees memory _current = liquidationFees;\n        if (newLiquidatorIncentive_ + _current.protocolFee > MAX_FEE_VALUE) revert FeeIsGreaterThanTheMax();\n        if (newLiquidatorIncentive_ == _current.liquidatorIncentive) revert NewValueIsSameAsCurrent();\n        if (newLiquidatorIncentive_ > _current.liquidatorIncentive) {\n            _revertIfLiquidationFeesAreTooHigh(newLiquidatorIncentive_ + _current.protocolFee);\n        }\n        emit LiquidatorIncentiveUpdated(_current.liquidatorIncentive, newLiquidatorIncentive_);\n        liquidationFees.liquidatorIncentive = newLiquidatorIncentive_;\n    }\n\n    /**\n     * @notice Update protocol liquidation fee\n     * @dev liquidatorIncentive + protocolFee can't surpass max\n     */\n    function updateProtocolLiquidationFee(uint128 newProtocolLiquidationFee_) external onlyGovernor {\n        LiquidationFees memory _current = liquidationFees;\n        if (newProtocolLiquidationFee_ + _current.liquidatorIncentive > MAX_FEE_VALUE) revert FeeIsGreaterThanTheMax();\n        if (newProtocolLiquidationFee_ == _current.protocolFee) revert NewValueIsSameAsCurrent();\n        if (newProtocolLiquidationFee_ > _current.protocolFee) {\n            _revertIfLiquidationFeesAreTooHigh(newProtocolLiquidationFee_ + _current.liquidatorIncentive);\n        }\n        emit ProtocolLiquidationFeeUpdated(_current.protocolFee, newProtocolLiquidationFee_);\n        liquidationFees.protocolFee = newProtocolLiquidationFee_;\n    }\n\n    /**\n     * @notice Update repay fee\n     */\n    function updateRepayFee(uint256 newRepayFee_) external onlyGovernor {\n        if (newRepayFee_ > MAX_FEE_VALUE) revert FeeIsGreaterThanTheMax();\n        uint256 _currentRepayFee = repayFee;\n        if (newRepayFee_ == _currentRepayFee) revert NewValueIsSameAsCurrent();\n        emit RepayFeeUpdated(_currentRepayFee, newRepayFee_);\n        repayFee = newRepayFee_;\n    }\n\n    /**\n     * @notice Update swap fee\n     */\n    function updateSwapFee(address synthIn_, address synthOut_, uint256 newSwapFee_) external onlyGovernor {\n        if (newSwapFee_ > MAX_FEE_VALUE) revert FeeIsGreaterThanTheMax();\n        uint256 _current = swapFees[synthIn_][synthOut_];\n        if (newSwapFee_ == _current) revert NewValueIsSameAsCurrent();\n        emit SwapFeeUpdated(synthIn_, synthOut_, _current, newSwapFee_);\n        swapFees[synthIn_][synthOut_] = newSwapFee_;\n    }\n\n    /**\n     * @notice Update withdraw fee\n     */\n    function updateWithdrawFee(uint256 newWithdrawFee_) external onlyGovernor {\n        if (newWithdrawFee_ > MAX_FEE_VALUE) revert FeeIsGreaterThanTheMax();\n        uint256 _currentWithdrawFee = withdrawFee;\n        if (newWithdrawFee_ == _currentWithdrawFee) revert NewValueIsSameAsCurrent();\n        emit WithdrawFeeUpdated(_currentWithdrawFee, newWithdrawFee_);\n        withdrawFee = newWithdrawFee_;\n    }\n}\n"},{"file_path":"contracts/utils/TokenHolder.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {Address} from \"../dependencies/openzeppelin/utils/Address.sol\";\nimport {SafeERC20, IERC20} from \"../dependencies/openzeppelin/token/ERC20/utils/SafeERC20.sol\";\n\nerror FallbackIsNotAllowed();\nerror ReceiveIsNotAllowed();\n\n/**\n * @title Utils contract that handles tokens sent to it\n */\nabstract contract TokenHolder {\n    using SafeERC20 for IERC20;\n\n    /**\n     * @dev Revert fallback calls\n     */\n    fallback() external payable {\n        revert FallbackIsNotAllowed();\n    }\n\n    /**\n     * @dev Revert when receiving by default\n     */\n    receive() external payable virtual {\n        revert ReceiveIsNotAllowed();\n    }\n\n    /**\n     * @notice ERC20 recovery in case of stuck tokens due direct transfers to the contract address.\n     * @param token_ The token to transfer\n     * @param to_ The recipient of the transfer\n     * @param amount_ The amount to send\n     */\n    function sweep(IERC20 token_, address to_, uint256 amount_) external {\n        _requireCanSweep();\n\n        if (address(token_) == address(0)) {\n            Address.sendValue(payable(to_), amount_);\n        } else {\n            token_.safeTransfer(to_, amount_);\n        }\n    }\n\n    /**\n     * @notice Function that reverts if the caller isn't allowed to sweep tokens\n     * @dev Usually requires the owner or governor as the caller\n     */\n    function _requireCanSweep() internal view virtual;\n}\n"},{"file_path":"contracts/storage/RewardsDistributorStorage.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IERC20} from \"../dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {IRewardsDistributor} from \"../interfaces/IRewardsDistributor.sol\";\n\nabstract contract RewardsDistributorStorageV1 is IRewardsDistributor {\n    struct TokenState {\n        uint224 index; // The last updated index\n        uint32 timestamp; // The timestamp of the latest index update\n    }\n\n    /**\n     * @notice The token to reward\n     */\n    IERC20 public override rewardToken;\n\n    /**\n     * @notice Track tokens for reward\n     */\n    IERC20[] public override tokens;\n\n    /**\n     * @notice The amount of token distributed for each token per second\n     */\n    mapping(IERC20 => uint256) public override tokenSpeeds;\n\n    /**\n     * @notice The reward state for each token\n     */\n    mapping(IERC20 => TokenState) public override tokenStates;\n\n    /**\n     * @notice The supply index for each token for each account as of the last time they accrued token\n     */\n    mapping(IERC20 => mapping(address => uint256)) public override accountIndexOf;\n\n    /**\n     * @notice The token accrued but not yet transferred to each user\n     */\n    mapping(address => uint256) public override tokensAccruedOf;\n}\n\nabstract contract RewardsDistributorStorageV2 is RewardsDistributorStorageV1 {\n    address public tokenSpeedKeeper;\n}\n"},{"file_path":"contracts/interfaces/IPool.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IERC20} from \"../dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {IDepositToken} from \"./IDepositToken.sol\";\nimport {IDebtToken} from \"./IDebtToken.sol\";\nimport {ITreasury} from \"./ITreasury.sol\";\nimport {IPoolRegistry} from \"./IPoolRegistry.sol\";\nimport {IFeeProvider} from \"./IFeeProvider.sol\";\nimport {ISmartFarmingManager} from \"./ISmartFarmingManager.sol\";\nimport {IFeeProvider} from \"../interfaces/IFeeProvider.sol\";\nimport {IPauseable} from \"../interfaces/IPauseable.sol\";\nimport {IGovernable} from \"../interfaces/IGovernable.sol\";\nimport {ISyntheticToken} from \"../interfaces/ISyntheticToken.sol\";\nimport {IMasterOracle} from \"../interfaces/external/IMasterOracle.sol\";\n\n/**\n * @notice Pool interface\n */\ninterface IPool is IPauseable, IGovernable {\n    function debtFloorInUsd() external view returns (uint256);\n\n    function feeCollector() external view returns (address);\n\n    function feeProvider() external view returns (IFeeProvider);\n\n    function maxLiquidable() external view returns (uint256);\n\n    function doesSyntheticTokenExist(ISyntheticToken syntheticToken_) external view returns (bool);\n\n    function doesDebtTokenExist(IDebtToken debtToken_) external view returns (bool);\n\n    function doesDepositTokenExist(IDepositToken depositToken_) external view returns (bool);\n\n    function depositTokenOf(IERC20 underlying_) external view returns (IDepositToken);\n\n    function debtTokenOf(ISyntheticToken syntheticToken_) external view returns (IDebtToken);\n\n    function getDepositTokens() external view returns (address[] memory);\n\n    function getDebtTokens() external view returns (address[] memory);\n\n    function getRewardsDistributors() external view returns (address[] memory);\n\n    function debtOf(address account_) external view returns (uint256 _debtInUsd);\n\n    function depositOf(address account_) external view returns (uint256 _depositInUsd, uint256 _issuableLimitInUsd);\n\n    function debtPositionOf(\n        address account_\n    )\n        external\n        view\n        returns (\n            bool _isHealthy,\n            uint256 _depositInUsd,\n            uint256 _debtInUsd,\n            uint256 _issuableLimitInUsd,\n            uint256 _issuableInUsd\n        );\n\n    function liquidate(\n        ISyntheticToken syntheticToken_,\n        address account_,\n        uint256 amountToRepay_,\n        IDepositToken depositToken_\n    ) external returns (uint256 _totalSeized, uint256 _toLiquidator, uint256 _fee);\n\n    function quoteLiquidateIn(\n        ISyntheticToken syntheticToken_,\n        uint256 totalToSeized_,\n        IDepositToken depositToken_\n    ) external view returns (uint256 _amountToRepay, uint256 _toLiquidator, uint256 _fee);\n\n    function quoteLiquidateMax(\n        ISyntheticToken syntheticToken_,\n        address account_,\n        IDepositToken depositToken_\n    ) external view returns (uint256 _maxAmountToRepay);\n\n    function quoteLiquidateOut(\n        ISyntheticToken syntheticToken_,\n        uint256 amountToRepay_,\n        IDepositToken depositToken_\n    ) external view returns (uint256 _totalSeized, uint256 _toLiquidator, uint256 _fee);\n\n    function quoteSwapIn(\n        ISyntheticToken syntheticTokenIn_,\n        ISyntheticToken syntheticTokenOut_,\n        uint256 amountOut_\n    ) external view returns (uint256 _amountIn, uint256 _fee);\n\n    function quoteSwapOut(\n        ISyntheticToken syntheticTokenIn_,\n        ISyntheticToken syntheticTokenOut_,\n        uint256 amountIn_\n    ) external view returns (uint256 _amountOut, uint256 _fee);\n\n    function swap(\n        ISyntheticToken syntheticTokenIn_,\n        ISyntheticToken syntheticTokenOut_,\n        uint256 amountIn_\n    ) external returns (uint256 _amountOut, uint256 _fee);\n\n    function treasury() external view returns (ITreasury);\n\n    function masterOracle() external view returns (IMasterOracle);\n\n    function poolRegistry() external view returns (IPoolRegistry);\n\n    function addToDepositTokensOfAccount(address account_) external;\n\n    function removeFromDepositTokensOfAccount(address account_) external;\n\n    function addToDebtTokensOfAccount(address account_) external;\n\n    function removeFromDebtTokensOfAccount(address account_) external;\n\n    function getDepositTokensOfAccount(address account_) external view returns (address[] memory);\n\n    function getDebtTokensOfAccount(address account_) external view returns (address[] memory);\n\n    function isSwapActive() external view returns (bool);\n\n    function smartFarmingManager() external view returns (ISmartFarmingManager);\n}\n"},{"file_path":"contracts/mock/MasterOracleMock.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IERC20Metadata} from \"../dependencies/openzeppelin/token/ERC20/extensions/IERC20Metadata.sol\";\nimport {IMasterOracle} from \"../interfaces/external/IMasterOracle.sol\";\n\ncontract MasterOracleMock is IMasterOracle {\n    mapping(address => uint256) public prices;\n\n    uint256 public expireAt = type(uint256).max;\n    uint256 public expirationPeriod = 100 * 365 days;\n\n    function updatePrice(address _asset, uint256 _price) external {\n        prices[_asset] = _price;\n        expireAt = block.timestamp + expirationPeriod;\n    }\n\n    function quoteTokenToUsd(address _asset, uint256 _amount) public view override returns (uint256 _amountInUsd) {\n        require(block.timestamp <= expireAt, \"price-expired\");\n        _amountInUsd = (_amount * prices[_asset]) / 10 ** IERC20Metadata(address(_asset)).decimals();\n    }\n\n    function quoteUsdToToken(address _asset, uint256 _amountInUsd) public view override returns (uint256 _amount) {\n        require(block.timestamp <= expireAt, \"price-expired\");\n        _amount = (_amountInUsd * 10 ** IERC20Metadata(address(_asset)).decimals()) / prices[_asset];\n    }\n\n    function quote(\n        address _assetIn,\n        address _assetOut,\n        uint256 _amountIn\n    ) public view override returns (uint256 _amountOut) {\n        uint256 _amountInUsd = quoteTokenToUsd(_assetIn, _amountIn);\n        _amountOut = quoteUsdToToken(_assetOut, _amountInUsd);\n    }\n\n    function setExpirationPeriod(uint256 expirationPeriod_) public {\n        expirationPeriod = expirationPeriod_;\n    }\n}\n"},{"file_path":"contracts/SmartFarmingManager.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {SafeERC20} from \"./dependencies/openzeppelin/token/ERC20/utils/SafeERC20.sol\";\nimport {Math} from \"./dependencies/openzeppelin/utils/math/Math.sol\";\nimport {IERC20} from \"./dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {Initializable} from \"./dependencies/openzeppelin-upgradeable/proxy/utils/Initializable.sol\";\nimport {Manageable} from \"./access/Manageable.sol\";\nimport {ReentrancyGuardDeprecated} from \"./utils/ReentrancyGuardDeprecated.sol\";\nimport {ReentrancyGuardTransient} from \"./utils/ReentrancyGuardTransient.sol\";\nimport {WadRayMath} from \"./lib/WadRayMath.sol\";\nimport {ISyntheticToken} from \"./interfaces/ISyntheticToken.sol\";\nimport {IDepositToken} from \"./interfaces/IDepositToken.sol\";\nimport {IPool} from \"./interfaces/IPool.sol\";\nimport {IDebtToken} from \"./interfaces/IDebtToken.sol\";\nimport {ISwapper} from \"./interfaces/external/ISwapper.sol\";\nimport {SmartFarmingManagerStorageV1} from \"./storage/SmartFarmingManagerStorage.sol\";\n\nerror SyntheticDoesNotExist();\nerror PoolIsNull();\nerror FlashRepaySlippageTooHigh();\nerror LeverageTooLow();\nerror LeverageTooHigh();\nerror LeverageSlippageTooHigh();\nerror PositionIsNotHealthy();\nerror AmountIsZero();\nerror AmountIsTooHigh();\nerror DepositTokenDoesNotExist();\n\n/**\n * @title SmartFarmingManager contract\n */\ncontract SmartFarmingManager is\n    Initializable,\n    ReentrancyGuardDeprecated,\n    ReentrancyGuardTransient,\n    Manageable,\n    SmartFarmingManagerStorageV1\n{\n    using SafeERC20 for IERC20;\n    using SafeERC20 for ISyntheticToken;\n    using WadRayMath for uint256;\n\n    string public constant VERSION = \"1.4.1\";\n\n    /// @notice Emitted when debt is flash repaid\n    event FlashRepaid(\n        ISyntheticToken indexed syntheticToken,\n        IDepositToken indexed depositToken,\n        uint256 withdrawn,\n        uint256 repaid\n    );\n\n    /// @notice Emitted when deposit is leveraged\n    event Leveraged(\n        IERC20 indexed tokenIn,\n        IDepositToken indexed depositToken,\n        ISyntheticToken indexed syntheticToken,\n        uint256 leverage,\n        uint256 amountIn,\n        uint256 issued,\n        uint256 deposited\n    );\n\n    /**\n     * @dev Throws if deposit token doesn't exist\n     */\n    modifier onlyIfDepositTokenExists(IDepositToken depositToken_) {\n        if (!pool.doesDepositTokenExist(depositToken_)) revert DepositTokenDoesNotExist();\n        _;\n    }\n\n    /**\n     * @dev Throws if synthetic token doesn't exist\n     */\n    modifier onlyIfSyntheticTokenExists(ISyntheticToken syntheticToken_) {\n        if (!pool.doesSyntheticTokenExist(syntheticToken_)) revert SyntheticDoesNotExist();\n        _;\n    }\n\n    constructor() {\n        _disableInitializers();\n    }\n\n    function initialize(IPool pool_) public initializer {\n        if (address(pool_) == address(0)) revert PoolIsNull();\n        __Manageable_init(pool_);\n    }\n\n    /**\n     * @notice Flash debt repayment\n     * @param syntheticToken_ The debt token to repay\n     * @param depositToken_ The collateral to withdraw\n     * @param withdrawAmount_ The amount to withdraw\n     * @param swapAmountOutMin_ The minimum amount of synthetic tokens to receive (slippage check)\n     */\n    function flashRepay(\n        ISyntheticToken syntheticToken_,\n        IDepositToken depositToken_,\n        uint256 withdrawAmount_,\n        uint256 swapAmountOutMin_\n    )\n        external\n        override\n        whenNotShutdown\n        nonReentrant\n        onlyIfDepositTokenExists(depositToken_)\n        onlyIfSyntheticTokenExists(syntheticToken_)\n        returns (uint256 _withdrawn, uint256 _repaid)\n    {\n        ISyntheticToken _syntheticToken = syntheticToken_; // stack too deep\n\n        address _msgSender = _msgSender();\n        if (withdrawAmount_ == 0) revert AmountIsZero();\n        if (withdrawAmount_ > depositToken_.balanceOf(_msgSender)) revert AmountIsTooHigh();\n\n        // 1. withdraw collateral\n        (_withdrawn, ) = depositToken_.flashWithdraw(_msgSender, withdrawAmount_);\n\n        // 2. swap it for synth\n        // Note: `amountOutMin_` is `0` because slippage is checked below on the actual amount received\n        uint256 _synthAmountOut = _swap(swapper(), _collateralOf(depositToken_), _syntheticToken, _withdrawn, 0);\n        if (_synthAmountOut < swapAmountOutMin_) revert FlashRepaySlippageTooHigh();\n\n        IPool _pool = pool;\n        IDebtToken _debtToken = _pool.debtTokenOf(_syntheticToken);\n        (uint256 _maxRepayAmount, ) = _debtToken.quoteRepayIn(_debtToken.balanceOf(_msgSender));\n        uint256 _amountToRepay = Math.min(_synthAmountOut, _maxRepayAmount);\n\n        // 3. repay debt\n        (_repaid, ) = _debtToken.repay(_msgSender, _amountToRepay);\n\n        // 4. refund synthetic token in excess\n        if (_synthAmountOut > _amountToRepay) {\n            _syntheticToken.safeTransfer(_msgSender, _synthAmountOut - _amountToRepay);\n        }\n\n        // 5. check the health of the outcome position\n        (bool _isHealthy, , , , ) = _pool.debtPositionOf(_msgSender);\n        if (!_isHealthy) revert PositionIsNotHealthy();\n\n        emit FlashRepaid(_syntheticToken, depositToken_, _withdrawn, _repaid);\n    }\n\n    /**\n     * @notice Leverage yield position\n     * @param tokenIn_ The token to transfer\n     * @param depositToken_ The collateral to deposit\n     * @param syntheticToken_ The msAsset to mint\n     * @param amountIn_ The amount to deposit\n     * @param leverage_ The leverage X param (e.g. 1.5e18 for 1.5X)\n     * @param depositAmountMin_ The min final deposit amount (slippage)\n     */\n    function leverage(\n        IERC20 tokenIn_,\n        IDepositToken depositToken_,\n        ISyntheticToken syntheticToken_,\n        uint256 amountIn_,\n        uint256 leverage_,\n        uint256 depositAmountMin_\n    )\n        external\n        override\n        whenNotShutdown\n        nonReentrant\n        onlyIfDepositTokenExists(depositToken_)\n        onlyIfSyntheticTokenExists(syntheticToken_)\n        returns (uint256 _deposited, uint256 _issued)\n    {\n        if (amountIn_ == 0) revert AmountIsZero();\n        if (leverage_ <= 1e18) revert LeverageTooLow();\n        if (leverage_ > uint256(1e18).wadDiv(1e18 - depositToken_.collateralFactor())) revert LeverageTooHigh();\n\n        address _msgSender = _msgSender();\n        ISwapper _swapper = swapper();\n\n        // 1. transfer collateral\n        IERC20 _collateral = _collateralOf(depositToken_);\n        if (address(tokenIn_) == address(0)) tokenIn_ = _collateral;\n        amountIn_ = _safeTransferFrom(tokenIn_, _msgSender, amountIn_);\n        if (tokenIn_ != _collateral) {\n            // Note: `amountOutMin_` is `0` because slippage will be checked later on\n            amountIn_ = _swap(_swapper, tokenIn_, _collateral, amountIn_, 0);\n        }\n\n        {\n            // 2. mint synth + debt\n            uint256 _debtAmount = _calculateLeverageDebtAmount(_collateral, syntheticToken_, amountIn_, leverage_);\n            IDebtToken _debtToken = pool.debtTokenOf(syntheticToken_);\n            (_issued, ) = _debtToken.flashIssue(address(this), _debtAmount);\n            _debtToken.mint(_msgSender, _debtAmount);\n        }\n\n        {\n            // 3. swap synth for collateral\n            uint256 _depositAmount = amountIn_ + _swap(_swapper, syntheticToken_, _collateral, _issued, 0);\n            if (_depositAmount < depositAmountMin_) revert LeverageSlippageTooHigh();\n\n            // 4. deposit collateral\n            _collateral.safeApprove(address(depositToken_), 0);\n            _collateral.safeApprove(address(depositToken_), _depositAmount);\n            (_deposited, ) = depositToken_.deposit(_depositAmount, _msgSender);\n        }\n\n        // 5. check the health of the outcome position\n        (bool _isHealthy, , , , ) = pool.debtPositionOf(_msgSender);\n        if (!_isHealthy) revert PositionIsNotHealthy();\n\n        emit Leveraged(tokenIn_, depositToken_, syntheticToken_, leverage_, amountIn_, _issued, _deposited);\n    }\n\n    /**\n     * @notice Get the swapper contract\n     */\n    function swapper() public view returns (ISwapper _swapper) {\n        return pool.poolRegistry().swapper();\n    }\n\n    /**\n     * @notice Calculate debt to issue for a leverage operation\n     * @param collateral_ The collateral to deposit\n     * @param syntheticToken_ The msAsset to mint\n     * @param amountIn_ The amount to deposit\n     * @param leverage_ The leverage X param (e.g. 1.5e18 for 1.5X)\n     * @return _debtAmount The debt issue\n     */\n    function _calculateLeverageDebtAmount(\n        IERC20 collateral_,\n        ISyntheticToken syntheticToken_,\n        uint256 amountIn_,\n        uint256 leverage_\n    ) private view returns (uint256 _debtAmount) {\n        return\n            pool.masterOracle().quote(\n                address(collateral_),\n                address(syntheticToken_),\n                (leverage_ - 1e18).wadMul(amountIn_)\n            );\n    }\n\n    /**\n     * @dev `collateral` is a better name than `underlying`\n     * See more: https://github.com/autonomoussoftware/metronome-synth/issues/905\n     */\n    function _collateralOf(IDepositToken depositToken_) private view returns (IERC20) {\n        return depositToken_.underlying();\n    }\n\n    /**\n     * @notice Transfer token and check actual amount transferred\n     * @param token_ The token to transfer\n     * @param from_ The account to get tokens from\n     * @param amount_ The amount to transfer\n     * @return _transferred The actual transferred amount\n     */\n    function _safeTransferFrom(IERC20 token_, address from_, uint256 amount_) private returns (uint256 _transferred) {\n        uint256 _before = token_.balanceOf(address(this));\n        token_.safeTransferFrom(from_, address(this), amount_);\n        return token_.balanceOf(address(this)) - _before;\n    }\n\n    /**\n     * @notice Swap assets using Swapper contract\n     * @dev Use `address(this)` as amount out receiver\n     * @param swapper_ The Swapper contract\n     * @param tokenIn_ The token to swap from\n     * @param tokenOut_ The token to swap to\n     * @param amountIn_ The amount in\n     * @param amountOutMin_ The minimum amount out (slippage check)\n     * @return _amountOut The actual amount out\n     */\n    function _swap(\n        ISwapper swapper_,\n        IERC20 tokenIn_,\n        IERC20 tokenOut_,\n        uint256 amountIn_,\n        uint256 amountOutMin_\n    ) private returns (uint256 _amountOut) {\n        return _swap(swapper_, tokenIn_, tokenOut_, amountIn_, amountOutMin_, address(this));\n    }\n\n    /**\n     * @notice Swap assets using Swapper contract\n     * @param swapper_ The Swapper contract\n     * @param tokenIn_ The token to swap from\n     * @param tokenOut_ The token to swap to\n     * @param amountIn_ The amount in\n     * @param amountOutMin_ The minimum amount out (slippage check)\n     * @param to_ The amount out receiver\n     * @return _amountOut The actual amount out\n     */\n    function _swap(\n        ISwapper swapper_,\n        IERC20 tokenIn_,\n        IERC20 tokenOut_,\n        uint256 amountIn_,\n        uint256 amountOutMin_,\n        address to_\n    ) private returns (uint256 _amountOut) {\n        if (tokenIn_ != tokenOut_) {\n            tokenIn_.safeApprove(address(swapper_), 0);\n            tokenIn_.safeApprove(address(swapper_), amountIn_);\n            uint256 _tokenOutBefore = tokenOut_.balanceOf(to_);\n            swapper_.swapExactInput(address(tokenIn_), address(tokenOut_), amountIn_, amountOutMin_, to_);\n            return tokenOut_.balanceOf(to_) - _tokenOutBefore;\n        } else if (to_ != address(this)) {\n            tokenIn_.safeTransfer(to_, amountIn_);\n        }\n        return amountIn_;\n    }\n}\n"},{"file_path":"contracts/interfaces/ISmartFarmingManager.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IERC20} from \"../dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {IDepositToken} from \"./IDepositToken.sol\";\nimport {ISyntheticToken} from \"./ISyntheticToken.sol\";\n\n/**\n * @notice SmartFarmingManager interface\n */\ninterface ISmartFarmingManager {\n    function flashRepay(\n        ISyntheticToken syntheticToken_,\n        IDepositToken depositToken_,\n        uint256 withdrawAmount_,\n        uint256 swapAmountOutMin_\n    ) external returns (uint256 _withdrawn, uint256 _repaid);\n\n    function leverage(\n        IERC20 tokenIn_,\n        IDepositToken depositToken_,\n        ISyntheticToken syntheticToken_,\n        uint256 amountIn_,\n        uint256 leverage_,\n        uint256 depositAmountMin_\n    ) external returns (uint256 _deposited, uint256 _issued);\n}\n"},{"file_path":"contracts/utils/ReentrancyGuardDeprecated.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/// @dev This contract is used to avoid breaking storage when migrating to `ReentrancyGuardTransient`\nabstract contract ReentrancyGuardDeprecated {\n    uint256 private _status_DEPRECATED;\n}\n"},{"file_path":"contracts/SyntheticToken.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {Initializable} from \"./dependencies/openzeppelin-upgradeable/proxy/utils/Initializable.sol\";\nimport {IERC20} from \"./dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {SynthContext} from \"./utils/SynthContext.sol\";\nimport {WadRayMath} from \"./lib/WadRayMath.sol\";\nimport {IPool} from \"./interfaces/IPool.sol\";\nimport {IProxyOFT} from \"./interfaces/IProxyOFT.sol\";\nimport {IManageable} from \"./interfaces/IManageable.sol\";\nimport {IPoolRegistry} from \"./interfaces/IPoolRegistry.sol\";\nimport {ISyntheticToken} from \"./interfaces/ISyntheticToken.sol\";\nimport {IDebtToken} from \"./interfaces/IDebtToken.sol\";\nimport {SyntheticTokenStorageV2} from \"./storage/SyntheticTokenStorage.sol\";\n\nerror SenderIsNotGovernor();\nerror SenderCanNotBurn();\nerror SenderCanNotMint();\nerror SenderCanNotSeize();\nerror SyntheticIsInactive();\nerror NameIsNull();\nerror SymbolIsNull();\nerror DecimalsIsNull();\nerror PoolRegistryIsNull();\nerror DecreasedAllowanceBelowZero();\nerror AmountExceedsAllowance();\nerror ApproveFromTheZeroAddress();\nerror ApproveToTheZeroAddress();\nerror BurnFromTheZeroAddress();\nerror BurnAmountExceedsBalance();\nerror MintToTheZeroAddress();\nerror SurpassMaxBridgingSupply();\nerror SurpassMaxSynthSupply();\nerror TransferFromTheZeroAddress();\nerror TransferToTheZeroAddress();\nerror TransferAmountExceedsBalance();\nerror NewValueIsSameAsCurrent();\nerror AddressIsNull();\nerror SurpassMaxAmoSupply();\n\n/**\n * @title Synthetic Token contract\n */\ncontract SyntheticToken is SynthContext, Initializable, SyntheticTokenStorageV2 {\n    using WadRayMath for uint256;\n\n    string public constant VERSION = \"1.4.1\";\n\n    /// @notice Emitted when active flag is updated\n    event SyntheticTokenActiveUpdated(bool newActive);\n\n    /// @notice Emitted when max amo supply is updated\n    event MaxAmoSupplyUpdated(uint256 oldMaxAmoSupply, uint256 newMaxAmoSupply);\n\n    /// @notice Emitted when max total supply is updated\n    event MaxTotalSupplyUpdated(uint256 oldMaxTotalSupply, uint256 newMaxTotalSupply);\n\n    /// @notice Emitted when max bridged-in supply is updated\n    event MaxBridgedInSupplyUpdated(uint256 oldMaxBridgedInSupply, uint256 newMaxBridgedInSupply);\n\n    /// @notice Emitted when max bridged-out supply is updated\n    event MaxBridgedOutSupplyUpdated(uint256 oldMaxBridgedOutSupply, uint256 newMaxBridgedOutSupply);\n\n    /// @notice Emitted when proxyOFT is updated\n    event ProxyOFTUpdated(IProxyOFT oldProxyOFT, IProxyOFT newProxyOFT);\n\n    /// @notice Emitted when AMO is updated\n    event AmoUpdated(address oldAmo, address newAmo);\n\n    /**\n     * @notice Throws if caller isn't the governor\n     */\n    modifier onlyGovernor() {\n        if (_msgSender() != _poolRegistry.governor()) revert SenderIsNotGovernor();\n        _;\n    }\n\n    /**\n     * @dev Throws if sender can't burn\n     */\n    modifier onlyIfCanBurn() {\n        address _msgSender = _msgSender();\n        if (!_isProxyOFT(_msgSender) && !_isPool(_msgSender) && !_isDebtToken(_msgSender)) revert SenderCanNotBurn();\n        _;\n    }\n\n    /**\n     * @dev Throws if sender can't mint\n     */\n    modifier onlyIfCanMint() {\n        address _msgSender = _msgSender();\n        if (!_isProxyOFT(_msgSender) && !_isAmo(_msgSender) && !_isPool(_msgSender) && !_isDebtToken(_msgSender))\n            revert SenderCanNotMint();\n        _;\n    }\n\n    /**\n     * @dev Throws if sender can't seize\n     */\n    modifier onlyIfCanSeize() {\n        address _msgSender = _msgSender();\n        if (!_isProxyOFT(_msgSender) && !_isPool(_msgSender) && !_isDebtToken(_msgSender)) revert SenderCanNotSeize();\n        _;\n    }\n\n    /**\n     * @dev Throws if synthetic token isn't enabled\n     */\n    modifier onlyIfSyntheticTokenIsActive() {\n        if (!isActive) revert SyntheticIsInactive();\n        _;\n    }\n\n    constructor() {\n        _disableInitializers();\n    }\n\n    function initialize(\n        string calldata name_,\n        string calldata symbol_,\n        uint8 decimals_,\n        IPoolRegistry poolRegistry_\n    ) external initializer {\n        if (bytes(name_).length == 0) revert NameIsNull();\n        if (bytes(symbol_).length == 0) revert SymbolIsNull();\n        if (decimals_ == 0) revert DecimalsIsNull();\n        if (address(poolRegistry_) == address(0)) revert PoolRegistryIsNull();\n\n        _poolRegistry = poolRegistry_;\n        name = name_;\n        symbol = symbol_;\n        decimals = decimals_;\n        isActive = true;\n        maxTotalSupply = type(uint256).max;\n    }\n\n    /**\n     * @notice Set `amount` as the allowance of `spender` over the caller's tokens\n     */\n    function approve(address spender_, uint256 amount_) external override returns (bool) {\n        _approve(_msgSender(), spender_, amount_);\n        return true;\n    }\n\n    /**\n     * @notice Get net bridged-in circulating supply\n     * @dev The supply is calculated using `MAX(totalBridgedIn - totalBridgedOut, 0)`\n     */\n    function bridgedInSupply() public view returns (uint256 _supply) {\n        uint256 _totalBridgedIn = totalBridgedIn;\n        uint256 _totalBridgedOut = totalBridgedOut;\n\n        if (_totalBridgedIn > _totalBridgedOut) {\n            return _totalBridgedIn - _totalBridgedOut;\n        }\n    }\n\n    /**\n     * @notice Get net bridged-out circulating supply\n     * @dev The supply is calculated using `MAX(totalBridgedOut - totalBridgedIn, 0)`\n     */\n    function bridgedOutSupply() public view returns (uint256 _supply) {\n        uint256 _totalBridgedIn = totalBridgedIn;\n        uint256 _totalBridgedOut = totalBridgedOut;\n\n        if (_totalBridgedOut > _totalBridgedIn) {\n            return _totalBridgedOut - _totalBridgedIn;\n        }\n    }\n\n    /**\n     * @notice Burn synthetic token\n     * @param from_ The account to burn from\n     * @param amount_ The amount to burn\n     */\n    function burnFor(address from_, uint256 amount_) external override onlyIfCanBurn {\n        _burn(from_, amount_);\n    }\n\n    /**\n     * @notice Burn caller's synthetic tokens\n     * @param amount_ The amount to burn\n     */\n    function burn(uint256 amount_) external override {\n        _burn(_msgSender(), amount_);\n    }\n\n    /**\n     * @notice Burn synthetic tokens from `from_`, deducting from the caller's allowance\n     * @param from_ The account to burn from\n     * @param amount_ The amount to burn\n     */\n    function burnFrom(address from_, uint256 amount_) external override {\n        _spendAllowance(from_, _msgSender(), amount_);\n        _burn(from_, amount_);\n    }\n\n    /**\n     * @notice Atomically decrease the allowance granted to `spender` by the caller\n     */\n    function decreaseAllowance(address spender_, uint256 subtractedValue_) external returns (bool) {\n        address _msgSender = _msgSender();\n        uint256 _currentAllowance = allowance[_msgSender][spender_];\n        if (_currentAllowance < subtractedValue_) revert DecreasedAllowanceBelowZero();\n        unchecked {\n            _approve(_msgSender, spender_, _currentAllowance - subtractedValue_);\n        }\n        return true;\n    }\n\n    /**\n     * @notice Atomically increase the allowance granted to `spender` by the caller\n     */\n    function increaseAllowance(address spender_, uint256 addedValue_) external returns (bool) {\n        address _msgSender = _msgSender();\n        _approve(_msgSender, spender_, allowance[_msgSender][spender_] + addedValue_);\n        return true;\n    }\n\n    /**\n     * @notice Mint synthetic token\n     * @param to_ The account to mint to\n     * @param amount_ The amount to mint\n     */\n    function mint(address to_, uint256 amount_) external override onlyIfCanMint {\n        _mint(to_, amount_);\n    }\n\n    /**\n     * @notice Seize synthetic tokens\n     * @dev Same as _transfer\n     * @param to_ The account to seize from\n     * @param to_ The beneficiary account\n     * @param amount_ The amount to seize\n     */\n    function seize(address from_, address to_, uint256 amount_) external override onlyIfCanSeize {\n        if (_isProxyOFT(_msgSender()) && to_ != _poolRegistry.feeCollector()) revert SenderCanNotSeize();\n\n        _transfer(from_, to_, amount_);\n    }\n\n    /// @inheritdoc IERC20\n    function transfer(address to_, uint256 amount_) external override returns (bool) {\n        _transfer(_msgSender(), to_, amount_);\n        return true;\n    }\n\n    /// @inheritdoc IERC20\n    function transferFrom(address from_, address to_, uint256 amount_) external override returns (bool) {\n        _spendAllowance(from_, _msgSender(), amount_);\n\n        _transfer(from_, to_, amount_);\n\n        return true;\n    }\n\n    /**\n     * @notice Update `owner`'s allowance for `spender` based on spent `amount`\n     * @dev Maximum `uint256` means infinite allowance\n     */\n    function _spendAllowance(address owner_, address spender_, uint256 amount_) private {\n        uint256 _currentAllowance = allowance[owner_][spender_];\n        if (_currentAllowance != type(uint256).max) {\n            if (_currentAllowance < amount_) revert AmountExceedsAllowance();\n            unchecked {\n                _approve(owner_, spender_, _currentAllowance - amount_);\n            }\n        }\n    }\n\n    /**\n     * @notice Set `amount` as the allowance of `spender` over the `owner` s tokens\n     */\n    function _approve(address owner_, address spender_, uint256 amount_) private {\n        if (owner_ == address(0)) revert ApproveFromTheZeroAddress();\n        if (spender_ == address(0)) revert ApproveToTheZeroAddress();\n\n        allowance[owner_][spender_] = amount_;\n        emit Approval(owner_, spender_, amount_);\n    }\n\n    /**\n     * @notice Destroy `amount` tokens from `account`, reducing the\n     * total supply\n     */\n    function _burn(address account_, uint256 amount_) private {\n        if (account_ == address(0)) revert BurnFromTheZeroAddress();\n\n        address _msgSender = _msgSender();\n\n        if (_isProxyOFT(_msgSender)) {\n            totalBridgedOut += amount_;\n            if (bridgedOutSupply() > maxBridgedOutSupply) revert SurpassMaxBridgingSupply();\n        } else if (_isAmo(_msgSender)) {\n            amoSupply -= amount_;\n        }\n\n        uint256 _currentBalance = balanceOf[account_];\n        if (_currentBalance < amount_) revert BurnAmountExceedsBalance();\n        unchecked {\n            balanceOf[account_] = _currentBalance - amount_;\n            totalSupply -= amount_;\n        }\n\n        emit Transfer(account_, address(0), amount_);\n    }\n\n    /**\n     * @dev Check if the account is AMO\n     */\n    function _isAmo(address account_) private view returns (bool) {\n        return account_ == amo;\n    }\n\n    /**\n     * @dev Check if the account is proxyOFT\n     */\n    function _isProxyOFT(address account_) private view returns (bool) {\n        return account_ == address(proxyOFT);\n    }\n\n    /**\n     * @notice Check if the account is a valid DebtToken contract\n     */\n    function _isDebtToken(address account_) private view returns (bool) {\n        IPool _pool = IManageable(account_).pool();\n\n        return\n            _poolRegistry.isPoolRegistered(address(_pool)) &&\n            _pool.doesDebtTokenExist(IDebtToken(account_)) &&\n            IDebtToken(account_).syntheticToken() == this;\n    }\n\n    /**\n     * @notice Check if the account is a valid Pool contract\n     */\n    function _isPool(address account_) private view returns (bool) {\n        return _poolRegistry.isPoolRegistered(account_) && IPool(account_).doesSyntheticTokenExist(this);\n    }\n\n    /**\n     * @notice Create `amount` tokens and assigns them to `account`, increasing\n     * the total supply\n     */\n    function _mint(address account_, uint256 amount_) private onlyIfSyntheticTokenIsActive {\n        if (account_ == address(0)) revert MintToTheZeroAddress();\n\n        address _msgSender = _msgSender();\n\n        if (_isProxyOFT(_msgSender)) {\n            totalBridgedIn += amount_;\n            if (bridgedInSupply() > maxBridgedInSupply) revert SurpassMaxBridgingSupply();\n        } else if (_isAmo(_msgSender)) {\n            amoSupply += amount_;\n            if (amoSupply > maxAmoSupply) revert SurpassMaxAmoSupply();\n        }\n\n        totalSupply += amount_;\n        if (totalSupply > maxTotalSupply) revert SurpassMaxSynthSupply();\n        balanceOf[account_] += amount_;\n        emit Transfer(address(0), account_, amount_);\n    }\n\n    /**\n     * @notice Move `amount` of tokens from `sender` to `recipient`\n     */\n    function _transfer(address sender_, address recipient_, uint256 amount_) private {\n        if (sender_ == address(0)) revert TransferFromTheZeroAddress();\n        if (recipient_ == address(0)) revert TransferToTheZeroAddress();\n\n        uint256 senderBalance = balanceOf[sender_];\n        if (senderBalance < amount_) revert TransferAmountExceedsBalance();\n        unchecked {\n            balanceOf[sender_] = senderBalance - amount_;\n            balanceOf[recipient_] += amount_;\n        }\n\n        emit Transfer(sender_, recipient_, amount_);\n    }\n\n    /**\n     * @notice Enable/Disable Synthetic Token\n     */\n    function toggleIsActive() external override onlyGovernor {\n        bool _newIsActive = !isActive;\n        emit SyntheticTokenActiveUpdated(_newIsActive);\n        isActive = _newIsActive;\n    }\n\n    /**\n     * Update AMO (Automated Marker Operator)\n     * @param newAmo_ new AMO address\n     */\n    function updateAmo(address newAmo_) external onlyGovernor {\n        address _currentAmo = amo;\n        if (newAmo_ == _currentAmo) revert NewValueIsSameAsCurrent();\n        emit AmoUpdated(_currentAmo, newAmo_);\n        amo = newAmo_;\n    }\n\n    /**\n     * @notice Update max synth supply for AMO.\n     * @param newMaxAmoSupply_ The new max synth supply for AMO\n     */\n    function updateMaxAmoSupply(uint256 newMaxAmoSupply_) external onlyGovernor {\n        uint256 _currentMaxAmoSupply = maxAmoSupply;\n        if (newMaxAmoSupply_ == _currentMaxAmoSupply) revert NewValueIsSameAsCurrent();\n        emit MaxAmoSupplyUpdated(_currentMaxAmoSupply, newMaxAmoSupply_);\n        maxAmoSupply = newMaxAmoSupply_;\n    }\n\n    /**\n     * @notice Update max total supply\n     * @param newMaxTotalSupply_ The new max total supply\n     */\n    function updateMaxTotalSupply(uint256 newMaxTotalSupply_) external override onlyGovernor {\n        uint256 _currentMaxTotalSupply = maxTotalSupply;\n        if (newMaxTotalSupply_ == _currentMaxTotalSupply) revert NewValueIsSameAsCurrent();\n        emit MaxTotalSupplyUpdated(_currentMaxTotalSupply, newMaxTotalSupply_);\n        maxTotalSupply = newMaxTotalSupply_;\n    }\n\n    /**\n     * @notice Update max bridged-in supply\n     */\n    function updateMaxBridgedInSupply(uint256 maxBridgedInSupply_) external onlyGovernor {\n        uint256 _currentMaxBridgedInBalance = maxBridgedInSupply;\n        if (maxBridgedInSupply_ == _currentMaxBridgedInBalance) revert NewValueIsSameAsCurrent();\n        emit MaxBridgedInSupplyUpdated(_currentMaxBridgedInBalance, maxBridgedInSupply_);\n        maxBridgedInSupply = maxBridgedInSupply_;\n    }\n\n    /**\n     * @notice Update max bridged-out supply\n     */\n    function updateMaxBridgedOutSupply(uint256 maxBridgedOutSupply_) external onlyGovernor {\n        uint256 _currentMaxBridgedOutBalance = maxBridgedOutSupply;\n        if (maxBridgedOutSupply_ == _currentMaxBridgedOutBalance) revert NewValueIsSameAsCurrent();\n        emit MaxBridgedOutSupplyUpdated(_currentMaxBridgedOutBalance, maxBridgedOutSupply_);\n        maxBridgedOutSupply = maxBridgedOutSupply_;\n    }\n\n    /**\n     * @notice Update proxyOFT\n     * @param newProxyOFT_ Address of new ProxyOFT\n     */\n    function updateProxyOFT(IProxyOFT newProxyOFT_) external override onlyGovernor {\n        if (address(newProxyOFT_) == address(0)) revert AddressIsNull();\n        IProxyOFT _currentProxyOFT = proxyOFT;\n        if (newProxyOFT_ == _currentProxyOFT) revert NewValueIsSameAsCurrent();\n        emit ProxyOFTUpdated(_currentProxyOFT, newProxyOFT_);\n        proxyOFT = newProxyOFT_;\n    }\n\n    /// @inheritdoc SynthContext\n    function poolRegistry() public view override(ISyntheticToken, SynthContext) returns (IPoolRegistry) {\n        return _poolRegistry;\n    }\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/proxy/Proxy.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n    /**\n     * @dev Delegates the current call to `implementation`.\n     *\n     * This function does not return to its internal call site, it will return directly to the external caller.\n     */\n    function _delegate(address implementation) internal virtual {\n        assembly {\n            // Copy msg.data. We take full control of memory in this inline assembly\n            // block because it will not return to Solidity code. We overwrite the\n            // Solidity scratch pad at memory position 0.\n            calldatacopy(0, 0, calldatasize())\n\n            // Call the implementation.\n            // out and outsize are 0 because we don't know the size yet.\n            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n            // Copy the returned data.\n            returndatacopy(0, 0, returndatasize())\n\n            switch result\n            // delegatecall returns 0 on error.\n            case 0 {\n                revert(0, returndatasize())\n            }\n            default {\n                return(0, returndatasize())\n            }\n        }\n    }\n\n    /**\n     * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function\n     * and {_fallback} should delegate.\n     */\n    function _implementation() internal view virtual returns (address);\n\n    /**\n     * @dev Delegates the current call to the address returned by `_implementation()`.\n     *\n     * This function does not return to its internal call site, it will return directly to the external caller.\n     */\n    function _fallback() internal virtual {\n        _beforeFallback();\n        _delegate(_implementation());\n    }\n\n    /**\n     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n     * function in the contract matches the call data.\n     */\n    fallback() external payable virtual {\n        _fallback();\n    }\n\n    /**\n     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n     * is empty.\n     */\n    receive() external payable virtual {\n        _fallback();\n    }\n\n    /**\n     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n     * call, or as part of the Solidity `fallback` or `receive` functions.\n     *\n     * If overridden should call `super._beforeFallback()`.\n     */\n    function _beforeFallback() internal virtual {}\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/utils/math/SafeMath.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)\n\npragma solidity ^0.8.0;\n\n// CAUTION\n// This version of SafeMath should only be used with Solidity 0.8 or later,\n// because it relies on the compiler's built in overflow checks.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations.\n *\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\n * now has built in overflow checking.\n */\nlibrary SafeMath {\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            uint256 c = a + b;\n            if (c < a) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b > a) return (false, 0);\n            return (true, a - b);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n            // benefit is lost if 'b' is also tested.\n            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n            if (a == 0) return (true, 0);\n            uint256 c = a * b;\n            if (c / a != b) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a / b);\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a % b);\n        }\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `+` operator.\n     *\n     * Requirements:\n     *\n     * - Addition cannot overflow.\n     */\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a + b;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting on\n     * overflow (when the result is negative).\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a - b;\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `*` operator.\n     *\n     * Requirements:\n     *\n     * - Multiplication cannot overflow.\n     */\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a * b;\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers, reverting on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator.\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a / b;\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * reverting when dividing by zero.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a % b;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n     * overflow (when the result is negative).\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {trySub}.\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(\n        uint256 a,\n        uint256 b,\n        string memory errorMessage\n    ) internal pure returns (uint256) {\n        unchecked {\n            require(b <= a, errorMessage);\n            return a - b;\n        }\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function div(\n        uint256 a,\n        uint256 b,\n        string memory errorMessage\n    ) internal pure returns (uint256) {\n        unchecked {\n            require(b > 0, errorMessage);\n            return a / b;\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * reverting with custom message when dividing by zero.\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {tryMod}.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function mod(\n        uint256 a,\n        uint256 b,\n        string memory errorMessage\n    ) internal pure returns (uint256) {\n        unchecked {\n            require(b > 0, errorMessage);\n            return a % b;\n        }\n    }\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/utils/Address.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\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     *\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://diligence.consensys.net/posts/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.5.11/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 functionCall(target, data, \"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(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) 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        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(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        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(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        require(isContract(target), \"Address: delegate call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason 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            // 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\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}\n"},{"file_path":"contracts/dependencies/openzeppelin-upgradeable/proxy/utils/Initializable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.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 * ```\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\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. Equivalent to `reinitializer(1)`.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = _setInitializedVersion(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     * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n     * initialization step. This is essential to configure modules that are added through upgrades and that require\n     * initialization.\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    modifier reinitializer(uint8 version) {\n        bool isTopLevelCall = _setInitializedVersion(version);\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(version);\n        }\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    function _disableInitializers() internal virtual {\n        _setInitializedVersion(type(uint8).max);\n    }\n\n    function _setInitializedVersion(uint8 version) private returns (bool) {\n        // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n        // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level\n        // of initializers, because in other contexts the contract may have been reentered.\n        if (_initializing) {\n            require(\n                version == 1 && !AddressUpgradeable.isContract(address(this)),\n                \"Initializable: contract is already initialized\"\n            );\n            return false;\n        } else {\n            require(_initialized < version, \"Initializable: contract is already initialized\");\n            _initialized = version;\n            return true;\n        }\n    }\n}\n"},{"file_path":"contracts/MetAirdrop.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {SafeERC20} from \"./dependencies/openzeppelin/token/ERC20/utils/SafeERC20.sol\";\nimport {IERC20} from \"./dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {Math} from \"./dependencies/openzeppelin/utils/math/Math.sol\";\nimport {RecurringAirdrop} from \"./utils/RecurringAirdrop.sol\";\nimport {IESMET} from \"./interfaces/external/IESMET.sol\";\n\n/**\n * @title MET Airdrop contract\n */\ncontract MetAirdrop is RecurringAirdrop {\n    using SafeERC20 for IERC20;\n    using Math for uint256;\n\n    IESMET public constant ESMET = IESMET(0xA28D70795a61Dc925D4c220762A4344803876bb8);\n    IERC20 public constant MET = IERC20(0x2Ebd53d035150f328bd754D6DC66B99B0eDB89aa);\n\n    /// @notice For how long `MET` tokens will be locked\n    uint256 public lockPeriod = 7 days;\n\n    constructor() RecurringAirdrop(MET) {}\n\n    /**\n     * @inheritdoc RecurringAirdrop\n     * @dev Locks the `MET` into `esMET` on user's behalf.\n     * The `lockPeriod` starts from the current merkle root update (i.e. `updatedAt`)\n     */\n    function _transferReward(address to_, uint256 amount_) internal override {\n        uint256 _end = updatedAt + lockPeriod;\n\n        if (_end < block.timestamp) {\n            MET.safeTransfer(to_, amount_);\n            return;\n        }\n\n        uint256 _min = ESMET.MINIMUM_LOCK_PERIOD() + 1;\n        uint256 _max = ESMET.MAXIMUM_LOCK_PERIOD();\n\n        // Ensures valid lock period\n        uint256 _remainLockPeriod = Math.min(Math.max(_end - block.timestamp, _min), _max);\n\n        token.safeApprove(address(ESMET), 0);\n        token.safeApprove(address(ESMET), amount_);\n        ESMET.lockFor(to_, amount_, _remainLockPeriod);\n    }\n\n    /**\n     * @notice Update esMET lock period\n     * @param lockPeriod_ The new value\n     */\n    function updateLockPeriod(uint256 lockPeriod_) public onlyGovernor {\n        lockPeriod = lockPeriod_;\n    }\n}\n"},{"file_path":"contracts/mock/PauseableMock.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {Pauseable} from \"../utils/Pauseable.sol\";\n\ncontract PauseableMock is Pauseable {\n    mapping(address => bool) internal _isGuardian;\n\n    function setGuardian(address address_, bool isGuardian_) external {\n        _isGuardian[address_] = isGuardian_;\n    }\n\n    function isGuardian(address sender_) public view override returns (bool) {\n        return _isGuardian[sender_];\n    }\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/libraries/LzLib.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.6.0;\npragma experimental ABIEncoderV2;\n\nlibrary LzLib {\n    // LayerZero communication\n    struct CallParams {\n        address payable refundAddress;\n        address zroPaymentAddress;\n    }\n\n    //---------------------------------------------------------------------------\n    // Address type handling\n\n    struct AirdropParams {\n        uint airdropAmount;\n        bytes32 airdropAddress;\n    }\n\n    function buildAdapterParams(\n        LzLib.AirdropParams memory _airdropParams,\n        uint _uaGasLimit\n    ) internal pure returns (bytes memory adapterParams) {\n        if (_airdropParams.airdropAmount == 0 && _airdropParams.airdropAddress == bytes32(0x0)) {\n            adapterParams = buildDefaultAdapterParams(_uaGasLimit);\n        } else {\n            adapterParams = buildAirdropAdapterParams(_uaGasLimit, _airdropParams);\n        }\n    }\n\n    // Build Adapter Params\n    function buildDefaultAdapterParams(uint _uaGas) internal pure returns (bytes memory) {\n        // txType 1\n        // bytes  [2       32      ]\n        // fields [txType  extraGas]\n        return abi.encodePacked(uint16(1), _uaGas);\n    }\n\n    function buildAirdropAdapterParams(uint _uaGas, AirdropParams memory _params) internal pure returns (bytes memory) {\n        require(_params.airdropAmount > 0, \"Airdrop amount must be greater than 0\");\n        require(_params.airdropAddress != bytes32(0x0), \"Airdrop address must be set\");\n\n        // txType 2\n        // bytes  [2       32        32            bytes[]         ]\n        // fields [txType  extraGas  dstNativeAmt  dstNativeAddress]\n        return abi.encodePacked(uint16(2), _uaGas, _params.airdropAmount, _params.airdropAddress);\n    }\n\n    function getGasLimit(bytes memory _adapterParams) internal pure returns (uint gasLimit) {\n        require(_adapterParams.length == 34 || _adapterParams.length > 66, \"Invalid adapterParams\");\n        assembly {\n            gasLimit := mload(add(_adapterParams, 34))\n        }\n    }\n\n    // Decode Adapter Params\n    function decodeAdapterParams(\n        bytes memory _adapterParams\n    ) internal pure returns (uint16 txType, uint uaGas, uint airdropAmount, address payable airdropAddress) {\n        require(_adapterParams.length == 34 || _adapterParams.length > 66, \"Invalid adapterParams\");\n        assembly {\n            txType := mload(add(_adapterParams, 2))\n            uaGas := mload(add(_adapterParams, 34))\n        }\n        require(txType == 1 || txType == 2, \"Unsupported txType\");\n        require(uaGas > 0, \"Gas too low\");\n\n        if (txType == 2) {\n            assembly {\n                airdropAmount := mload(add(_adapterParams, 66))\n                airdropAddress := mload(add(_adapterParams, 86))\n            }\n        }\n    }\n\n    //---------------------------------------------------------------------------\n    // Address type handling\n    function bytes32ToAddress(bytes32 _bytes32Address) internal pure returns (address _address) {\n        return address(uint160(uint(_bytes32Address)));\n    }\n\n    function addressToBytes32(address _address) internal pure returns (bytes32 _bytes32Address) {\n        return bytes32(uint(uint160(_address)));\n    }\n}\n"},{"file_path":"contracts/dependencies/openzeppelin-upgradeable/utils/AddressUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.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     *\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://diligence.consensys.net/posts/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.5.11/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 functionCall(target, data, \"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(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) 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        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(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        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason 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            // 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\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}\n"},{"file_path":"contracts/dependencies/openzeppelin/security/ReentrancyGuard.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\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 ReentrancyGuard {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    constructor() {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        // On the first call to nonReentrant, _notEntered will be true\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n\n        _;\n\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"},{"file_path":"contracts/dependencies/openzeppelin-upgradeable/utils/introspection/IERC165Upgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165Upgradeable {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/utils/math/Math.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a >= b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a / b + (a % b == 0 ? 0 : 1);\n    }\n}\n"},{"file_path":"contracts/storage/TreasuryStorage.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {ITreasury} from \"../interfaces/ITreasury.sol\";\n\n// solhint-disable-next-line no-empty-blocks\nabstract contract TreasuryStorageV1 is ITreasury {\n\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/utils/structs/EnumerableSet.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/EnumerableSet.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n *     // Add the library methods\n *     using EnumerableSet for EnumerableSet.AddressSet;\n *\n *     // Declare a set state variable\n *     EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n    // To implement this library for multiple types with as little code\n    // repetition as possible, we write it in terms of a generic Set type with\n    // bytes32 values.\n    // The Set implementation uses private functions, and user-facing\n    // implementations (such as AddressSet) are just wrappers around the\n    // underlying Set.\n    // This means that we can only create new EnumerableSets for types that fit\n    // in bytes32.\n\n    struct Set {\n        // Storage of set values\n        bytes32[] _values;\n        // Position of the value in the `values` array, plus 1 because index 0\n        // means a value is not in the set.\n        mapping(bytes32 => uint256) _indexes;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function _add(Set storage set, bytes32 value) private returns (bool) {\n        if (!_contains(set, value)) {\n            set._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._indexes[value] = set._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function _remove(Set storage set, bytes32 value) private returns (bool) {\n        // We read and store the value's index to prevent multiple reads from the same storage slot\n        uint256 valueIndex = set._indexes[value];\n\n        if (valueIndex != 0) {\n            // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 toDeleteIndex = valueIndex - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            if (lastIndex != toDeleteIndex) {\n                bytes32 lastValue = set._values[lastIndex];\n\n                // Move the last value to the index where the value to delete is\n                set._values[toDeleteIndex] = lastValue;\n                // Update the index for the moved value\n                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n            }\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the index for the deleted slot\n            delete set._indexes[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function _contains(Set storage set, bytes32 value) private view returns (bool) {\n        return set._indexes[value] != 0;\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function _length(Set storage set) private view returns (uint256) {\n        return set._values.length;\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function _at(Set storage set, uint256 index) private view returns (bytes32) {\n        return set._values[index];\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function _values(Set storage set) private view returns (bytes32[] memory) {\n        return set._values;\n    }\n\n    // Bytes32Set\n\n    struct Bytes32Set {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _add(set._inner, value);\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _remove(set._inner, value);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n        return _contains(set._inner, value);\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(Bytes32Set storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n        return _at(set._inner, index);\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n        return _values(set._inner);\n    }\n\n    // AddressSet\n\n    struct AddressSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(AddressSet storage set, address value) internal returns (bool) {\n        return _add(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(AddressSet storage set, address value) internal returns (bool) {\n        return _remove(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(AddressSet storage set, address value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(AddressSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(AddressSet storage set, uint256 index) internal view returns (address) {\n        return address(uint160(uint256(_at(set._inner, index))));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(AddressSet storage set) internal view returns (address[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        address[] memory result;\n\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // UintSet\n\n    struct UintSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(UintSet storage set, uint256 value) internal returns (bool) {\n        return _add(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(UintSet storage set, uint256 value) internal returns (bool) {\n        return _remove(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function length(UintSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n        return uint256(_at(set._inner, index));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(UintSet storage set) internal view returns (uint256[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        uint256[] memory result;\n\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n}\n"},{"file_path":"contracts/interfaces/IProxyOFT.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IComposableOFTCoreUpgradeable} from \"../dependencies/@layerzerolabs/solidity-examples/contracts-upgradeable/token/oft/composable/IComposableOFTCoreUpgradeable.sol\";\n\ninterface IProxyOFT is IComposableOFTCoreUpgradeable {\n    function getProxyOFTOf(uint16 chainId_) external view returns (address _proxyOFT);\n\n    function approvalRequired() external view returns (bool);\n\n    function oftFee() external view returns (uint256);\n\n    function quoteSendFromIn(uint256 amountOut_) external view returns (uint256 _amountIn, uint256 _fee);\n\n    function quoteSendFromOut(uint256 amountIn_) external view returns (uint256 _amountOut, uint256 _fee);\n\n    function updateOftFee(uint256 newOftFee_) external;\n}\n"},{"file_path":"contracts/interfaces/IPoolRegistry.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IMasterOracle} from \"./external/IMasterOracle.sol\";\nimport {IPauseable} from \"./IPauseable.sol\";\nimport {IGovernable} from \"./IGovernable.sol\";\nimport {ISyntheticToken} from \"./ISyntheticToken.sol\";\nimport {ISwapper} from \"./external/ISwapper.sol\";\nimport {IOperator} from \"./IOperator.sol\";\n\ninterface IPoolRegistry is IPauseable, IGovernable {\n    function feeCollector() external view returns (address);\n\n    function isPoolRegistered(address pool_) external view returns (bool);\n\n    function nativeTokenGateway() external view returns (address);\n\n    function getPools() external view returns (address[] memory);\n\n    function registerPool(address pool_) external;\n\n    function unregisterPool(address pool_) external;\n\n    function masterOracle() external view returns (IMasterOracle);\n\n    function updateFeeCollector(address newFeeCollector_) external;\n\n    function idOfPool(address pool_) external view returns (uint256);\n\n    function nextPoolId() external view returns (uint256);\n\n    function swapper() external view returns (ISwapper);\n\n    function doesSyntheticTokenExist(ISyntheticToken syntheticToken_) external view returns (bool _exists);\n\n    function operator() external view returns (IOperator);\n\n    function isGuardian(address) external view returns (bool);\n\n    function isBridgingActive() external view returns (bool);\n\n    function lzBaseGasLimit() external view returns (uint256);\n\n    function isDestinationChainSupported(uint16 dstChainId_) external view returns (bool);\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/token/oft/composable/IComposableOFTCore.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\nimport \"../IOFTCore.sol\";\n\n/**\n * @dev Interface of the composable OFT core standard\n */\ninterface IComposableOFTCore is IOFTCore {\n    function estimateSendAndCallFee(\n        uint16 _dstChainId,\n        bytes calldata _toAddress,\n        uint _amount,\n        bytes calldata _payload,\n        uint64 _dstGasForCall,\n        bool _useZro,\n        bytes calldata _adapterParams\n    ) external view returns (uint nativeFee, uint zroFee);\n\n    function sendAndCall(\n        address _from,\n        uint16 _dstChainId,\n        bytes calldata _toAddress,\n        uint _amount,\n        bytes calldata _payload,\n        uint64 _dstGasForCall,\n        address payable _refundAddress,\n        address _zroPaymentAddress,\n        bytes calldata _adapterParams\n    ) external payable;\n\n    function retryOFTReceived(\n        uint16 _srcChainId,\n        bytes calldata _srcAddress,\n        uint64 _nonce,\n        bytes calldata _from,\n        address _to,\n        uint _amount,\n        bytes calldata _payload\n    ) external;\n\n    event CallOFTReceivedFailure(\n        uint16 indexed _srcChainId,\n        bytes _srcAddress,\n        uint64 _nonce,\n        bytes _from,\n        address indexed _to,\n        uint _amount,\n        bytes _payload,\n        bytes _reason\n    );\n\n    event CallOFTReceivedSuccess(uint16 indexed _srcChainId, bytes _srcAddress, uint64 _nonce, bytes32 _hash);\n\n    event RetryOFTReceivedSuccess(bytes32 _messageHash);\n\n    event NonContractAddress(address _address);\n}\n"},{"file_path":"contracts/interfaces/IVesperGateway.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IPool} from \"./IPool.sol\";\nimport {IVPool} from \"./external/IVPool.sol\";\n\ninterface IVesperGateway {\n    function deposit(IPool pool_, IVPool vToken_, uint256 amount_) external;\n\n    function withdraw(IPool pool_, IVPool vToken_, uint256 amount_) external;\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/contracts-upgradeable/token/oft/composable/ComposableOFTCoreUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../OFTCoreUpgradeable.sol\";\nimport \"./IOFTReceiverUpgradeable.sol\";\nimport \"./IComposableOFTCoreUpgradeable.sol\";\nimport \"../../../../util/ExcessivelySafeCall.sol\";\n\nabstract contract ComposableOFTCoreUpgradeable is OFTCoreUpgradeable, IComposableOFTCoreUpgradeable {\n    using ExcessivelySafeCall for address;\n    using BytesLib for bytes;\n\n    // packet type\n    uint16 public constant PT_SEND_AND_CALL = 1;\n\n    mapping(uint16 => mapping(bytes => mapping(uint64 => bytes32))) public failedOFTReceivedMessages;\n\n    function __ComposableOFTCoreUpgradeable_init(address _lzEndpoint) internal onlyInitializing {\n        __OFTCoreUpgradeable_init(_lzEndpoint);\n    }\n\n    function __ComposableOFTCoreUpgradeable_init_unchained() internal onlyInitializing {}\n\n    function supportsInterface(\n        bytes4 interfaceId\n    ) public view virtual override(OFTCoreUpgradeable, IERC165Upgradeable) returns (bool) {\n        return interfaceId == type(IComposableOFTCoreUpgradeable).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    function estimateSendAndCallFee(\n        uint16 _dstChainId,\n        bytes calldata _toAddress,\n        uint _amount,\n        bytes calldata _payload,\n        uint64 _dstGasForCall,\n        bool _useZro,\n        bytes calldata _adapterParams\n    ) public view virtual override returns (uint nativeFee, uint zroFee) {\n        // mock the payload for sendAndCall()\n        bytes memory payload = abi.encode(\n            PT_SEND_AND_CALL,\n            abi.encodePacked(_msgSender()),\n            _toAddress,\n            _amount,\n            _payload,\n            _dstGasForCall\n        );\n        return lzEndpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _adapterParams);\n    }\n\n    function sendAndCall(\n        address _from,\n        uint16 _dstChainId,\n        bytes calldata _toAddress,\n        uint _amount,\n        bytes calldata _payload,\n        uint64 _dstGasForCall,\n        address payable _refundAddress,\n        address _zroPaymentAddress,\n        bytes calldata _adapterParams\n    ) public payable virtual override {\n        _sendAndCall(\n            _from,\n            _dstChainId,\n            _toAddress,\n            _amount,\n            _payload,\n            _dstGasForCall,\n            _refundAddress,\n            _zroPaymentAddress,\n            _adapterParams\n        );\n    }\n\n    function retryOFTReceived(\n        uint16 _srcChainId,\n        bytes calldata _srcAddress,\n        uint64 _nonce,\n        bytes calldata _from,\n        address _to,\n        uint _amount,\n        bytes calldata _payload\n    ) public virtual override {\n        bytes32 msgHash = failedOFTReceivedMessages[_srcChainId][_srcAddress][_nonce];\n        require(msgHash != bytes32(0), \"ComposableOFTCore: no failed message to retry\");\n\n        bytes32 hash = keccak256(abi.encode(_from, _to, _amount, _payload));\n        require(hash == msgHash, \"ComposableOFTCore: failed message hash mismatch\");\n\n        delete failedOFTReceivedMessages[_srcChainId][_srcAddress][_nonce];\n        IOFTReceiverUpgradeable(_to).onOFTReceived(_srcChainId, _srcAddress, _nonce, _from, _amount, _payload);\n        emit RetryOFTReceivedSuccess(hash);\n    }\n\n    function _nonblockingLzReceive(\n        uint16 _srcChainId,\n        bytes memory _srcAddress,\n        uint64 _nonce,\n        bytes memory _payload\n    ) internal virtual override {\n        uint16 packetType;\n        assembly {\n            packetType := mload(add(_payload, 32))\n        }\n\n        if (packetType == PT_SEND) {\n            _sendAck(_srcChainId, _srcAddress, _nonce, _payload);\n        } else if (packetType == PT_SEND_AND_CALL) {\n            _sendAndCallAck(_srcChainId, _srcAddress, _nonce, _payload);\n        } else {\n            revert(\"ComposableOFTCore: unknown packet type\");\n        }\n    }\n\n    function _sendAndCall(\n        address _from,\n        uint16 _dstChainId,\n        bytes memory _toAddress,\n        uint _amount,\n        bytes calldata _payload,\n        uint64 _dstGasForCall,\n        address payable _refundAddress,\n        address _zroPaymentAddress,\n        bytes memory _adapterParams\n    ) internal virtual {\n        _checkAdapterParams(_dstChainId, PT_SEND_AND_CALL, _adapterParams, _dstGasForCall);\n\n        uint amount = _debitFrom(_from, _dstChainId, _toAddress, _amount);\n\n        bytes memory lzPayload = abi.encode(\n            PT_SEND_AND_CALL,\n            abi.encodePacked(_msgSender()),\n            _toAddress,\n            amount,\n            _payload,\n            _dstGasForCall\n        );\n        _lzSend(_dstChainId, lzPayload, _refundAddress, _zroPaymentAddress, _adapterParams, msg.value);\n\n        emit SendToChain(_dstChainId, _from, _toAddress, amount);\n    }\n\n    function _sendAndCallAck(\n        uint16 _srcChainId,\n        bytes memory _srcAddress,\n        uint64 _nonce,\n        bytes memory _payload\n    ) internal virtual {\n        (, bytes memory from, bytes memory toAddress, uint amount, bytes memory payload, uint64 gasForCall) = abi\n            .decode(_payload, (uint16, bytes, bytes, uint, bytes, uint64));\n\n        address to = toAddress.toAddress(0);\n\n        amount = _creditTo(_srcChainId, to, amount);\n        emit ReceiveFromChain(_srcChainId, to, amount);\n\n        if (!_isContract(to)) {\n            emit NonContractAddress(to);\n            return;\n        }\n\n        _safeCallOnOFTReceived(_srcChainId, _srcAddress, _nonce, from, to, amount, payload, gasForCall);\n    }\n\n    function _safeCallOnOFTReceived(\n        uint16 _srcChainId,\n        bytes memory _srcAddress,\n        uint64 _nonce,\n        bytes memory _from,\n        address _to,\n        uint _amount,\n        bytes memory _payload,\n        uint _gasForCall\n    ) internal virtual {\n        (bool success, bytes memory reason) = _to.excessivelySafeCall(\n            _gasForCall,\n            150,\n            abi.encodeWithSelector(\n                IOFTReceiverUpgradeable.onOFTReceived.selector,\n                _srcChainId,\n                _srcAddress,\n                _nonce,\n                _from,\n                _amount,\n                _payload\n            )\n        );\n        if (!success) {\n            failedOFTReceivedMessages[_srcChainId][_srcAddress][_nonce] = keccak256(\n                abi.encode(_from, _to, _amount, _payload)\n            );\n            emit CallOFTReceivedFailure(_srcChainId, _srcAddress, _nonce, _from, _to, _amount, _payload, reason);\n        } else {\n            bytes32 hash = keccak256(abi.encode(_from, _to, _amount, _payload));\n            emit CallOFTReceivedSuccess(_srcChainId, _srcAddress, _nonce, hash);\n        }\n    }\n\n    function _isContract(address _account) internal view returns (bool) {\n        return _account.code.length > 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    uint[49] private __gap;\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/token/ERC20/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\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 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 `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, 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 `sender` to `recipient` 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(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) external returns (bool);\n\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"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/lzApp/NonblockingLzApp.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./LzApp.sol\";\nimport \"../util/ExcessivelySafeCall.sol\";\n\n/*\n * the default LayerZero messaging behaviour is blocking, i.e. any failed message will block the channel\n * this abstract class try-catch all fail messages and store locally for future retry. hence, non-blocking\n * NOTE: if the srcAddress is not configured properly, it will still block the message pathway from (srcChainId, srcAddress)\n */\nabstract contract NonblockingLzApp is LzApp {\n    using ExcessivelySafeCall for address;\n\n    constructor(address _endpoint) LzApp(_endpoint) {}\n\n    mapping(uint16 => mapping(bytes => mapping(uint64 => bytes32))) public failedMessages;\n\n    event MessageFailed(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes _payload, bytes _reason);\n    event RetryMessageSuccess(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes32 _payloadHash);\n\n    // overriding the virtual function in LzReceiver\n    function _blockingLzReceive(\n        uint16 _srcChainId,\n        bytes memory _srcAddress,\n        uint64 _nonce,\n        bytes memory _payload\n    ) internal virtual override {\n        (bool success, bytes memory reason) = address(this).excessivelySafeCall(\n            gasleft(),\n            150,\n            abi.encodeWithSelector(this.nonblockingLzReceive.selector, _srcChainId, _srcAddress, _nonce, _payload)\n        );\n        // try-catch all errors/exceptions\n        if (!success) {\n            _storeFailedMessage(_srcChainId, _srcAddress, _nonce, _payload, reason);\n        }\n    }\n\n    function _storeFailedMessage(\n        uint16 _srcChainId,\n        bytes memory _srcAddress,\n        uint64 _nonce,\n        bytes memory _payload,\n        bytes memory _reason\n    ) internal virtual {\n        failedMessages[_srcChainId][_srcAddress][_nonce] = keccak256(_payload);\n        emit MessageFailed(_srcChainId, _srcAddress, _nonce, _payload, _reason);\n    }\n\n    function nonblockingLzReceive(\n        uint16 _srcChainId,\n        bytes calldata _srcAddress,\n        uint64 _nonce,\n        bytes calldata _payload\n    ) public virtual {\n        // only internal transaction\n        require(_msgSender() == address(this), \"NonblockingLzApp: caller must be LzApp\");\n        _nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);\n    }\n\n    //@notice override this function\n    function _nonblockingLzReceive(\n        uint16 _srcChainId,\n        bytes memory _srcAddress,\n        uint64 _nonce,\n        bytes memory _payload\n    ) internal virtual;\n\n    function retryMessage(\n        uint16 _srcChainId,\n        bytes calldata _srcAddress,\n        uint64 _nonce,\n        bytes calldata _payload\n    ) public payable virtual {\n        // assert there is message to retry\n        bytes32 payloadHash = failedMessages[_srcChainId][_srcAddress][_nonce];\n        require(payloadHash != bytes32(0), \"NonblockingLzApp: no stored message\");\n        require(keccak256(_payload) == payloadHash, \"NonblockingLzApp: invalid payload\");\n        // clear the stored message\n        failedMessages[_srcChainId][_srcAddress][_nonce] = bytes32(0);\n        // execute the message. revert if it fails again\n        _nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);\n        emit RetryMessageSuccess(_srcChainId, _srcAddress, _nonce, payloadHash);\n    }\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/util/BytesLib.sol","source_code":"// SPDX-License-Identifier: Unlicense\n/*\n * @title Solidity Bytes Arrays Utils\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\n *\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\n */\npragma solidity >=0.8.0 <0.9.0;\n\nlibrary BytesLib {\n    function concat(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bytes memory) {\n        bytes memory tempBytes;\n\n        assembly {\n            // Get a location of some free memory and store it in tempBytes as\n            // Solidity does for memory variables.\n            tempBytes := mload(0x40)\n\n            // Store the length of the first bytes array at the beginning of\n            // the memory for tempBytes.\n            let length := mload(_preBytes)\n            mstore(tempBytes, length)\n\n            // Maintain a memory counter for the current write location in the\n            // temp bytes array by adding the 32 bytes for the array length to\n            // the starting location.\n            let mc := add(tempBytes, 0x20)\n            // Stop copying when the memory counter reaches the length of the\n            // first bytes array.\n            let end := add(mc, length)\n\n            for {\n                // Initialize a copy counter to the start of the _preBytes data,\n                // 32 bytes into its memory.\n                let cc := add(_preBytes, 0x20)\n            } lt(mc, end) {\n                // Increase both counters by 32 bytes each iteration.\n                mc := add(mc, 0x20)\n                cc := add(cc, 0x20)\n            } {\n                // Write the _preBytes data into the tempBytes memory 32 bytes\n                // at a time.\n                mstore(mc, mload(cc))\n            }\n\n            // Add the length of _postBytes to the current length of tempBytes\n            // and store it as the new length in the first 32 bytes of the\n            // tempBytes memory.\n            length := mload(_postBytes)\n            mstore(tempBytes, add(length, mload(tempBytes)))\n\n            // Move the memory counter back from a multiple of 0x20 to the\n            // actual end of the _preBytes data.\n            mc := end\n            // Stop copying when the memory counter reaches the new combined\n            // length of the arrays.\n            end := add(mc, length)\n\n            for {\n                let cc := add(_postBytes, 0x20)\n            } lt(mc, end) {\n                mc := add(mc, 0x20)\n                cc := add(cc, 0x20)\n            } {\n                mstore(mc, mload(cc))\n            }\n\n            // Update the free-memory pointer by padding our last write location\n            // to 32 bytes: add 31 bytes to the end of tempBytes to move to the\n            // next 32 byte block, then round down to the nearest multiple of\n            // 32. If the sum of the length of the two arrays is zero then add\n            // one before rounding down to leave a blank 32 bytes (the length block with 0).\n            mstore(\n                0x40,\n                and(\n                    add(add(end, iszero(add(length, mload(_preBytes)))), 31),\n                    not(31) // Round down to the nearest 32 bytes.\n                )\n            )\n        }\n\n        return tempBytes;\n    }\n\n    function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {\n        assembly {\n            // Read the first 32 bytes of _preBytes storage, which is the length\n            // of the array. (We don't need to use the offset into the slot\n            // because arrays use the entire slot.)\n            let fslot := sload(_preBytes.slot)\n            // Arrays of 31 bytes or less have an even value in their slot,\n            // while longer arrays have an odd value. The actual length is\n            // the slot divided by two for odd values, and the lowest order\n            // byte divided by two for even values.\n            // If the slot is even, bitwise and the slot with 255 and divide by\n            // two to get the length. If the slot is odd, bitwise and the slot\n            // with -1 and divide by two.\n            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)\n            let mlength := mload(_postBytes)\n            let newlength := add(slength, mlength)\n            // slength can contain both the length and contents of the array\n            // if length < 32 bytes so let's prepare for that\n            // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage\n            switch add(lt(slength, 32), lt(newlength, 32))\n            case 2 {\n                // Since the new array still fits in the slot, we just need to\n                // update the contents of the slot.\n                // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length\n                sstore(\n                    _preBytes.slot,\n                    // all the modifications to the slot are inside this\n                    // next block\n                    add(\n                        // we can just add to the slot contents because the\n                        // bytes we want to change are the LSBs\n                        fslot,\n                        add(\n                            mul(\n                                div(\n                                    // load the bytes from memory\n                                    mload(add(_postBytes, 0x20)),\n                                    // zero all bytes to the right\n                                    exp(0x100, sub(32, mlength))\n                                ),\n                                // and now shift left the number of bytes to\n                                // leave space for the length in the slot\n                                exp(0x100, sub(32, newlength))\n                            ),\n                            // increase length by the double of the memory\n                            // bytes length\n                            mul(mlength, 2)\n                        )\n                    )\n                )\n            }\n            case 1 {\n                // The stored value fits in the slot, but the combined value\n                // will exceed it.\n                // get the keccak hash to get the contents of the array\n                mstore(0x0, _preBytes.slot)\n                let sc := add(keccak256(0x0, 0x20), div(slength, 32))\n\n                // save new length\n                sstore(_preBytes.slot, add(mul(newlength, 2), 1))\n\n                // The contents of the _postBytes array start 32 bytes into\n                // the structure. Our first read should obtain the `submod`\n                // bytes that can fit into the unused space in the last word\n                // of the stored array. To get this, we read 32 bytes starting\n                // from `submod`, so the data we read overlaps with the array\n                // contents by `submod` bytes. Masking the lowest-order\n                // `submod` bytes allows us to add that value directly to the\n                // stored value.\n\n                let submod := sub(32, slength)\n                let mc := add(_postBytes, submod)\n                let end := add(_postBytes, mlength)\n                let mask := sub(exp(0x100, submod), 1)\n\n                sstore(\n                    sc,\n                    add(\n                        and(fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00),\n                        and(mload(mc), mask)\n                    )\n                )\n\n                for {\n                    mc := add(mc, 0x20)\n                    sc := add(sc, 1)\n                } lt(mc, end) {\n                    sc := add(sc, 1)\n                    mc := add(mc, 0x20)\n                } {\n                    sstore(sc, mload(mc))\n                }\n\n                mask := exp(0x100, sub(mc, end))\n\n                sstore(sc, mul(div(mload(mc), mask), mask))\n            }\n            default {\n                // get the keccak hash to get the contents of the array\n                mstore(0x0, _preBytes.slot)\n                // Start copying to the last used word of the stored array.\n                let sc := add(keccak256(0x0, 0x20), div(slength, 32))\n\n                // save new length\n                sstore(_preBytes.slot, add(mul(newlength, 2), 1))\n\n                // Copy over the first `submod` bytes of the new data as in\n                // case 1 above.\n                let slengthmod := mod(slength, 32)\n                let mlengthmod := mod(mlength, 32)\n                let submod := sub(32, slengthmod)\n                let mc := add(_postBytes, submod)\n                let end := add(_postBytes, mlength)\n                let mask := sub(exp(0x100, submod), 1)\n\n                sstore(sc, add(sload(sc), and(mload(mc), mask)))\n\n                for {\n                    sc := add(sc, 1)\n                    mc := add(mc, 0x20)\n                } lt(mc, end) {\n                    sc := add(sc, 1)\n                    mc := add(mc, 0x20)\n                } {\n                    sstore(sc, mload(mc))\n                }\n\n                mask := exp(0x100, sub(mc, end))\n\n                sstore(sc, mul(div(mload(mc), mask), mask))\n            }\n        }\n    }\n\n    function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) {\n        require(_length + 31 >= _length, \"slice_overflow\");\n        require(_bytes.length >= _start + _length, \"slice_outOfBounds\");\n\n        bytes memory tempBytes;\n\n        assembly {\n            switch iszero(_length)\n            case 0 {\n                // Get a location of some free memory and store it in tempBytes as\n                // Solidity does for memory variables.\n                tempBytes := mload(0x40)\n\n                // The first word of the slice result is potentially a partial\n                // word read from the original array. To read it, we calculate\n                // the length of that partial word and start copying that many\n                // bytes into the array. The first word we copy will start with\n                // data we don't care about, but the last `lengthmod` bytes will\n                // land at the beginning of the contents of the new array. When\n                // we're done copying, we overwrite the full first word with\n                // the actual length of the slice.\n                let lengthmod := and(_length, 31)\n\n                // The multiplication in the next line is necessary\n                // because when slicing multiples of 32 bytes (lengthmod == 0)\n                // the following copy loop was copying the origin's length\n                // and then ending prematurely not copying everything it should.\n                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n                let end := add(mc, _length)\n\n                for {\n                    // The multiplication in the next line has the same exact purpose\n                    // as the one above.\n                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n                } lt(mc, end) {\n                    mc := add(mc, 0x20)\n                    cc := add(cc, 0x20)\n                } {\n                    mstore(mc, mload(cc))\n                }\n\n                mstore(tempBytes, _length)\n\n                //update free-memory pointer\n                //allocating the array padded to 32 bytes like the compiler does now\n                mstore(0x40, and(add(mc, 31), not(31)))\n            }\n            //if we want a zero-length slice let's just return a zero-length array\n            default {\n                tempBytes := mload(0x40)\n                //zero out the 32 bytes slice we are about to return\n                //we need to do it because Solidity does not garbage collect\n                mstore(tempBytes, 0)\n\n                mstore(0x40, add(tempBytes, 0x20))\n            }\n        }\n\n        return tempBytes;\n    }\n\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\n        require(_bytes.length >= _start + 20, \"toAddress_outOfBounds\");\n        address tempAddress;\n\n        assembly {\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\n        }\n\n        return tempAddress;\n    }\n\n    function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {\n        require(_bytes.length >= _start + 1, \"toUint8_outOfBounds\");\n        uint8 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x1), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {\n        require(_bytes.length >= _start + 2, \"toUint16_outOfBounds\");\n        uint16 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x2), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {\n        require(_bytes.length >= _start + 4, \"toUint32_outOfBounds\");\n        uint32 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x4), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {\n        require(_bytes.length >= _start + 8, \"toUint64_outOfBounds\");\n        uint64 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x8), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {\n        require(_bytes.length >= _start + 12, \"toUint96_outOfBounds\");\n        uint96 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0xc), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {\n        require(_bytes.length >= _start + 16, \"toUint128_outOfBounds\");\n        uint128 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x10), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {\n        require(_bytes.length >= _start + 32, \"toUint256_outOfBounds\");\n        uint256 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x20), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {\n        require(_bytes.length >= _start + 32, \"toBytes32_outOfBounds\");\n        bytes32 tempBytes32;\n\n        assembly {\n            tempBytes32 := mload(add(add(_bytes, 0x20), _start))\n        }\n\n        return tempBytes32;\n    }\n\n    function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {\n        bool success = true;\n\n        assembly {\n            let length := mload(_preBytes)\n\n            // if lengths don't match the arrays are not equal\n            switch eq(length, mload(_postBytes))\n            case 1 {\n                // cb is a circuit breaker in the for loop since there's\n                //  no said feature for inline assembly loops\n                // cb = 1 - don't breaker\n                // cb = 0 - break\n                let cb := 1\n\n                let mc := add(_preBytes, 0x20)\n                let end := add(mc, length)\n\n                for {\n                    let cc := add(_postBytes, 0x20)\n                    // the next line is the loop condition:\n                    // while(uint256(mc < end) + cb == 2)\n                } eq(add(lt(mc, end), cb), 2) {\n                    mc := add(mc, 0x20)\n                    cc := add(cc, 0x20)\n                } {\n                    // if any of these checks fails then arrays are not equal\n                    if iszero(eq(mload(mc), mload(cc))) {\n                        // unsuccess:\n                        success := 0\n                        cb := 0\n                    }\n                }\n            }\n            default {\n                // unsuccess:\n                success := 0\n            }\n        }\n\n        return success;\n    }\n\n    function equalStorage(bytes storage _preBytes, bytes memory _postBytes) internal view returns (bool) {\n        bool success = true;\n\n        assembly {\n            // we know _preBytes_offset is 0\n            let fslot := sload(_preBytes.slot)\n            // Decode the length of the stored array like in concatStorage().\n            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)\n            let mlength := mload(_postBytes)\n\n            // if lengths don't match the arrays are not equal\n            switch eq(slength, mlength)\n            case 1 {\n                // slength can contain both the length and contents of the array\n                // if length < 32 bytes so let's prepare for that\n                // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage\n                if iszero(iszero(slength)) {\n                    switch lt(slength, 32)\n                    case 1 {\n                        // blank the last byte which is the length\n                        fslot := mul(div(fslot, 0x100), 0x100)\n\n                        if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {\n                            // unsuccess:\n                            success := 0\n                        }\n                    }\n                    default {\n                        // cb is a circuit breaker in the for loop since there's\n                        //  no said feature for inline assembly loops\n                        // cb = 1 - don't breaker\n                        // cb = 0 - break\n                        let cb := 1\n\n                        // get the keccak hash to get the contents of the array\n                        mstore(0x0, _preBytes.slot)\n                        let sc := keccak256(0x0, 0x20)\n\n                        let mc := add(_postBytes, 0x20)\n                        let end := add(mc, mlength)\n\n                        // the next line is the loop condition:\n                        // while(uint256(mc < end) + cb == 2)\n                        for {\n\n                        } eq(add(lt(mc, end), cb), 2) {\n                            sc := add(sc, 1)\n                            mc := add(mc, 0x20)\n                        } {\n                            if iszero(eq(sload(sc), mload(mc))) {\n                                // unsuccess:\n                                success := 0\n                                cb := 0\n                            }\n                        }\n                    }\n                }\n            }\n            default {\n                // unsuccess:\n                success := 0\n            }\n        }\n\n        return success;\n    }\n}\n"},{"file_path":"contracts/storage/SmartFarmingManagerStorage.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IERC20} from \"../dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {ISmartFarmingManager} from \"../interfaces/ISmartFarmingManager.sol\";\nimport {IDepositToken} from \"../interfaces/IDepositToken.sol\";\nimport {ISyntheticToken} from \"../interfaces/ISyntheticToken.sol\";\n\n// solhint-disable var-name-mixedcase, max-states-count\nabstract contract SmartFarmingManagerStorageV1 is ISmartFarmingManager {\n    struct CrossChainLeverage {\n        uint16 dstChainId;\n        IERC20 bridgeToken;\n        IDepositToken depositToken;\n        ISyntheticToken syntheticToken;\n        uint256 amountIn;\n        uint256 debtAmount;\n        uint256 depositAmountMin;\n        address account;\n        bool finished;\n        IERC20 tokenIn;\n    }\n\n    struct CrossChainFlashRepay {\n        uint16 dstChainId;\n        ISyntheticToken syntheticToken;\n        uint256 repayAmountMin;\n        address account;\n        bool finished;\n    }\n\n    uint256 private crossChainRequestsLength__DEPRECATED;\n\n    mapping(uint256 => CrossChainLeverage) private crossChainLeverages__DEPRECATED;\n\n    mapping(uint256 => CrossChainFlashRepay) private crossChainFlashRepays__DEPRECATED;\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/utils/introspection/ERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"},{"file_path":"contracts/RewardsDistributor.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {Initializable} from \"./dependencies/openzeppelin-upgradeable/proxy/utils/Initializable.sol\";\nimport {IERC20} from \"./dependencies/openzeppelin/token/ERC20/IERC20.sol\";\nimport {SafeCast} from \"./dependencies/openzeppelin/utils/math/SafeCast.sol\";\nimport {SafeERC20} from \"./dependencies/openzeppelin/token/ERC20/utils/SafeERC20.sol\";\nimport {ReentrancyGuardDeprecated} from \"./utils/ReentrancyGuardDeprecated.sol\";\nimport {ReentrancyGuardTransient} from \"./utils/ReentrancyGuardTransient.sol\";\nimport {IDebtToken} from \"./interfaces/IDebtToken.sol\";\nimport {IDepositToken} from \"./interfaces/IDepositToken.sol\";\nimport {Manageable} from \"./access/Manageable.sol\";\nimport {RewardsDistributorStorageV2} from \"./storage/RewardsDistributorStorage.sol\";\nimport {WadRayMath} from \"./lib/WadRayMath.sol\";\nimport {IPool} from \"./interfaces/IPool.sol\";\nimport {IVPool} from \"./interfaces/external/IVPool.sol\";\nimport {IPoolRewards} from \"./interfaces/external/IPoolRewards.sol\";\n\n/// @notice Updated to IPoolRewards will trigger treasury upgrade and we want to avoid it.\n/// Hence defining new interface here.\ninterface IPoolRewardsExt is IPoolRewards {\n    function rewardRates(address rewardToken_) external returns (uint256);\n\n    function periodFinish(address rewardToken_) external returns (uint256);\n}\n\nerror AddressIsNull();\nerror NotTokenSpeedKeeper();\nerror DistributorDoesNotExist();\nerror InvalidToken();\nerror RewardTokenIsNull();\nerror ReachedMaxRewardTokens();\nerror ArraysLengthDoNotMatch();\n\n/**\n * @title RewardsDistributor contract\n */\ncontract RewardsDistributor is\n    Initializable,\n    ReentrancyGuardDeprecated,\n    ReentrancyGuardTransient,\n    Manageable,\n    RewardsDistributorStorageV2\n{\n    using SafeERC20 for IERC20;\n    using SafeCast for uint256;\n    using WadRayMath for uint256;\n\n    string public constant VERSION = \"1.4.1\";\n\n    /// @notice The initial index\n    uint224 public constant INITIAL_INDEX = 1e18;\n\n    /// @notice Max reward tokens to avoid DoS scenario\n    uint224 public constant MAX_REWARD_TOKENS = 20;\n\n    /// @notice Emitted when reward is claimed\n    event RewardClaimed(address indexed account, uint256 amount);\n\n    /// @notice Emitted when updating accrued token\n    event TokensAccruedUpdated(IERC20 indexed token, address indexed account, uint256 tokensDelta, uint256 supplyIndex);\n\n    /// @notice Emitted when updating token speed\n    event TokenSpeedUpdated(IERC20 indexed token, uint256 oldSpeed, uint256 newSpeed);\n\n    /// @notice Emitted when updating token index\n    event TokenIndexUpdated(uint224 newIndex, uint32 newTimestamp);\n\n    /**\n     * @dev Throws if this contract isn't registered on pool\n     */\n    modifier onlyIfDistributorExists() {\n        bool _distributorAdded = false;\n        address[] memory _rewardsDistributors = pool.getRewardsDistributors();\n        uint256 _length = _rewardsDistributors.length;\n        for (uint256 i; i < _length; ++i) {\n            if (_rewardsDistributors[i] == address(this)) {\n                _distributorAdded = true;\n                break;\n            }\n        }\n        if (!_distributorAdded) revert DistributorDoesNotExist();\n        _;\n    }\n\n    /**\n     * @dev Throws if token doesn't exist\n     * @dev Should be a DepositToken (suppliers) or DebtToken (borrowers)\n     */\n    modifier onlyIfTokenExists(address token_) {\n        IPool _pool = pool;\n        if (!_pool.doesDebtTokenExist(IDebtToken(token_)) && !_pool.doesDepositTokenExist(IDepositToken(token_))) {\n            revert InvalidToken();\n        }\n        _;\n    }\n\n    constructor() {\n        _disableInitializers();\n    }\n\n    function initialize(IPool pool_, IERC20 rewardToken_) external initializer {\n        if (address(rewardToken_) == address(0)) revert RewardTokenIsNull();\n\n        __Manageable_init(pool_);\n\n        rewardToken = rewardToken_;\n    }\n\n    /**\n     * @notice Returns claimable amount consider all tokens\n     */\n    function claimable(address account_) external view override returns (uint256 _claimable) {\n        _claimable = tokensAccruedOf[account_];\n        uint256 _len = tokens.length;\n        for (uint256 i; i < _len; ++i) {\n            _claimable += _claimableRewards(account_, tokens[i]);\n        }\n    }\n\n    /**\n     * @notice Returns updated claimable amount for given token\n     * @dev Removing this function will change interface and will result\n     * updating other contracts using interface.\n     */\n    function claimable(address, IERC20) public view override returns (uint256) {\n        revert(\"Unsupported\");\n    }\n\n    /**\n     * @notice Claim tokens accrued by account in all tokens\n     */\n    function claimRewards(address account_) external override {\n        claimRewards(account_, tokens);\n    }\n\n    /**\n     * @notice Claim tokens accrued by account in the specified tokens\n     */\n    function claimRewards(address account_, IERC20[] memory tokens_) public override {\n        address[] memory _accounts = new address[](1);\n        _accounts[0] = account_;\n        claimRewards(_accounts, tokens_);\n    }\n\n    /**\n     * @notice Claim tokens accrued by the accounts in the specified tokens\n     */\n    function claimRewards(address[] memory accounts_, IERC20[] memory tokens_) public override nonReentrant {\n        uint256 _accountsLength = accounts_.length;\n        uint256 _tokensLength = tokens_.length;\n        for (uint256 i; i < _tokensLength; ++i) {\n            IERC20 _token = tokens_[i];\n\n            if (tokenStates[_token].index > 0) {\n                _updateTokenIndex(_token);\n                for (uint256 j; j < _accountsLength; j++) {\n                    _updateTokensAccruedOf(_token, accounts_[j]);\n                }\n            }\n        }\n\n        for (uint256 j; j < _accountsLength; j++) {\n            address _account = accounts_[j];\n            _transferRewardIfEnoughTokens(_account, tokensAccruedOf[_account]);\n        }\n    }\n\n    /**\n     * @notice Update indexes on pre-mint and pre-burn\n     * @dev Called by DepositToken and DebtToken contracts\n     * This function also may be called by anyone to update stored indexes\n     */\n    function updateBeforeMintOrBurn(IERC20 token_, address account_) external override {\n        if (tokenStates[token_].index > 0) {\n            _updateTokenIndex(token_);\n            _updateTokensAccruedOf(token_, account_);\n        }\n    }\n\n    /**\n     * @notice Update indexes on pre-transfer\n     * @dev Called by DepositToken and DebtToken contracts\n     */\n    function updateBeforeTransfer(IERC20 token_, address from_, address to_) external override {\n        if (tokenStates[token_].index > 0) {\n            _updateTokenIndex(token_);\n            _updateTokensAccruedOf(token_, from_);\n            _updateTokensAccruedOf(token_, to_);\n        }\n    }\n\n    /**\n     * @notice Calculate updated token index values\n     */\n    function _calculateTokenIndex(\n        TokenState memory _supplyState,\n        IERC20 token_\n    ) private view returns (uint224 _newIndex, uint32 _newTimestamp) {\n        uint256 _speed = tokenSpeeds[token_];\n        uint256 _deltaTimestamps = block.timestamp - uint256(_supplyState.timestamp);\n        if (_deltaTimestamps > 0 && _speed > 0) {\n            uint256 _totalSupply = token_.totalSupply();\n            uint256 _tokensAccrued = _deltaTimestamps * _speed;\n            uint256 _ratio = _totalSupply > 0 ? _tokensAccrued.wadDiv(_totalSupply) : 0;\n            _newIndex = (_supplyState.index + _ratio).toUint224();\n            _newTimestamp = block.timestamp.toUint32();\n        } else if (_deltaTimestamps > 0 && _supplyState.index > 0) {\n            _newTimestamp = block.timestamp.toUint32();\n        }\n    }\n\n    /**\n     * @notice Calculate updated account index and claimable values\n     */\n    function _calculateTokenDelta(\n        TokenState memory _tokenState,\n        IERC20 token_,\n        address account_\n    ) private view returns (uint256 _tokenIndex, uint256 _tokensDelta) {\n        _tokenIndex = _tokenState.index;\n        uint256 _accountIndex = accountIndexOf[token_][account_];\n\n        if (_accountIndex == 0 && _tokenIndex > INITIAL_INDEX) {\n            _accountIndex = INITIAL_INDEX;\n        }\n\n        uint256 _deltaIndex = _tokenIndex - _accountIndex;\n        _tokensDelta = token_.balanceOf(account_).wadMul(_deltaIndex);\n    }\n\n    function _claimableRewards(address account_, IERC20 token_) internal view returns (uint256 _claimableDelta) {\n        TokenState memory _tokenState = tokenStates[token_];\n        (uint224 _newIndex, uint32 _newTimestamp) = _calculateTokenIndex(_tokenState, token_);\n        if (_newIndex > 0 && _newTimestamp > 0) {\n            _tokenState = TokenState({index: _newIndex, timestamp: _newTimestamp});\n        } else if (_newTimestamp > 0) {\n            _tokenState.timestamp = _newTimestamp;\n        }\n        (, _claimableDelta) = _calculateTokenDelta(_tokenState, token_, account_);\n    }\n\n    /**\n     * @notice Transfer tokens to the user\n     * @dev If there is not enough tokens, we do not perform the transfer\n     */\n    function _transferRewardIfEnoughTokens(address account_, uint256 amount_) private {\n        IERC20 _rewardToken = rewardToken;\n        uint256 _balance = _rewardToken.balanceOf(address(this));\n        if (amount_ > 0 && amount_ <= _balance) {\n            tokensAccruedOf[account_] = 0;\n            _rewardToken.safeTransfer(account_, amount_);\n            emit RewardClaimed(account_, amount_);\n        }\n    }\n\n    /**\n     * @notice Calculate tokens accrued by an account\n     */\n    function _updateTokensAccruedOf(IERC20 token_, address account_) private {\n        (uint256 _tokenIndex, uint256 _tokensDelta) = _calculateTokenDelta(tokenStates[token_], token_, account_);\n        accountIndexOf[token_][account_] = _tokenIndex;\n        tokensAccruedOf[account_] = tokensAccruedOf[account_] + _tokensDelta;\n        emit TokensAccruedUpdated(token_, account_, _tokensDelta, _tokenIndex);\n    }\n\n    /**\n     * @notice Accrue reward token by updating the index\n     */\n    function _updateTokenIndex(IERC20 token_) private {\n        TokenState storage _supplyState = tokenStates[token_];\n        (uint224 _newIndex, uint32 _newTimestamp) = _calculateTokenIndex(_supplyState, token_);\n        if (_newIndex > 0 && _newTimestamp > 0) {\n            _supplyState.index = _newIndex;\n            _supplyState.timestamp = _newTimestamp;\n            emit TokenIndexUpdated(_newIndex, _newTimestamp);\n        } else if (_newTimestamp > 0) {\n            _supplyState.timestamp = _newTimestamp;\n            emit TokenIndexUpdated(_supplyState.index, _newTimestamp);\n        }\n    }\n\n    /**\n     * @notice Update the speed for token\n     */\n    function _updateTokenSpeed(\n        IERC20 token_,\n        uint256 newSpeed_\n    ) private onlyIfDistributorExists onlyIfTokenExists(address(token_)) {\n        uint256 _currentSpeed = tokenSpeeds[token_];\n        if (_currentSpeed > 0) {\n            _updateTokenIndex(token_);\n        } else if (newSpeed_ > 0) {\n            // Add token to the list\n            if (tokenStates[token_].index == 0) {\n                if (tokens.length == MAX_REWARD_TOKENS) revert ReachedMaxRewardTokens();\n                tokenStates[token_] = TokenState({index: INITIAL_INDEX, timestamp: block.timestamp.toUint32()});\n                tokens.push(token_);\n            } else {\n                // Update timestamp to ensure extra interest is not accrued during the prior period\n                tokenStates[token_].timestamp = block.timestamp.toUint32();\n            }\n        }\n\n        if (_currentSpeed != newSpeed_) {\n            tokenSpeeds[token_] = newSpeed_;\n            emit TokenSpeedUpdated(token_, _currentSpeed, newSpeed_);\n        }\n    }\n\n    /**\n     * @notice Update speed for a single deposit token\n     */\n    function updateTokenSpeed(IERC20 token_, uint256 newSpeed_) external override onlyGovernor {\n        _updateTokenSpeed(token_, newSpeed_);\n    }\n\n    /**\n     * @notice Update token speeds\n     */\n    function updateTokenSpeeds(IERC20[] calldata tokens_, uint256[] calldata speeds_) external override onlyGovernor {\n        uint256 _tokensLength = tokens_.length;\n        if (_tokensLength != speeds_.length) revert ArraysLengthDoNotMatch();\n\n        for (uint256 i; i < _tokensLength; ++i) {\n            _updateTokenSpeed(tokens_[i], speeds_[i]);\n        }\n    }\n\n    //********************************  TokenSpeed and RewardRate sync fix ***********************************/\n    /// @notice This is temporary fix to keep tokenSpeed and rewardRate from Vesper in sync.\n    function syncTokenSpeed(IDepositToken depositToken_) external {\n        if (_msgSender() != tokenSpeedKeeper) revert NotTokenSpeedKeeper();\n\n        IVPool _vPool = IVPool(address(depositToken_.underlying()));\n        IPoolRewardsExt _rewards = IPoolRewardsExt(_vPool.poolRewards());\n\n        uint256 _speed;\n\n        if (block.timestamp < _rewards.periodFinish(address(rewardToken))) {\n            _speed =\n                (_rewards.rewardRates(address(rewardToken)) * _vPool.balanceOf(address(pool.treasury()))) /\n                _vPool.totalSupply();\n        }\n\n        _updateTokenSpeed(IERC20(address(depositToken_)), _speed);\n    }\n\n    /// @notice This function is part of temporary fix to keep tokenSpeed and rewardRate in sync.\n    function updateTokenSpeedKeeper(address keeper_) external onlyGovernor {\n        if (keeper_ == address(0)) revert AddressIsNull();\n        tokenSpeedKeeper = keeper_;\n    }\n}\n"},{"file_path":"contracts/dependencies/stargate-protocol/LPTokenERC20.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.9;\n\n// libraries\nimport \"../openzeppelin/utils/math/SafeMath.sol\";\n\ncontract LPTokenERC20 {\n    using SafeMath for uint256;\n\n    //---------------------------------------------------------------------------\n    // CONSTANTS\n    string public name;\n    string public symbol;\n    bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n    // set in constructor\n    bytes32 public DOMAIN_SEPARATOR;\n\n    //---------------------------------------------------------------------------\n    // VARIABLES\n    uint256 public decimals;\n    uint256 public totalSupply;\n    mapping(address => uint256) public balanceOf;\n    mapping(address => mapping(address => uint256)) public allowance;\n    mapping(address => uint256) public nonces;\n\n    //---------------------------------------------------------------------------\n    // EVENTS\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    constructor(string memory _name, string memory _symbol) {\n        name = _name;\n        symbol = _symbol;\n        uint256 chainId;\n        assembly {\n            chainId := chainid()\n        }\n        DOMAIN_SEPARATOR = keccak256(\n            abi.encode(\n                keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n                keccak256(bytes(name)),\n                keccak256(bytes(\"1\")),\n                chainId,\n                address(this)\n            )\n        );\n    }\n\n    function _mint(address to, uint256 value) internal {\n        totalSupply = totalSupply.add(value);\n        balanceOf[to] = balanceOf[to].add(value);\n        emit Transfer(address(0), to, value);\n    }\n\n    function _burn(address from, uint256 value) internal {\n        balanceOf[from] = balanceOf[from].sub(value);\n        totalSupply = totalSupply.sub(value);\n        emit Transfer(from, address(0), value);\n    }\n\n    function _approve(address owner, address spender, uint256 value) private {\n        allowance[owner][spender] = value;\n        emit Approval(owner, spender, value);\n    }\n\n    function _transfer(address from, address to, uint256 value) private {\n        balanceOf[from] = balanceOf[from].sub(value);\n        balanceOf[to] = balanceOf[to].add(value);\n        emit Transfer(from, to, value);\n    }\n\n    function approve(address spender, uint256 value) external returns (bool) {\n        _approve(msg.sender, spender, value);\n        return true;\n    }\n\n    function transfer(address to, uint256 value) external returns (bool) {\n        _transfer(msg.sender, to, value);\n        return true;\n    }\n\n    function transferFrom(address from, address to, uint256 value) external returns (bool) {\n        if (allowance[from][msg.sender] != type(uint256).max) {\n            allowance[from][msg.sender] = allowance[from][msg.sender].sub(value);\n        }\n        _transfer(from, to, value);\n        return true;\n    }\n\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n        _approve(msg.sender, spender, allowance[msg.sender][spender].add(addedValue));\n        return true;\n    }\n\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n        _approve(\n            msg.sender,\n            spender,\n            allowance[msg.sender][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\")\n        );\n        return true;\n    }\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        require(deadline >= block.timestamp, \"Bridge: EXPIRED\");\n        bytes32 digest = keccak256(\n            abi.encodePacked(\n                \"\\x19\\x01\",\n                DOMAIN_SEPARATOR,\n                keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))\n            )\n        );\n        address recoveredAddress = ecrecover(digest, v, r, s);\n        require(recoveredAddress != address(0) && recoveredAddress == owner, \"Bridge: INVALID_SIGNATURE\");\n        _approve(owner, spender, value);\n    }\n}\n"},{"file_path":"contracts/dependencies/stargate-protocol/interfaces/IStargateReceiver.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.9;\n\ninterface IStargateReceiver {\n    function sgReceive(\n        uint16 _chainId,\n        bytes memory _srcAddress,\n        uint256 _nonce,\n        address _token,\n        uint256 amountLD,\n        bytes memory payload\n    ) external;\n}\n"},{"file_path":"contracts/interfaces/IDepositToken.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IERC20Metadata, IERC20} from \"../dependencies/openzeppelin/token/ERC20/extensions/IERC20Metadata.sol\";\n\ninterface IDepositToken is IERC20Metadata {\n    function underlying() external view returns (IERC20);\n\n    function collateralFactor() external view returns (uint256);\n\n    function unlockedBalanceOf(address account_) external view returns (uint256);\n\n    function lockedBalanceOf(address account_) external view returns (uint256);\n\n    function flashWithdraw(address account_, uint256 amount_) external returns (uint256 _withdrawn, uint256 _fee);\n\n    function deposit(uint256 amount_, address onBehalfOf_) external returns (uint256 _deposited, uint256 _fee);\n\n    function quoteDepositIn(uint256 amountToDeposit_) external view returns (uint256 _amount, uint256 _fee);\n\n    function quoteDepositOut(uint256 amount_) external view returns (uint256 _amountToDeposit, uint256 _fee);\n\n    function quoteWithdrawIn(uint256 amountToWithdraw_) external view returns (uint256 _amount, uint256 _fee);\n\n    function quoteWithdrawOut(uint256 amount_) external view returns (uint256 _amountToWithdraw, uint256 _fee);\n\n    function withdraw(uint256 amount_, address to_) external returns (uint256 _withdrawn, uint256 _fee);\n\n    function seize(address from_, address to_, uint256 amount_) external;\n\n    function updateCollateralFactor(uint128 newCollateralFactor_) external;\n\n    function isActive() external view returns (bool);\n\n    function toggleIsActive() external;\n\n    function maxTotalSupply() external view returns (uint256);\n\n    function updateMaxTotalSupply(uint256 newMaxTotalSupply_) external;\n\n    function withdrawFrom(address from_, uint256 amount_) external returns (uint256 _withdrawn, uint256 _fee);\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/utils/TransientSlot.sol","source_code":"// SPDX-License-Identifier: MIT\n// This file was procedurally generated from scripts/generate/templates/TransientSlot.js.\n\npragma solidity ^0.8.24;\n\n/**\n * @dev Library for reading and writing value-types to specific transient storage slots.\n *\n * Transient slots are often used to store temporary values that are removed after the current transaction.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n *  * Example reading and writing values using transient storage:\n * ```solidity\n * contract Lock {\n *     using TransientSlot for *;\n *\n *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n *     bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;\n *\n *     modifier locked() {\n *         require(!_LOCK_SLOT.asBoolean().tload());\n *\n *         _LOCK_SLOT.asBoolean().tstore(true);\n *         _;\n *         _LOCK_SLOT.asBoolean().tstore(false);\n *     }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary TransientSlot {\n    /**\n     * @dev UDVT that represent a slot holding a address.\n     */\n    type AddressSlot is bytes32;\n\n    /**\n     * @dev Cast an arbitrary slot to a AddressSlot.\n     */\n    function asAddress(bytes32 slot) internal pure returns (AddressSlot) {\n        return AddressSlot.wrap(slot);\n    }\n\n    /**\n     * @dev UDVT that represent a slot holding a bool.\n     */\n    type BooleanSlot is bytes32;\n\n    /**\n     * @dev Cast an arbitrary slot to a BooleanSlot.\n     */\n    function asBoolean(bytes32 slot) internal pure returns (BooleanSlot) {\n        return BooleanSlot.wrap(slot);\n    }\n\n    /**\n     * @dev UDVT that represent a slot holding a bytes32.\n     */\n    type Bytes32Slot is bytes32;\n\n    /**\n     * @dev Cast an arbitrary slot to a Bytes32Slot.\n     */\n    function asBytes32(bytes32 slot) internal pure returns (Bytes32Slot) {\n        return Bytes32Slot.wrap(slot);\n    }\n\n    /**\n     * @dev UDVT that represent a slot holding a uint256.\n     */\n    type Uint256Slot is bytes32;\n\n    /**\n     * @dev Cast an arbitrary slot to a Uint256Slot.\n     */\n    function asUint256(bytes32 slot) internal pure returns (Uint256Slot) {\n        return Uint256Slot.wrap(slot);\n    }\n\n    /**\n     * @dev UDVT that represent a slot holding a int256.\n     */\n    type Int256Slot is bytes32;\n\n    /**\n     * @dev Cast an arbitrary slot to a Int256Slot.\n     */\n    function asInt256(bytes32 slot) internal pure returns (Int256Slot) {\n        return Int256Slot.wrap(slot);\n    }\n\n    /**\n     * @dev Load the value held at location `slot` in transient storage.\n     */\n    function tload(AddressSlot slot) internal view returns (address value) {\n        assembly (\"memory-safe\") {\n            value := tload(slot)\n        }\n    }\n\n    /**\n     * @dev Store `value` at location `slot` in transient storage.\n     */\n    function tstore(AddressSlot slot, address value) internal {\n        assembly (\"memory-safe\") {\n            tstore(slot, value)\n        }\n    }\n\n    /**\n     * @dev Load the value held at location `slot` in transient storage.\n     */\n    function tload(BooleanSlot slot) internal view returns (bool value) {\n        assembly (\"memory-safe\") {\n            value := tload(slot)\n        }\n    }\n\n    /**\n     * @dev Store `value` at location `slot` in transient storage.\n     */\n    function tstore(BooleanSlot slot, bool value) internal {\n        assembly (\"memory-safe\") {\n            tstore(slot, value)\n        }\n    }\n\n    /**\n     * @dev Load the value held at location `slot` in transient storage.\n     */\n    function tload(Bytes32Slot slot) internal view returns (bytes32 value) {\n        assembly (\"memory-safe\") {\n            value := tload(slot)\n        }\n    }\n\n    /**\n     * @dev Store `value` at location `slot` in transient storage.\n     */\n    function tstore(Bytes32Slot slot, bytes32 value) internal {\n        assembly (\"memory-safe\") {\n            tstore(slot, value)\n        }\n    }\n\n    /**\n     * @dev Load the value held at location `slot` in transient storage.\n     */\n    function tload(Uint256Slot slot) internal view returns (uint256 value) {\n        assembly (\"memory-safe\") {\n            value := tload(slot)\n        }\n    }\n\n    /**\n     * @dev Store `value` at location `slot` in transient storage.\n     */\n    function tstore(Uint256Slot slot, uint256 value) internal {\n        assembly (\"memory-safe\") {\n            tstore(slot, value)\n        }\n    }\n\n    /**\n     * @dev Load the value held at location `slot` in transient storage.\n     */\n    function tload(Int256Slot slot) internal view returns (int256 value) {\n        assembly (\"memory-safe\") {\n            value := tload(slot)\n        }\n    }\n\n    /**\n     * @dev Store `value` at location `slot` in transient storage.\n     */\n    function tstore(Int256Slot slot, int256 value) internal {\n        assembly (\"memory-safe\") {\n            tstore(slot, value)\n        }\n    }\n}\n"},{"file_path":"contracts/lib/WadRayMath.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\n/**\n * @title Math library\n * @dev Provides mul and div function for wads (decimal numbers with 18 digits precision) and rays (decimals with 27 digits)\n * @dev Based on https://github.com/dapphub/ds-math/blob/master/src/math.sol\n */\nlibrary WadRayMath {\n    uint256 internal constant WAD = 1e18;\n    uint256 internal constant HALF_WAD = WAD / 2;\n\n    uint256 internal constant RAY = 1e27;\n    uint256 internal constant HALF_RAY = RAY / 2;\n\n    uint256 internal constant WAD_RAY_RATIO = 1e9;\n\n    /**\n     * @dev Multiplies two wad, rounding half up to the nearest wad\n     * @param a Wad\n     * @param b Wad\n     * @return The result of a*b, in wad\n     */\n    function wadMul(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (a == 0 || b == 0) {\n            return 0;\n        }\n\n        return (a * b + HALF_WAD) / WAD;\n    }\n\n    /**\n     * @dev Divides two wad, rounding half up to the nearest wad\n     * @param a Wad\n     * @param b Wad\n     * @return The result of a/b, in wad\n     */\n    function wadDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        return (a * WAD + b / 2) / b;\n    }\n}\n"},{"file_path":"contracts/mock/ERC20Mock.sol","source_code":"// SPDX-License-Identifier: MIT\n\n// Note: Minimalist ERC20 based on https://github.com/maple-labs/erc20\n\npragma solidity 0.8.24;\n\nimport {IERC20Metadata} from \"../dependencies/openzeppelin/token/ERC20/extensions/IERC20Metadata.sol\";\n\ncontract ERC20Mock is IERC20Metadata {\n    string public override name;\n    string public override symbol;\n\n    uint8 public immutable override decimals;\n\n    uint256 public override totalSupply;\n\n    mapping(address => uint256) public override balanceOf;\n\n    mapping(address => mapping(address => uint256)) public override allowance;\n\n    uint256 public fee;\n\n    constructor(string memory name_, string memory symbol_, uint8 decimals_) {\n        name = name_;\n        symbol = symbol_;\n        decimals = decimals_;\n    }\n\n    /**************************/\n    /*** External Functions ***/\n    /**************************/\n\n    function approve(address spender_, uint256 amount_) external override returns (bool success_) {\n        _approve(msg.sender, spender_, amount_);\n        return true;\n    }\n\n    function transfer(address recipient_, uint256 amount_) external override returns (bool success_) {\n        _transfer(msg.sender, recipient_, amount_);\n        return true;\n    }\n\n    function transferFrom(\n        address owner_,\n        address recipient_,\n        uint256 amount_\n    ) external override returns (bool success_) {\n        _approve(owner_, msg.sender, allowance[owner_][msg.sender] - amount_);\n        _transfer(owner_, recipient_, amount_);\n        return true;\n    }\n\n    function mint(address _to, uint256 _amount) external {\n        _mint(_to, _amount);\n    }\n\n    function burn(address _to, uint256 _amount) external {\n        _burn(_to, _amount);\n    }\n\n    function updateFee(uint256 _fee) external {\n        fee = _fee;\n    }\n\n    /**************************/\n    /*** Internal Functions ***/\n    /**************************/\n\n    function _approve(address owner_, address spender_, uint256 amount_) internal {\n        emit Approval(owner_, spender_, allowance[owner_][spender_] = amount_);\n    }\n\n    function _transfer(address owner_, address recipient_, uint256 amount_) internal {\n        uint256 feeAmount = fee > 0 ? (amount_ * fee) / 1e18 : 0;\n        balanceOf[owner_] -= amount_;\n        balanceOf[recipient_] += amount_ - feeAmount;\n\n        if (feeAmount > 0) {\n            balanceOf[address(0)] = feeAmount;\n        }\n\n        emit Transfer(owner_, recipient_, amount_);\n    }\n\n    function _mint(address recipient_, uint256 amount_) internal {\n        totalSupply += amount_;\n        balanceOf[recipient_] += amount_;\n\n        emit Transfer(address(0), recipient_, amount_);\n    }\n\n    function _burn(address owner_, uint256 amount_) internal {\n        balanceOf[owner_] -= amount_;\n        totalSupply -= amount_;\n\n        emit Transfer(owner_, address(0), amount_);\n    }\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/token/oft/IOFTCore.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\nimport \"../../../../openzeppelin/utils/introspection/IERC165.sol\";\n\n/**\n * @dev Interface of the IOFT core standard\n */\ninterface IOFTCore is IERC165 {\n    /**\n     * @dev estimate send token `_tokenId` to (`_dstChainId`, `_toAddress`)\n     * _dstChainId - L0 defined chain id to send tokens too\n     * _toAddress - dynamic bytes array which contains the address to whom you are sending tokens to on the dstChain\n     * _amount - amount of the tokens to transfer\n     * _useZro - indicates to use zro to pay L0 fees\n     * _adapterParam - flexible bytes array to indicate messaging adapter services in L0\n     */\n    function estimateSendFee(\n        uint16 _dstChainId,\n        bytes calldata _toAddress,\n        uint _amount,\n        bool _useZro,\n        bytes calldata _adapterParams\n    ) external view returns (uint nativeFee, uint zroFee);\n\n    /**\n     * @dev send `_amount` amount of token to (`_dstChainId`, `_toAddress`) from `_from`\n     * `_from` the owner of token\n     * `_dstChainId` the destination chain identifier\n     * `_toAddress` can be any size depending on the `dstChainId`.\n     * `_amount` the quantity of tokens in wei\n     * `_refundAddress` the address LayerZero refunds if too much message fee is sent\n     * `_zroPaymentAddress` set to address(0x0) if not paying in ZRO (LayerZero Token)\n     * `_adapterParams` is a flexible bytes array to indicate messaging adapter services\n     */\n    function sendFrom(\n        address _from,\n        uint16 _dstChainId,\n        bytes calldata _toAddress,\n        uint _amount,\n        address payable _refundAddress,\n        address _zroPaymentAddress,\n        bytes calldata _adapterParams\n    ) external payable;\n\n    /**\n     * @dev returns the circulating amount of tokens on current chain\n     */\n    function circulatingSupply() external view returns (uint);\n\n    /**\n     * @dev returns the address of the ERC20 token\n     */\n    function token() external view returns (address);\n\n    /**\n     * @dev Emitted when `_amount` tokens are moved from the `_sender` to (`_dstChainId`, `_toAddress`)\n     * `_nonce` is the outbound nonce\n     */\n    event SendToChain(uint16 indexed _dstChainId, address indexed _from, bytes _toAddress, uint _amount);\n\n    /**\n     * @dev Emitted when `_amount` tokens are received from `_srcChainId` into the `_toAddress` on the local chain.\n     * `_nonce` is the inbound nonce.\n     */\n    event ReceiveFromChain(uint16 indexed _srcChainId, address indexed _to, uint _amount);\n\n    event SetUseCustomAdapterParams(bool _useCustomAdapterParams);\n}\n"},{"file_path":"contracts/access/Manageable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {Initializable} from \"../dependencies/openzeppelin-upgradeable/proxy/utils/Initializable.sol\";\nimport {SynthContext} from \"../utils/SynthContext.sol\";\nimport {IGovernable} from \"../interfaces/IGovernable.sol\";\nimport {IManageable} from \"../interfaces/IManageable.sol\";\nimport {IPool} from \"../interfaces/IPool.sol\";\nimport {IPoolRegistry} from \"../interfaces/IPoolRegistry.sol\";\n\nerror SenderIsNotPool();\nerror SenderIsNotGovernor();\nerror IsPaused();\nerror IsShutdown();\nerror PoolAddressIsNull();\n\n/**\n * @title Reusable contract that handles accesses\n */\nabstract contract Manageable is IManageable, SynthContext, Initializable {\n    /**\n     * @notice Pool contract\n     */\n    IPool public pool;\n\n    /**\n     * @dev Throws if `_msgSender()` isn't the pool\n     */\n    modifier onlyPool() {\n        if (_msgSender() != address(pool)) revert SenderIsNotPool();\n        _;\n    }\n\n    /**\n     * @dev Throws if `_msgSender()` isn't the governor\n     */\n    modifier onlyGovernor() {\n        if (_msgSender() != governor()) revert SenderIsNotGovernor();\n        _;\n    }\n\n    /**\n     * @dev Throws if contract is paused\n     */\n    modifier whenNotPaused() {\n        if (pool.paused()) revert IsPaused();\n        _;\n    }\n\n    /**\n     * @dev Throws if contract is shutdown\n     */\n    modifier whenNotShutdown() {\n        if (pool.everythingStopped()) revert IsShutdown();\n        _;\n    }\n\n    // solhint-disable-next-line func-name-mixedcase\n    function __Manageable_init(IPool pool_) internal onlyInitializing {\n        if (address(pool_) == address(0)) revert PoolAddressIsNull();\n        pool = pool_;\n    }\n\n    /**\n     * @notice Get the governor\n     * @return _governor The governor\n     */\n    function governor() public view returns (address _governor) {\n        _governor = IGovernable(address(pool)).governor();\n    }\n\n    /// @inheritdoc SynthContext\n    function poolRegistry() public view override returns (IPoolRegistry) {\n        return pool.poolRegistry();\n    }\n\n    uint256[49] private __gap;\n}\n"},{"file_path":"contracts/dependencies/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Proxy.sol\";\nimport \"./ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n */\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\n    /**\n     * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\n     *\n     * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\n     * function call, and allows initializating the storage of the proxy like a Solidity constructor.\n     */\n    constructor(address _logic, bytes memory _data) payable {\n        assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1));\n        _upgradeToAndCall(_logic, _data, false);\n    }\n\n    /**\n     * @dev Returns the current implementation address.\n     */\n    function _implementation() internal view virtual override returns (address impl) {\n        return ERC1967Upgrade._getImplementation();\n    }\n}\n"},{"file_path":"contracts/dependencies/stargate-protocol/interfaces/IStargateFeeLibrary.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.9;\npragma abicoder v2;\nimport \"../Pool.sol\";\n\ninterface IStargateFeeLibrary {\n    function getFees(\n        uint256 _srcPoolId,\n        uint256 _dstPoolId,\n        uint16 _dstChainId,\n        address _from,\n        uint256 _amountSD\n    ) external returns (Pool.SwapObj memory s);\n\n    function getVersion() external view returns (string memory);\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/token/oft/composable/ComposableOFTCore.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../OFTCore.sol\";\nimport \"./IOFTReceiver.sol\";\nimport \"./IComposableOFTCore.sol\";\nimport \"../../../util/ExcessivelySafeCall.sol\";\n\nabstract contract ComposableOFTCore is OFTCore, IComposableOFTCore {\n    using ExcessivelySafeCall for address;\n    using BytesLib for bytes;\n\n    // packet type\n    uint16 public constant PT_SEND_AND_CALL = 1;\n\n    mapping(uint16 => mapping(bytes => mapping(uint64 => bytes32))) public failedOFTReceivedMessages;\n\n    constructor(address _lzEndpoint) OFTCore(_lzEndpoint) {}\n\n    function supportsInterface(bytes4 interfaceId) public view virtual override(OFTCore, IERC165) returns (bool) {\n        return interfaceId == type(IComposableOFTCore).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    function estimateSendAndCallFee(\n        uint16 _dstChainId,\n        bytes calldata _toAddress,\n        uint _amount,\n        bytes calldata _payload,\n        uint64 _dstGasForCall,\n        bool _useZro,\n        bytes calldata _adapterParams\n    ) public view virtual override returns (uint nativeFee, uint zroFee) {\n        // mock the payload for sendAndCall()\n        bytes memory payload = abi.encode(\n            PT_SEND_AND_CALL,\n            abi.encodePacked(_msgSender()),\n            _toAddress,\n            _amount,\n            _payload,\n            _dstGasForCall\n        );\n        return lzEndpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _adapterParams);\n    }\n\n    function sendAndCall(\n        address _from,\n        uint16 _dstChainId,\n        bytes calldata _toAddress,\n        uint _amount,\n        bytes calldata _payload,\n        uint64 _dstGasForCall,\n        address payable _refundAddress,\n        address _zroPaymentAddress,\n        bytes calldata _adapterParams\n    ) public payable virtual override {\n        _sendAndCall(\n            _from,\n            _dstChainId,\n            _toAddress,\n            _amount,\n            _payload,\n            _dstGasForCall,\n            _refundAddress,\n            _zroPaymentAddress,\n            _adapterParams\n        );\n    }\n\n    function retryOFTReceived(\n        uint16 _srcChainId,\n        bytes calldata _srcAddress,\n        uint64 _nonce,\n        bytes calldata _from,\n        address _to,\n        uint _amount,\n        bytes calldata _payload\n    ) public virtual override {\n        bytes32 msgHash = failedOFTReceivedMessages[_srcChainId][_srcAddress][_nonce];\n        require(msgHash != bytes32(0), \"ComposableOFTCore: no failed message to retry\");\n\n        bytes32 hash = keccak256(abi.encode(_from, _to, _amount, _payload));\n        require(hash == msgHash, \"ComposableOFTCore: failed message hash mismatch\");\n\n        delete failedOFTReceivedMessages[_srcChainId][_srcAddress][_nonce];\n        IOFTReceiver(_to).onOFTReceived(_srcChainId, _srcAddress, _nonce, _from, _amount, _payload);\n        emit RetryOFTReceivedSuccess(hash);\n    }\n\n    function _nonblockingLzReceive(\n        uint16 _srcChainId,\n        bytes memory _srcAddress,\n        uint64 _nonce,\n        bytes memory _payload\n    ) internal virtual override {\n        uint16 packetType;\n        assembly {\n            packetType := mload(add(_payload, 32))\n        }\n\n        if (packetType == PT_SEND) {\n            _sendAck(_srcChainId, _srcAddress, _nonce, _payload);\n        } else if (packetType == PT_SEND_AND_CALL) {\n            _sendAndCallAck(_srcChainId, _srcAddress, _nonce, _payload);\n        } else {\n            revert(\"ComposableOFTCore: unknown packet type\");\n        }\n    }\n\n    function _sendAndCall(\n        address _from,\n        uint16 _dstChainId,\n        bytes memory _toAddress,\n        uint _amount,\n        bytes calldata _payload,\n        uint64 _dstGasForCall,\n        address payable _refundAddress,\n        address _zroPaymentAddress,\n        bytes memory _adapterParams\n    ) internal virtual {\n        _checkAdapterParams(_dstChainId, PT_SEND_AND_CALL, _adapterParams, _dstGasForCall);\n\n        uint amount = _debitFrom(_from, _dstChainId, _toAddress, _amount);\n\n        bytes memory lzPayload = abi.encode(\n            PT_SEND_AND_CALL,\n            abi.encodePacked(_msgSender()),\n            _toAddress,\n            amount,\n            _payload,\n            _dstGasForCall\n        );\n        _lzSend(_dstChainId, lzPayload, _refundAddress, _zroPaymentAddress, _adapterParams, msg.value);\n\n        emit SendToChain(_dstChainId, _from, _toAddress, amount);\n    }\n\n    function _sendAndCallAck(\n        uint16 _srcChainId,\n        bytes memory _srcAddress,\n        uint64 _nonce,\n        bytes memory _payload\n    ) internal virtual {\n        (, bytes memory from, bytes memory toAddress, uint amount, bytes memory payload, uint64 gasForCall) = abi\n            .decode(_payload, (uint16, bytes, bytes, uint, bytes, uint64));\n\n        address to = toAddress.toAddress(0);\n\n        amount = _creditTo(_srcChainId, to, amount);\n        emit ReceiveFromChain(_srcChainId, to, amount);\n\n        if (!_isContract(to)) {\n            emit NonContractAddress(to);\n            return;\n        }\n\n        _safeCallOnOFTReceived(_srcChainId, _srcAddress, _nonce, from, to, amount, payload, gasForCall);\n    }\n\n    function _safeCallOnOFTReceived(\n        uint16 _srcChainId,\n        bytes memory _srcAddress,\n        uint64 _nonce,\n        bytes memory _from,\n        address _to,\n        uint _amount,\n        bytes memory _payload,\n        uint _gasForCall\n    ) internal virtual {\n        (bool success, bytes memory reason) = _to.excessivelySafeCall(\n            _gasForCall,\n            150,\n            abi.encodeWithSelector(\n                IOFTReceiver.onOFTReceived.selector,\n                _srcChainId,\n                _srcAddress,\n                _nonce,\n                _from,\n                _amount,\n                _payload\n            )\n        );\n        if (!success) {\n            failedOFTReceivedMessages[_srcChainId][_srcAddress][_nonce] = keccak256(\n                abi.encode(_from, _to, _amount, _payload)\n            );\n            emit CallOFTReceivedFailure(_srcChainId, _srcAddress, _nonce, _from, _to, _amount, _payload, reason);\n        } else {\n            bytes32 hash = keccak256(abi.encode(_from, _to, _amount, _payload));\n            emit CallOFTReceivedSuccess(_srcChainId, _srcAddress, _nonce, hash);\n        }\n    }\n\n    function _isContract(address _account) internal view returns (bool) {\n        return _account.code.length > 0;\n    }\n}\n"},{"file_path":"contracts/dependencies/openzeppelin-upgradeable/utils/ContextUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../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    /**\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":"contracts/dependencies/@layerzerolabs/solidity-examples/token/oft/composable/ComposableBasedOFT.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./ComposableOFT.sol\";\n\ncontract ComposableBasedOFT is ComposableOFT {\n    constructor(\n        string memory _name,\n        string memory _symbol,\n        address _lzEndpoint\n    ) ComposableOFT(_name, _symbol, _lzEndpoint) {}\n\n    function circulatingSupply() public view virtual override returns (uint) {\n        unchecked {\n            return totalSupply() - balanceOf(address(this));\n        }\n    }\n\n    function _debitFrom(address _from, uint16, bytes memory, uint _amount) internal virtual override returns (uint) {\n        address spender = _msgSender();\n        if (_from != spender) _spendAllowance(_from, spender, _amount);\n        _transfer(_from, address(this), _amount);\n        return _amount;\n    }\n\n    function _creditTo(uint16, address _toAddress, uint _amount) internal virtual override returns (uint) {\n        _transfer(address(this), _toAddress, _amount);\n        return _amount;\n    }\n}\n"},{"file_path":"contracts/interfaces/ISyntheticToken.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IERC20Metadata} from \"../dependencies/openzeppelin/token/ERC20/extensions/IERC20Metadata.sol\";\nimport {IPoolRegistry} from \"./IPoolRegistry.sol\";\nimport {IProxyOFT} from \"../interfaces/IProxyOFT.sol\";\n\ninterface ISyntheticToken is IERC20Metadata {\n    function isActive() external view returns (bool);\n\n    function mint(address to_, uint256 amount_) external;\n\n    function burnFor(address from_, uint256 amount) external;\n\n    function burn(uint256 amount_) external;\n\n    function burnFrom(address from_, uint256 amount_) external;\n\n    function poolRegistry() external view returns (IPoolRegistry);\n\n    function toggleIsActive() external;\n\n    function seize(address from_, address to_, uint256 amount_) external;\n\n    function updateMaxTotalSupply(uint256 newMaxTotalSupply_) external;\n\n    function updateProxyOFT(IProxyOFT newProxyOFT_) external;\n\n    function maxTotalSupply() external view returns (uint256);\n\n    function proxyOFT() external view returns (IProxyOFT);\n\n    function amoSupply() external view returns (uint256);\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/contracts-upgradeable/lzApp/NonblockingLzAppUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.2;\n\nimport \"./LzAppUpgradeable.sol\";\nimport \"../../util/ExcessivelySafeCall.sol\";\n\n/*\n * the default LayerZero messaging behaviour is blocking, i.e. any failed message will block the channel\n * this abstract class try-catch all fail messages and store locally for future retry. hence, non-blocking\n * NOTE: if the srcAddress is not configured properly, it will still block the message pathway from (srcChainId, srcAddress)\n */\nabstract contract NonblockingLzAppUpgradeable is Initializable, LzAppUpgradeable {\n    using ExcessivelySafeCall for address;\n\n    function __NonblockingLzAppUpgradeable_init(address _endpoint) internal onlyInitializing {\n        __Ownable_init_unchained();\n        __LzAppUpgradeable_init_unchained(_endpoint);\n    }\n\n    function __NonblockingLzAppUpgradeable_init_unchained(address _endpoint) internal onlyInitializing {}\n\n    mapping(uint16 => mapping(bytes => mapping(uint64 => bytes32))) public failedMessages;\n\n    event MessageFailed(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes _payload, bytes _reason);\n    event RetryMessageSuccess(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes32 _payloadHash);\n\n    // overriding the virtual function in LzReceiver\n    function _blockingLzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) internal virtual override {\n        (bool success, bytes memory reason) = address(this).excessivelySafeCall(gasleft(), 150, abi.encodeWithSelector(this.nonblockingLzReceive.selector, _srcChainId, _srcAddress, _nonce, _payload));\n        // try-catch all errors/exceptions\n        if (!success) {\n            _storeFailedMessage(_srcChainId, _srcAddress, _nonce, _payload, reason);\n        }\n    }\n\n    function _storeFailedMessage(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload, bytes memory _reason) internal virtual {\n        failedMessages[_srcChainId][_srcAddress][_nonce] = keccak256(_payload);\n        emit MessageFailed(_srcChainId, _srcAddress, _nonce, _payload, _reason);\n    }\n\n    function nonblockingLzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) public virtual {\n        // only internal transaction\n        require(_msgSender() == address(this), \"NonblockingLzApp: caller must be LzApp\");\n        _nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);\n    }\n\n    //@notice override this function\n    function _nonblockingLzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) internal virtual;\n\n    function retryMessage(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) public payable virtual {\n        // assert there is message to retry\n        bytes32 payloadHash = failedMessages[_srcChainId][_srcAddress][_nonce];\n        require(payloadHash != bytes32(0), \"NonblockingLzApp: no stored message\");\n        require(keccak256(_payload) == payloadHash, \"NonblockingLzApp: invalid payload\");\n        // clear the stored message\n        failedMessages[_srcChainId][_srcAddress][_nonce] = bytes32(0);\n        // execute the message. revert if it fails again\n        _nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);\n        emit RetryMessageSuccess(_srcChainId, _srcAddress, _nonce, payloadHash);\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    uint[49] private __gap;\n}\n"},{"file_path":"contracts/interfaces/IManageable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {IPool} from \"./IPool.sol\";\n\n/**\n * @notice Manageable interface\n */\ninterface IManageable {\n    function pool() external view returns (IPool _pool);\n}\n"},{"file_path":"contracts/dependencies/openzeppelin-upgradeable/access/OwnableUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../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 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 called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n        _;\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing 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":"contracts/dependencies/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1967/ERC1967Proxy.sol\";\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\n */\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\n    /**\n     * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n     * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\n     */\n    constructor(\n        address _logic,\n        address admin_,\n        bytes memory _data\n    ) payable ERC1967Proxy(_logic, _data) {\n        assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1));\n        _changeAdmin(admin_);\n    }\n\n    /**\n     * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n     */\n    modifier ifAdmin() {\n        if (msg.sender == _getAdmin()) {\n            _;\n        } else {\n            _fallback();\n        }\n    }\n\n    /**\n     * @dev Returns the current admin.\n     *\n     * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\n     *\n     * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n     * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n     * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n     */\n    function admin() external ifAdmin returns (address admin_) {\n        admin_ = _getAdmin();\n    }\n\n    /**\n     * @dev Returns the current implementation.\n     *\n     * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\n     *\n     * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n     * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n     * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n     */\n    function implementation() external ifAdmin returns (address implementation_) {\n        implementation_ = _implementation();\n    }\n\n    /**\n     * @dev Changes the admin of the proxy.\n     *\n     * Emits an {AdminChanged} event.\n     *\n     * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\n     */\n    function changeAdmin(address newAdmin) external virtual ifAdmin {\n        _changeAdmin(newAdmin);\n    }\n\n    /**\n     * @dev Upgrade the implementation of the proxy.\n     *\n     * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\n     */\n    function upgradeTo(address newImplementation) external ifAdmin {\n        _upgradeToAndCall(newImplementation, bytes(\"\"), false);\n    }\n\n    /**\n     * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n     * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n     * proxied contract.\n     *\n     * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\n     */\n    function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\n        _upgradeToAndCall(newImplementation, data, true);\n    }\n\n    /**\n     * @dev Returns the current admin.\n     */\n    function _admin() internal view virtual returns (address) {\n        return _getAdmin();\n    }\n\n    /**\n     * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\n     */\n    function _beforeFallback() internal virtual override {\n        require(msg.sender != _getAdmin(), \"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n        super._beforeFallback();\n    }\n}\n"},{"file_path":"contracts/dependencies/@layerzerolabs/solidity-examples/token/oft/OFTCore.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../../lzApp/NonblockingLzApp.sol\";\nimport \"./IOFTCore.sol\";\nimport \"../../../../../dependencies/openzeppelin/utils/introspection/ERC165.sol\";\n\nabstract contract OFTCore is NonblockingLzApp, ERC165, IOFTCore {\n    using BytesLib for bytes;\n\n    uint public constant NO_EXTRA_GAS = 0;\n\n    // packet type\n    uint16 public constant PT_SEND = 0;\n\n    bool public useCustomAdapterParams;\n\n    constructor(address _lzEndpoint) NonblockingLzApp(_lzEndpoint) {}\n\n    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n        return interfaceId == type(IOFTCore).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    function estimateSendFee(\n        uint16 _dstChainId,\n        bytes calldata _toAddress,\n        uint _amount,\n        bool _useZro,\n        bytes calldata _adapterParams\n    ) public view virtual override returns (uint nativeFee, uint zroFee) {\n        // mock the payload for sendFrom()\n        bytes memory payload = abi.encode(PT_SEND, _toAddress, _amount);\n        return lzEndpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _adapterParams);\n    }\n\n    function sendFrom(\n        address _from,\n        uint16 _dstChainId,\n        bytes calldata _toAddress,\n        uint _amount,\n        address payable _refundAddress,\n        address _zroPaymentAddress,\n        bytes calldata _adapterParams\n    ) public payable virtual override {\n        _send(_from, _dstChainId, _toAddress, _amount, _refundAddress, _zroPaymentAddress, _adapterParams);\n    }\n\n    function setUseCustomAdapterParams(bool _useCustomAdapterParams) public virtual onlyOwner {\n        useCustomAdapterParams = _useCustomAdapterParams;\n        emit SetUseCustomAdapterParams(_useCustomAdapterParams);\n    }\n\n    function _nonblockingLzReceive(\n        uint16 _srcChainId,\n        bytes memory _srcAddress,\n        uint64 _nonce,\n        bytes memory _payload\n    ) internal virtual override {\n        uint16 packetType;\n        assembly {\n            packetType := mload(add(_payload, 32))\n        }\n\n        if (packetType == PT_SEND) {\n            _sendAck(_srcChainId, _srcAddress, _nonce, _payload);\n        } else {\n            revert(\"OFTCore: unknown packet type\");\n        }\n    }\n\n    function _send(\n        address _from,\n        uint16 _dstChainId,\n        bytes memory _toAddress,\n        uint _amount,\n        address payable _refundAddress,\n        address _zroPaymentAddress,\n        bytes memory _adapterParams\n    ) internal virtual {\n        _checkAdapterParams(_dstChainId, PT_SEND, _adapterParams, NO_EXTRA_GAS);\n\n        uint amount = _debitFrom(_from, _dstChainId, _toAddress, _amount);\n\n        bytes memory lzPayload = abi.encode(PT_SEND, _toAddress, amount);\n        _lzSend(_dstChainId, lzPayload, _refundAddress, _zroPaymentAddress, _adapterParams, msg.value);\n\n        emit SendToChain(_dstChainId, _from, _toAddress, amount);\n    }\n\n    function _sendAck(uint16 _srcChainId, bytes memory, uint64, bytes memory _payload) internal virtual {\n        (, bytes memory toAddressBytes, uint amount) = abi.decode(_payload, (uint16, bytes, uint));\n\n        address to = toAddressBytes.toAddress(0);\n\n        amount = _creditTo(_srcChainId, to, amount);\n        emit ReceiveFromChain(_srcChainId, to, amount);\n    }\n\n    function _checkAdapterParams(\n        uint16 _dstChainId,\n        uint16 _pkType,\n        bytes memory _adapterParams,\n        uint _extraGas\n    ) internal virtual {\n        if (useCustomAdapterParams) {\n            _checkGasLimit(_dstChainId, _pkType, _adapterParams, _extraGas);\n        } else {\n            require(_adapterParams.length == 0, \"OFTCore: _adapterParams must be empty.\");\n        }\n    }\n\n    function _debitFrom(\n        address _from,\n        uint16 _dstChainId,\n        bytes memory _toAddress,\n        uint _amount\n    ) internal virtual returns (uint);\n\n    function _creditTo(uint16 _srcChainId, address _toAddress, uint _amount) internal virtual returns (uint);\n}\n"},{"file_path":"contracts/utils/RecurringAirdrop.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\nimport {SafeERC20, IERC20} from \"../dependencies/openzeppelin/token/ERC20/utils/SafeERC20.sol\";\nimport {ReentrancyGuardTransient} from \"../utils/ReentrancyGuardTransient.sol\";\nimport {MerkleProof} from \"../dependencies/openzeppelin/utils/cryptography/MerkleProof.sol\";\nimport {Governable} from \"../access/Governable.sol\";\n\nerror NothingToClaim();\nerror InvalidProof();\nerror NewMerkleRootSameAsCurrent();\nerror ProofsFileIsNull();\n\n/**\n * @title Generic Recurring Airdrop contract\n */\ncontract RecurringAirdrop is ReentrancyGuardTransient, Governable {\n    using SafeERC20 for IERC20;\n\n    /// @notice The token to distribute\n    IERC20 public immutable token;\n\n    /// @notice The merkle root for the current distribution\n    bytes32 public merkleRoot;\n\n    /// @notice The proofs file's IPFS hash\n    bytes32 public proofsFileHash;\n\n    /// @notice The timestamp of the latest merkle root update\n    uint256 public updatedAt;\n\n    /// @notice The Accumulated amount claimed for a given account\n    mapping(address => uint256) public claimed;\n\n    /// @notice Emitted when an account claims reward\n    event RewardClaimed(address indexed to, uint256 amount);\n\n    /// @notice Emitted when the merkle root is updated\n    event MerkleRootUpdated(bytes32 merkleRoot, uint256 createdAt);\n\n    constructor(IERC20 token_) {\n        token = token_;\n    }\n\n    /**\n     * @notice Claim reward\n     * @dev Every tree leaf is a `[account, amount]` tuple, we assume that the `msg.sender` is the account\n     * @param amount_ The amount to claim\n     * @param proof_ The merkle tree proof for the given leaf\n     */\n    function claim(uint256 amount_, bytes32[] calldata proof_) external nonReentrant {\n        if (merkleRoot == bytes32(0)) revert NothingToClaim();\n\n        bytes32 _leaf = keccak256(abi.encodePacked(msg.sender, amount_));\n        if (!MerkleProof.verify(proof_, merkleRoot, _leaf)) revert InvalidProof();\n\n        uint256 _claimable = amount_ - claimed[msg.sender];\n        if (_claimable == 0) revert NothingToClaim();\n\n        claimed[msg.sender] += _claimable;\n\n        _transferReward(msg.sender, _claimable);\n\n        emit RewardClaimed(msg.sender, _claimable);\n    }\n\n    /**\n     * @notice Transfer reward to the user\n     * @param to_ The claim account\n     * @param amount_ The reward amount\n     */\n    function _transferReward(address to_, uint256 amount_) internal virtual {\n        token.safeTransfer(to_, amount_);\n    }\n\n    /**\n     * @notice Update merkle tree root\n     * @param merkleRoot_ The merkle root\n     */\n    function updateMerkleRoot(bytes32 merkleRoot_, bytes32 proofsFileHash_) external onlyGovernor {\n        if (merkleRoot_ == merkleRoot) revert NewMerkleRootSameAsCurrent();\n        if (proofsFileHash_ == bytes32(0)) revert ProofsFileIsNull();\n\n        merkleRoot = merkleRoot_;\n        updatedAt = block.timestamp;\n        proofsFileHash = proofsFileHash_;\n\n        emit MerkleRootUpdated(merkleRoot_, block.timestamp);\n    }\n}\n"},{"file_path":"contracts/interfaces/IGovernable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.24;\n\n/**\n * @notice Governable interface\n */\ninterface IGovernable {\n    function governor() external view returns (address _governor);\n\n    function transferGovernorship(address _proposedGovernor) external;\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AllowanceNotSupported","type":"error"},{"inputs":[],"name":"AmountIsZero","type":"error"},{"inputs":[],"name":"ApprovalNotSupported","type":"error"},{"inputs":[],"name":"BurnAmountExceedsBalance","type":"error"},{"inputs":[],"name":"BurnFromNullAddress","type":"error"},{"inputs":[],"name":"DebtLowerThanTheFloor","type":"error"},{"inputs":[],"name":"DebtTokenInactive","type":"error"},{"inputs":[],"name":"FallbackIsNotAllowed","type":"error"},{"inputs":[],"name":"IsShutdown","type":"error"},{"inputs":[],"name":"MintToNullAddress","type":"error"},{"inputs":[],"name":"NameIsNull","type":"error"},{"inputs":[],"name":"NewValueIsSameAsCurrent","type":"error"},{"inputs":[],"name":"NotEnoughCollateral","type":"error"},{"inputs":[],"name":"PoolAddressIsNull","type":"error"},{"inputs":[],"name":"PoolIsNull","type":"error"},{"inputs":[],"name":"ReceiveIsNotAllowed","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"RemainingDebtIsLowerThanTheFloor","type":"error"},{"inputs":[],"name":"SenderIsNotGovernor","type":"error"},{"inputs":[],"name":"SenderIsNotPool","type":"error"},{"inputs":[],"name":"SenderIsNotSmartFarmingManager","type":"error"},{"inputs":[],"name":"SurpassMaxDebtSupply","type":"error"},{"inputs":[],"name":"SymbolIsNull","type":"error"},{"inputs":[],"name":"SyntheticDoesNotExist","type":"error"},{"inputs":[],"name":"SyntheticIsInactive","type":"error"},{"inputs":[],"name":"SyntheticIsNull","type":"error"},{"inputs":[],"name":"TransferNotSupported","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"payer","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"repaid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"DebtRepaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"newActive","type":"bool"}],"name":"DebtTokenActiveUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldInterestRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newInterestRate","type":"uint256"}],"name":"InterestRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldMaxTotalSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMaxTotalSupply","type":"uint256"}],"name":"MaxTotalSupplyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"issued","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"SyntheticTokenIssued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"SECONDS_PER_YEAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accrueInterest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"burnFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collectPendingInterestFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"debtIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"flashIssue","outputs":[{"internalType":"uint256","name":"_issued","type":"uint256"},{"internalType":"uint256","name":"_fee","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getPendingInterestFee","outputs":[{"internalType":"uint256","name":"_stored","type":"uint256"},{"internalType":"uint256","name":"_current","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governor","outputs":[{"internalType":"address","name":"_governor","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"contract IPool","name":"pool_","type":"address"},{"internalType":"contract ISyntheticToken","name":"syntheticToken_","type":"address"},{"internalType":"uint256","name":"interestRate_","type":"uint256"},{"internalType":"uint256","name":"maxTotalSupply_","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"interestRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"interestRatePerSecond","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"address","name":"to_","type":"address"}],"name":"issue","outputs":[{"internalType":"uint256","name":"_issued","type":"uint256"},{"internalType":"uint256","name":"_fee","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastTimestampAccrued","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"contract IPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolRegistry","outputs":[{"internalType":"contract IPoolRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountToIssue_","type":"uint256"}],"name":"quoteIssueIn","outputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"quoteIssueOut","outputs":[{"internalType":"uint256","name":"_amountToIssue","type":"uint256"},{"internalType":"uint256","name":"_fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountToRepay_","type":"uint256"}],"name":"quoteRepayIn","outputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"quoteRepayOut","outputs":[{"internalType":"uint256","name":"_amountToRepay","type":"uint256"},{"internalType":"uint256","name":"_fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"onBehalfOf_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"repay","outputs":[{"internalType":"uint256","name":"_repaid","type":"uint256"},{"internalType":"uint256","name":"_fee","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"onBehalfOf_","type":"address"}],"name":"repayAll","outputs":[{"internalType":"uint256","name":"_repaid","type":"uint256"},{"internalType":"uint256","name":"_fee","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"syntheticToken","outputs":[{"internalType":"contract ISyntheticToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleIsActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newInterestRate_","type":"uint256"}],"name":"updateInterestRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMaxTotalSupply_","type":"uint256"}],"name":"updateMaxTotalSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":null}