ETH Price: $1,971.29 (+0.13%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
IporProtocolRouterEthereum

Compiler Version
v0.8.26+commit.8a97fa7a

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
cancun EvmVersion, BSL 1.1 license
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;

import "../../../interfaces/IAmmSwapsLens.sol";
import "../../../interfaces/IAmmPoolsLens.sol";
import "../../../interfaces/IAssetManagementLens.sol";
import "../../../interfaces/IPowerTokenLens.sol";
import "../../../interfaces/ILiquidityMiningLens.sol";
import "../../../interfaces/IAmmGovernanceService.sol";
import "../../../interfaces/IAmmGovernanceLens.sol";
import "../../../interfaces/IAmmOpenSwapLens.sol";
import "../../../interfaces/IAmmOpenSwapService.sol";
import "../../../interfaces/IAmmOpenSwapServiceStEth.sol";
import "../../../interfaces/IAmmCloseSwapServiceUsdt.sol";
import "../../../interfaces/IAmmCloseSwapServiceUsdc.sol";
import "../../../interfaces/IAmmCloseSwapServiceDai.sol";
import "../../../interfaces/IAmmCloseSwapServiceStEth.sol";
import "../../../interfaces/IAmmCloseSwapLens.sol";
import "../../../interfaces/IAmmPoolsService.sol";
import "../../../interfaces/IPowerTokenFlowsService.sol";
import "../../../interfaces/IPowerTokenStakeService.sol";
import "../../../amm-eth/interfaces/IAmmPoolsServiceStEth.sol";
import "../../../amm-weEth/interfaces/IAmmPoolsServiceWeEth.sol";
import "../../../libraries/errors/IporErrors.sol";
import "../../../libraries/IporContractValidator.sol";
import "../../../router/IporProtocolRouterAbstract.sol";
import "../../../amm-usdm/interfaces/IAmmPoolsServiceUsdm.sol";
import "../../../base/interfaces/IAmmGovernanceServiceBaseV1.sol";

import "../../../base/libraries/StorageLibBaseV1.sol";

/// @title Entry point for IPOR protocol on Ethereum chain
contract IporProtocolRouterEthereum is IporProtocolRouterAbstract {
    using IporContractValidator for address;

    address public immutable ammSwapsLens;
    /// @dev for USDT, USDC, DAI pools
    address public immutable ammPoolsLens;
    /// @dev USDM, weETH, stETH pools
    address public immutable ammPoolsLensBaseV1;
    address public immutable ammCloseSwapLens;
    address public immutable ammGovernanceService;

    address public immutable flowService;
    address public immutable stakeService;
    address public immutable powerTokenLens;
    address public immutable liquidityMiningLens;

    address public immutable ammCloseSwapServiceUsdt;
    address public immutable ammCloseSwapServiceUsdc;
    address public immutable ammCloseSwapServiceDai;
    /// @dev for USDT, USDC, DAI pools
    address public immutable ammOpenSwapService;
    /// @dev for USDT, USDC, DAI pools
    address public immutable ammPoolsService;
    /// @dev for USDT, USDC, DAI pools
    address public immutable assetManagementLens;

    address public immutable stEth;
    address public immutable weEth;
    address public immutable usdm;

    struct DeployedContracts {
        address ammSwapsLens;
        address ammPoolsLens;
        address ammPoolsLensBaseV1;
        address assetManagementLens;
        address ammOpenSwapService;
        address ammCloseSwapServiceUsdt;
        address ammCloseSwapServiceUsdc;
        address ammCloseSwapServiceDai;
        address ammCloseSwapLens;
        address ammPoolsService;
        address ammGovernanceService;
        address liquidityMiningLens;
        address powerTokenLens;
        address flowService;
        address stakeService;
        address stEth;
        address weEth;
        address usdm;
    }

    constructor(DeployedContracts memory deployedContracts) {
        ammSwapsLens = deployedContracts.ammSwapsLens.checkAddress();
        ammPoolsLens = deployedContracts.ammPoolsLens.checkAddress();
        ammPoolsLensBaseV1 = deployedContracts.ammPoolsLensBaseV1.checkAddress();
        ammCloseSwapLens = deployedContracts.ammCloseSwapLens.checkAddress();
        ammGovernanceService = deployedContracts.ammGovernanceService.checkAddress();

        flowService = deployedContracts.flowService.checkAddress();
        stakeService = deployedContracts.stakeService.checkAddress();
        powerTokenLens = deployedContracts.powerTokenLens.checkAddress();
        liquidityMiningLens = deployedContracts.liquidityMiningLens.checkAddress();

        ammCloseSwapServiceUsdt = deployedContracts.ammCloseSwapServiceUsdt.checkAddress();
        ammCloseSwapServiceUsdc = deployedContracts.ammCloseSwapServiceUsdc.checkAddress();
        ammCloseSwapServiceDai = deployedContracts.ammCloseSwapServiceDai.checkAddress();
        ammOpenSwapService = deployedContracts.ammOpenSwapService.checkAddress();

        ammPoolsService = deployedContracts.ammPoolsService.checkAddress();
        assetManagementLens = deployedContracts.assetManagementLens.checkAddress();

        stEth = deployedContracts.stEth.checkAddress();
        weEth = deployedContracts.weEth.checkAddress();
        usdm = deployedContracts.usdm.checkAddress();

        _disableInitializers();
    }

    /// @notice Gets the Router configuration
    /// @return DeployedContracts struct
    function getConfiguration() external view returns (DeployedContracts memory) {
        return
            DeployedContracts({
                ammSwapsLens: ammSwapsLens,
                ammPoolsLens: ammPoolsLens,
                ammPoolsLensBaseV1: ammPoolsLensBaseV1,
                ammCloseSwapLens: ammCloseSwapLens,
                ammGovernanceService: ammGovernanceService,
                flowService: flowService,
                stakeService: stakeService,
                powerTokenLens: powerTokenLens,
                liquidityMiningLens: liquidityMiningLens,
                ammCloseSwapServiceUsdt: ammCloseSwapServiceUsdt,
                ammCloseSwapServiceUsdc: ammCloseSwapServiceUsdc,
                ammCloseSwapServiceDai: ammCloseSwapServiceDai,
                ammOpenSwapService: ammOpenSwapService,
                ammPoolsService: ammPoolsService,
                assetManagementLens: assetManagementLens,
                stEth: stEth,
                weEth: weEth,
                usdm: usdm
            });
    }

    function _getRouterImplementation(bytes4 sig, uint256 batchOperation) internal override returns (address) {
        if (
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapServiceStEth.openSwapPayFixed28daysStEth.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapServiceStEth.openSwapPayFixed60daysStEth.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapServiceStEth.openSwapPayFixed90daysStEth.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapServiceStEth.openSwapReceiveFixed28daysStEth.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapServiceStEth.openSwapReceiveFixed60daysStEth.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapServiceStEth.openSwapReceiveFixed90daysStEth.selector)
        ) {
            if (batchOperation == 0) {
                _nonReentrantBefore();
            }
            StorageLibBaseV1.AssetServicesValue storage servicesCfg = StorageLibBaseV1.getAssetServicesStorage().value[
                stEth
            ];
            return servicesCfg.ammOpenSwapService;
        } else if (
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapPayFixed60daysUsdt.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapPayFixed28daysUsdt.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapPayFixed90daysUsdt.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapReceiveFixed28daysUsdt.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapReceiveFixed60daysUsdt.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapReceiveFixed90daysUsdt.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapPayFixed28daysUsdc.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapPayFixed60daysUsdc.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapPayFixed90daysUsdc.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapReceiveFixed28daysUsdc.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapReceiveFixed60daysUsdc.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapReceiveFixed90daysUsdc.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapPayFixed28daysDai.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapPayFixed60daysDai.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapPayFixed90daysDai.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapReceiveFixed28daysDai.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapReceiveFixed60daysDai.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapReceiveFixed90daysDai.selector)
        ) {
            if (batchOperation == 0) {
                _nonReentrantBefore();
            }
            return ammOpenSwapService;
        } else if (_checkFunctionSigAndIsNotPause(sig, IAmmCloseSwapServiceStEth.closeSwapsStEth.selector)) {
            if (batchOperation == 0) {
                _nonReentrantBefore();
            }
            StorageLibBaseV1.AssetServicesValue storage servicesCfg = StorageLibBaseV1.getAssetServicesStorage().value[
                stEth
            ];
            return servicesCfg.ammCloseSwapService;
        } else if (_checkFunctionSigAndIsNotPause(sig, IAmmCloseSwapServiceUsdt.closeSwapsUsdt.selector)) {
            if (batchOperation == 0) {
                _nonReentrantBefore();
            }
            return ammCloseSwapServiceUsdt;
        } else if (_checkFunctionSigAndIsNotPause(sig, IAmmCloseSwapServiceUsdc.closeSwapsUsdc.selector)) {
            if (batchOperation == 0) {
                _nonReentrantBefore();
            }
            return ammCloseSwapServiceUsdc;
        } else if (_checkFunctionSigAndIsNotPause(sig, IAmmCloseSwapServiceDai.closeSwapsDai.selector)) {
            if (batchOperation == 0) {
                _nonReentrantBefore();
            }
            return ammCloseSwapServiceDai;
        } else if (
            _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceStEth.provideLiquidityStEth.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceStEth.provideLiquidityWEth.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceStEth.provideLiquidityEth.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceStEth.redeemFromAmmPoolStEth.selector) ||
            _checkFunctionSigAndIsNotPause(
                sig,
                IAmmPoolsServiceStEth.rebalanceBetweenAmmTreasuryAndAssetManagementStEth.selector
            )
        ) {
            if (batchOperation == 0) {
                _nonReentrantBefore();
            }
            StorageLibBaseV1.AssetServicesValue storage servicesCfg = StorageLibBaseV1.getAssetServicesStorage().value[
                stEth
            ];
            return servicesCfg.ammPoolsService;
        } else if (
            _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceWeEth.provideLiquidityWeEthToAmmPoolWeEth.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceWeEth.provideLiquidity.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceWeEth.redeemFromAmmPoolWeEth.selector) ||
            _checkFunctionSigAndIsNotPause(
                sig,
                IAmmPoolsServiceWeEth.rebalanceBetweenAmmTreasuryAndAssetManagementWeEth.selector
            )
        ) {
            if (batchOperation == 0) {
                _nonReentrantBefore();
            }
            StorageLibBaseV1.AssetServicesValue storage servicesCfg = StorageLibBaseV1.getAssetServicesStorage().value[
                weEth
            ];
            return servicesCfg.ammPoolsService;
        } else if (
            _checkFunctionSigAndIsNotPause(sig, IAmmPoolsService.provideLiquidityUsdt.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmPoolsService.provideLiquidityUsdc.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmPoolsService.provideLiquidityDai.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmPoolsService.redeemFromAmmPoolUsdt.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmPoolsService.redeemFromAmmPoolUsdc.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmPoolsService.redeemFromAmmPoolDai.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmPoolsService.rebalanceBetweenAmmTreasuryAndAssetManagement.selector)
        ) {
            if (batchOperation == 0) {
                _nonReentrantBefore();
            }
            return ammPoolsService;
        } else if (
            _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceUsdm.provideLiquidityUsdmToAmmPoolUsdm.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceUsdm.redeemFromAmmPoolUsdm.selector)
        ) {
            if (batchOperation == 0) {
                _nonReentrantBefore();
            }
            StorageLibBaseV1.AssetServicesValue storage servicesCfg = StorageLibBaseV1.getAssetServicesStorage().value[
                usdm
            ];
            return servicesCfg.ammPoolsService;
        } else if (
            _checkFunctionSigAndIsNotPause(sig, IPowerTokenStakeService.stakeLpTokensToLiquidityMining.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IPowerTokenStakeService.unstakeLpTokensFromLiquidityMining.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IPowerTokenStakeService.stakeGovernanceTokenToPowerToken.selector) ||
            _checkFunctionSigAndIsNotPause(
                sig,
                IPowerTokenStakeService.stakeGovernanceTokenToPowerTokenAndDelegate.selector
            ) ||
            _checkFunctionSigAndIsNotPause(
                sig,
                IPowerTokenStakeService.unstakeGovernanceTokenFromPowerToken.selector
            ) ||
            _checkFunctionSigAndIsNotPause(sig, IPowerTokenStakeService.pwTokenCooldown.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IPowerTokenStakeService.pwTokenCancelCooldown.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IPowerTokenStakeService.redeemPwToken.selector)
        ) {
            if (batchOperation == 0) {
                _nonReentrantBefore();
            }
            return stakeService;
        } else if (
            _checkFunctionSigAndIsNotPause(sig, IPowerTokenFlowsService.delegatePwTokensToLiquidityMining.selector) ||
            _checkFunctionSigAndIsNotPause(sig, IPowerTokenFlowsService.updateIndicatorsInLiquidityMining.selector) ||
            _checkFunctionSigAndIsNotPause(
                sig,
                IPowerTokenFlowsService.undelegatePwTokensFromLiquidityMining.selector
            ) ||
            _checkFunctionSigAndIsNotPause(sig, IPowerTokenFlowsService.claimRewardsFromLiquidityMining.selector)
        ) {
            if (batchOperation == 0) {
                _nonReentrantBefore();
            }
            return flowService;
        } else if (
            sig == IAmmGovernanceService.transferToTreasury.selector ||
            sig == IAmmGovernanceService.transferToCharlieTreasury.selector
        ) {
            if (batchOperation == 0) {
                _nonReentrantBefore();
            }
            return ammGovernanceService;
        } else if (
            sig == IAmmGovernanceService.addSwapLiquidator.selector ||
            sig == IAmmGovernanceService.removeSwapLiquidator.selector ||
            sig == IAmmGovernanceService.addAppointedToRebalanceInAmm.selector ||
            sig == IAmmGovernanceService.removeAppointedToRebalanceInAmm.selector ||
            sig == IAmmGovernanceService.depositToAssetManagement.selector ||
            sig == IAmmGovernanceService.withdrawFromAssetManagement.selector ||
            sig == IAmmGovernanceService.withdrawAllFromAssetManagement.selector ||
            sig == IAmmGovernanceService.setAmmPoolsParams.selector ||
            sig == IAmmGovernanceServiceBaseV1.setMessageSigner.selector ||
            sig == IAmmGovernanceServiceBaseV1.setAssetLensData.selector ||
            sig == IAmmGovernanceServiceBaseV1.setAmmGovernancePoolConfiguration.selector ||
            sig == IAmmGovernanceServiceBaseV1.setAssetServices.selector
        ) {
            _onlyOwner();
            return ammGovernanceService;
        } else if (sig == IAmmCloseSwapServiceStEth.emergencyCloseSwapsStEth.selector) {
            _onlyOwner();
            StorageLibBaseV1.AssetServicesValue storage servicesCfg = StorageLibBaseV1.getAssetServicesStorage().value[
                stEth
            ];
            return servicesCfg.ammCloseSwapService;
        } else if (sig == IAmmCloseSwapServiceUsdt.emergencyCloseSwapsUsdt.selector) {
            _onlyOwner();
            return ammCloseSwapServiceUsdt;
        } else if (sig == IAmmCloseSwapServiceUsdc.emergencyCloseSwapsUsdc.selector) {
            _onlyOwner();
            return ammCloseSwapServiceUsdc;
        } else if (sig == IAmmCloseSwapServiceDai.emergencyCloseSwapsDai.selector) {
            _onlyOwner();
            return ammCloseSwapServiceDai;
        } else if (
            sig == IAmmGovernanceLens.isSwapLiquidator.selector ||
            sig == IAmmGovernanceLens.isAppointedToRebalanceInAmm.selector ||
            sig == IAmmGovernanceLens.getAmmPoolsParams.selector ||
            sig == IAmmGovernanceLens.getAmmGovernancePoolConfiguration.selector
        ) {
            return ammGovernanceService;
        } else if (sig == IAmmOpenSwapLens.getAmmOpenSwapServicePoolConfiguration.selector) {
            return ammOpenSwapService;
        } else if (
            sig == IAmmSwapsLens.getSwaps.selector ||
            sig == IAmmSwapsLens.getPnlPayFixed.selector ||
            sig == IAmmSwapsLens.getPnlReceiveFixed.selector ||
            sig == IAmmSwapsLens.getBalancesForOpenSwap.selector ||
            sig == IAmmSwapsLens.getSoap.selector ||
            sig == IAmmSwapsLens.getOfferedRate.selector ||
            sig == IAmmSwapsLens.getSwapLensPoolConfiguration.selector
        ) {
            return ammSwapsLens;
        } else if (
            sig == IAmmPoolsLens.getAmmPoolsLensConfiguration.selector || sig == IAmmPoolsLens.getAmmBalance.selector
        ) {
            return ammPoolsLens;
        } else if (sig == IAmmPoolsLens.getIpTokenExchangeRate.selector) {
            // Extract asset address from calldata (first parameter after selector)
            address asset;
            assembly {
                asset := calldataload(4)
            }

            // Check if asset uses new BaseV1 architecture (stETH, weETH, USDM)
            if (asset == stEth || asset == weEth || asset == usdm) {
                return ammPoolsLensBaseV1;
            } else {
                // For legacy assets (USDT, USDC, DAI)
                return ammPoolsLens;
            }
        } else if (
            sig == IAssetManagementLens.balanceOfAmmTreasuryInAssetManagement.selector ||
            sig == IAssetManagementLens.getAssetManagementConfiguration.selector
        ) {
            return assetManagementLens;
        } else if (
            sig == ILiquidityMiningLens.balanceOfLpTokensStakedInLiquidityMining.selector ||
            sig == ILiquidityMiningLens.balanceOfPowerTokensDelegatedToLiquidityMining.selector ||
            sig == ILiquidityMiningLens.getAccruedRewardsInLiquidityMining.selector ||
            sig == ILiquidityMiningLens.getAccountIndicatorsFromLiquidityMining.selector ||
            sig == ILiquidityMiningLens.getGlobalIndicatorsFromLiquidityMining.selector ||
            sig == ILiquidityMiningLens.getAccountRewardsInLiquidityMining.selector
        ) {
            return liquidityMiningLens;
        } else if (
            sig == IPowerTokenLens.totalSupplyOfPwToken.selector ||
            sig == IPowerTokenLens.balanceOfPwToken.selector ||
            sig == IPowerTokenLens.balanceOfPwTokenDelegatedToLiquidityMining.selector ||
            sig == IPowerTokenLens.getPwTokensInCooldown.selector ||
            sig == IPowerTokenLens.getPwTokenUnstakeFee.selector ||
            sig == IPowerTokenLens.getPwTokenCooldownTime.selector ||
            sig == IPowerTokenLens.getPwTokenExchangeRate.selector ||
            sig == IPowerTokenLens.getPwTokenTotalSupplyBase.selector
        ) {
            return powerTokenLens;
        } else if (
            sig == IAmmCloseSwapLens.getAmmCloseSwapServicePoolConfiguration.selector ||
            sig == IAmmCloseSwapLens.getClosingSwapDetails.selector
        ) {
            return ammCloseSwapLens;
        } else if (sig == IAmmPoolsService.getAmmPoolServiceConfiguration.selector) {
            return ammPoolsService;
        }

        revert(IporErrors.ROUTER_INVALID_SIGNATURE);
    }
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;

import "./types/IporTypes.sol";
import "./types/AmmTypes.sol";

/// @title AmmSwapsLens interface responsible for reading data related with swaps.
interface IAmmSwapsLens {
    /// @notice IPOR Swap structure.
    struct IporSwap {
        /// @notice Swap's ID.
        uint256 id;
        /// @notice Swap's asset (stablecoin / underlying token)
        address asset;
        /// @notice Swap's buyer address
        address buyer;
        /// @notice Swap's collateral, represented in 18 decimals.
        uint256 collateral;
        /// @notice Notional amount, represented in 18 decimals.
        uint256 notional;
        /// @notice Swap's leverage, represented in 18 decimals.
        uint256 leverage;
        /// @notice Swap's direction
        /// @dev 0 - Pay Fixed-Receive Floating, 1 - Receive Fixed - Pay Floading
        uint256 direction;
        /// @notice Swap's notional amount denominated in the Interest Bearing Token (IBT)
        /// @dev value represented in 18 decimals
        uint256 ibtQuantity;
        /// @notice Fixed interest rate.
        uint256 fixedInterestRate;
        /// @notice Current PnL value (Profit and Loss Value), represented in 18 decimals.
        int256 pnlValue;
        /// @notice Moment when swap was opened.
        uint256 openTimestamp;
        /// @notice Moment when swap achieve its maturity.
        uint256 endTimestamp;
        /// @notice Liquidation deposit value on day when swap was opened. Value represented in 18 decimals.
        uint256 liquidationDepositAmount;
        /// @notice State of the swap
        /// @dev 0 - INACTIVE, 1 - ACTIVE
        uint256 state;
    }

    /// @notice Lens Configuration structure for AmmSwapsLens for a given asset (ppol)
    struct SwapLensPoolConfiguration {
        /// @notice Asset address
        address asset;
        /// @notice Address of the AMM (Automated Market Maker) storage contract
        address ammStorage;
        /// @notice Address of the AMM Treasury contract
        address ammTreasury;
        /// @notice Spread module
        address spread;
    }

    /// @notice Gets pool configuration for AmmSwapsLens
    /// @param asset asset address
    /// @return SwapLensPoolConfiguration pool configuration
    function getSwapLensPoolConfiguration(address asset) external view returns (SwapLensPoolConfiguration memory);

    /// @notice Gets active swaps for a given asset sender address (aka buyer).
    /// @param asset asset address
    /// @param offset offset for paging
    /// @param chunkSize page size for paging
    /// @return totalCount total number of sender's active swaps in AmmTreasury
    /// @return swaps list of active sender's swaps
    function getSwaps(
        address asset,
        address account,
        uint256 offset,
        uint256 chunkSize
    ) external view returns (uint256 totalCount, IporSwap[] memory swaps);

    /// @notice Gets the swap's PnL (Profit and Loss) for a pay-fixed, given asset and swap ID.
    /// @param asset asset address
    /// @param swapId swap ID
    /// @return pnlValue PnL for a pay fixed swap
    function getPnlPayFixed(address asset, uint256 swapId) external view returns (int256 pnlValue);

    /// @notice Gets the swap's PnL (Profit and Loss) for a receive-fixed, given asset and swap ID.
    /// @param asset asset address
    /// @param swapId swap ID
    /// @return pnlValue PnL for a receive fixed swap
    function getPnlReceiveFixed(address asset, uint256 swapId) external view returns (int256 pnlValue);

    /// @notice Gets the balances structure required to open a swap.
    /// @param asset The address of the asset.
    /// @return AmmBalancesForOpenSwapMemory The balances required for opening a swap.
    function getBalancesForOpenSwap(
        address asset
    ) external view returns (IporTypes.AmmBalancesForOpenSwapMemory memory);

    /// @notice Gets the SOAP value for a given asset.
    /// @param asset The address of the asset.
    /// @return soapPayFixed SOAP value for pay fixed swaps.
    /// @return soapReceiveFixed SOAP value for receive fixed swaps.
    /// @return soap SOAP value which is a sum of soapPayFixed and soapReceiveFixed.
    function getSoap(address asset) external view returns (int256 soapPayFixed, int256 soapReceiveFixed, int256 soap);

    /// @notice Gets the offered rate value for a given asset, tenor and notional.
    /// @param asset The address of the asset.
    /// @param tenor The duration of the swap.
    /// @param notional The notional amount of the swap, represented in 18 decimals.
    /// @param payFixedRiskIndicatorsInputs The risk indicators inputs for pay fixed swaps.
    /// @param receiveFixedRiskIndicatorsInputs The risk indicators inputs for receive fixed swaps.
    /// @return offeredRatePayFixed The offered rate for pay fixed swaps.
    /// @return offeredRateReceiveFixed The offered rate for receive fixed swaps.
    function getOfferedRate(
        address asset,
        IporTypes.SwapTenor tenor,
        uint256 notional,
        AmmTypes.RiskIndicatorsInputs calldata payFixedRiskIndicatorsInputs,
        AmmTypes.RiskIndicatorsInputs calldata receiveFixedRiskIndicatorsInputs
    ) external view returns (uint256 offeredRatePayFixed, uint256 offeredRateReceiveFixed);
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;

import "./types/IporTypes.sol";

/// @title Interface responsible for reading the AMM Pools state and configuration.
interface IAmmPoolsLens {
    /// @dev A struct to represent a pool configuration.
    /// @param asset The address of the asset.
    /// @param decimals The number of decimal places the asset uses.
    /// @param ipToken The address of the ipToken associated with the asset.
    /// @param ammStorage The address of the AMM's storage contract.
    /// @param ammTreasury The address of the AMM's treasury contract.
    /// @param assetManagement The address of the asset management contract.
    struct AmmPoolsLensPoolConfiguration {
        address asset;
        uint256 decimals;
        address ipToken;
        address ammStorage;
        address ammTreasury;
        address assetManagement;
    }

    /// @notice Gets Ipor Orale address
    function iporOracle() external view returns (address);

    /// @notice Retrieves the configuration of a specific asset's pool.
    /// @param asset The address of the asset.
    /// @return PoolConfiguration The pool's configuration.
    function getAmmPoolsLensConfiguration(address asset) external view returns (AmmPoolsLensPoolConfiguration memory);

    /// @notice Calculates the ipToken exchange rate.
    /// @dev The exchange rate is a ratio between the Liquidity Pool Balance and the ipToken's total supply.
    /// @param asset The address of the asset.
    /// @return uint256 The ipToken exchange rate for the specific asset, represented in 18 decimals.
    function getIpTokenExchangeRate(address asset) external view returns (uint256);

    /// @notice Retrieves the AmmTreasury balance for a given asset.
    /// @param asset The address of the asset.
    /// @return IporTypes.AmmBalancesMemory The balance of the AMM Treasury.
    function getAmmBalance(address asset) external view returns (IporTypes.AmmBalancesMemory memory);
}

// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.26;

/// @title AssetManagementLens interface responsible for reading data from AssetManagement.
interface IAssetManagementLens {
    /// @dev A struct to represent an asset configuration.
    struct AssetManagementConfiguration {
        /// @notice The address of the asset.
        address asset;
        /// @notice Asset decimals.
        uint256 decimals;
        /// @notice The address of the asset management contract.
        address assetManagement;
        /// @notice The address of the AMM treasury contract.
        address ammTreasury;
    }

    /// @notice Gets the AssetManagement configuration for the given asset.
    /// @param asset The address of the asset.
    /// @return AssetManagementConfiguration The AssetManagement configuration for the given asset.
    function getAssetManagementConfiguration(address asset) external view returns (AssetManagementConfiguration memory);

    /// @notice Gets balance of the AmmTreasury contract in the AssetManagement.
    /// @dev This includes assets transferred to AssetManagement.
    /// @param asset The address of the asset.
    /// @return uint256 The total balance for the specified account, represented in 18 decimals.
    function balanceOfAmmTreasuryInAssetManagement(address asset) external view returns (uint256);
}

// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.26;

/// @title Interface responsible for viewing data from PowerToken smart contract.
interface IPowerTokenLens {
    struct PwTokenCooldown {
        // @dev The timestamp when the account can redeem Power Tokens
        uint256 endTimestamp;
        // @dev The amount of Power Tokens which can be redeemed without fee when the cooldown reaches `endTimestamp`
        uint256 pwTokenAmount;
    }

    struct UpdateStakedToken {
        address beneficiary;
        uint256 stakedTokenAmount;
    }

    /// @notice Gets the total supply of the Power Token.
    /// @dev Value is calculated in runtime using baseTotalSupply and internal exchange rate.
    /// @return Total supply of Power tokens, represented with 18 decimals
    function totalSupplyOfPwToken() external view returns (uint256);

    /// @notice Gets the balance of Power Tokens for a given account
    /// @param account account address for which the balance of Power Tokens is fetched
    /// @return Returns the amount of the Power Tokens owned by the `account`.
    function balanceOfPwToken(address account) external view returns (uint256);

    /// @notice Gets the delegated balance of the Power Tokens for a given account.
    /// Tokens are delegated from PowerToken to LiquidityMining smart contract (reponsible for rewards distribution).
    /// @param account account address for which the balance of delegated Power Tokens is checked
    /// @return  Returns the amount of the Power Tokens owned by the `account` and delegated to the LiquidityMining contracts.
    function balanceOfPwTokenDelegatedToLiquidityMining(address account) external view returns (uint256);

    /// @notice Gets the rate of the fee from the configuration. This fee is applied when the owner of Power Tokens wants to unstake them immediately.
    /// @dev Fee value represented in as a percentage with 18 decimals
    /// @return value, a percentage represented with 18 decimal
    function getPwTokenUnstakeFee() external view returns (uint256);

    /// @notice Gets the state of the active cooldown for the sender.
    /// @dev If PowerTokenCoolDown contains only zeros it represents no active cool down.
    /// Struct containing information on when the cooldown end and what is the quantity of the Power Tokens locked.
    /// @param account account address that owns Power Tokens in the cooldown
    /// @return Object PowerTokenCoolDown represents active cool down
    function getPwTokensInCooldown(address account) external view returns (PwTokenCooldown memory);

    /// @notice Gets the power token cool down time in seconds.
    /// @return uint256 cool down time in seconds
    function getPwTokenCooldownTime() external view returns (uint256);

    /// @notice Calculates the internal exchange rate between the Staked Token and total supply of a base amount
    /// @return Current exchange rate between the Staked Token and the total supply of a base amount, represented with 18 decimals.
    function getPwTokenExchangeRate() external view returns (uint256);

    /// @notice Gets the total supply base amount
    /// @return total supply base amount, represented with 18 decimals
    function getPwTokenTotalSupplyBase() external view returns (uint256);
}

// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.26;

/// @title LiquidityMiningLens interface responsible for reading data from LiquidityMining.
interface ILiquidityMiningLens {
    /// @title Struct pair representing delegated pwToken balance
    struct DelegatedPwTokenBalance {
        /// @notice lpToken address
        address lpToken;
        /// @notice The amount of Power Token delegated to lpToken staking pool
        /// @dev value represented in 18 decimals
        uint256 pwTokenAmount;
    }

    /// @title Global indicators used in rewards calculation.
    struct GlobalRewardsIndicators {
        /// @notice powerUp indicator aggregated
        /// @dev It can be changed many times during transaction, represented with 18 decimals
        uint256 aggregatedPowerUp;
        /// @notice composite multiplier in a block described in field blockNumber
        /// @dev It can be changed many times during transaction, represented with 27 decimals
        uint128 compositeMultiplierInTheBlock;
        /// @notice Composite multiplier updated in block {blockNumber} but calculated for PREVIOUS (!) block.
        /// @dev It can be changed once per block, represented with 27 decimals
        uint128 compositeMultiplierCumulativePrevBlock;
        /// @dev It can be changed once per block. Block number in which all other params of this structure are updated
        uint32 blockNumber;
        /// @notice value describing amount of rewards issued per block,
        /// @dev It can be changed at most once per block, represented with 8 decimals
        uint32 rewardsPerBlock;
        /// @notice amount of accrued rewards since inception
        /// @dev It can be changed at most once per block, represented with 18 decimals
        uint88 accruedRewards;
    }

    /// @title Params recorded for a given account. These params are used by the algorithm responsible for rewards distribution.
    /// @dev The structure in storage is updated when account interacts with the LiquidityMining smart contract (stake, unstake, delegate, undelegate, claim)
    struct AccountRewardsIndicators {
        /// @notice `composite multiplier cumulative` is calculated for previous block
        /// @dev represented in 27 decimals
        uint128 compositeMultiplierCumulativePrevBlock;
        /// @notice lpToken account's balance
        uint128 lpTokenBalance;
        /// @notice PowerUp is a result of logarithmic equastion,
        /// @dev  powerUp < 100 *10^18
        uint72 powerUp;
        /// @notice balance of Power Tokens delegated to LiquidityMining
        /// @dev delegatedPwTokenBalance < 10^26 < 2^87
        uint96 delegatedPwTokenBalance;
    }

    struct UpdateLpToken {
        address beneficiary;
        address lpToken;
        uint256 lpTokenAmount;
    }

    struct UpdatePwToken {
        address beneficiary;
        address lpToken;
        uint256 pwTokenAmount;
    }

    struct AccruedRewardsResult {
        address lpToken;
        uint256 rewardsAmount;
    }

    struct AccountRewardResult {
        address lpToken;
        uint256 rewardsAmount;
        uint256 allocatedPwTokens;
    }

    struct AccountIndicatorsResult {
        address lpToken;
        AccountRewardsIndicators indicators;
    }

    struct GlobalIndicatorsResult {
        address lpToken;
        GlobalRewardsIndicators indicators;
    }

    /// @notice Returns the balance of LP tokens staked by the specified account in the Liquidity Mining contract.
    /// @param account The address of the account for which the LP token balance is queried.
    /// @param lpToken The address of the LP token for which the balance is queried.
    /// @return The balance of LP tokens staked by the specified account.
    function balanceOfLpTokensStakedInLiquidityMining(address account, address lpToken) external view returns (uint256);

    /// @notice It returns the balance of delegated Power Tokens for a given `account` and the list of lpToken addresses.
    /// @param account address for which to fetch the information about balance of delegated Power Tokens
    /// @param lpTokens list of lpTokens addresses(lpTokens)
    /// @return balances list of {LiquidityMiningTypes.DelegatedPwTokenBalance} structure, with information how much Power Token is delegated per lpToken address.
    function balanceOfPowerTokensDelegatedToLiquidityMining(
        address account,
        address[] memory lpTokens
    ) external view returns (DelegatedPwTokenBalance[] memory balances);

    /// @notice Calculates the accrued rewards for the specified LP tokens in the Liquidity Mining contract.
    /// @param lpTokens An array of LP tokens for which the accrued rewards are to be calculated.
    /// @return result An array of `AccruedRewardsResult` structs containing the accrued rewards information for each LP token.
    function getAccruedRewardsInLiquidityMining(
        address[] calldata lpTokens
    ) external view returns (AccruedRewardsResult[] memory result);

    /// @notice Calculates the rewards for the specified account and LP tokens in the Liquidity Mining contract.
    /// @param account The address of the account for which the rewards are to be calculated.
    /// @param lpTokens An array of LP tokens for which the rewards are to be calculated.
    /// @return An array of `AccountRewardResult` structs containing the rewards information for each LP token.
    function getAccountRewardsInLiquidityMining(
        address account,
        address[] calldata lpTokens
    ) external view returns (AccountRewardResult[] memory);

    /// @notice Retrieves the global indicators for the specified LP tokens in the Liquidity Mining contract.
    /// @param lpTokens An array of LP tokens for which the global indicators are to be retrieved.
    /// @return An array of `GlobalIndicatorsResult` structs containing the global indicators information for each LP token.
    function getGlobalIndicatorsFromLiquidityMining(
        address[] memory lpTokens
    ) external view returns (GlobalIndicatorsResult[] memory);

    /// @notice Retrieves the account indicators for the specified account and LP tokens in the Liquidity Mining contract.
    /// @param account The address of the account for which the account indicators are to be retrieved.
    /// @param lpTokens An array of LP tokens for which the account indicators are to be retrieved.
    /// @return An array of `AccountIndicatorsResult` structs containing the account indicators information for each LP token.
    function getAccountIndicatorsFromLiquidityMining(
        address account,
        address[] memory lpTokens
    ) external view returns (AccountIndicatorsResult[] memory);
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;

/// @title Interface for interacting with the AmmGovernanceService. Interface responsible for managing AMM Pools.
interface IAmmGovernanceService {
    /// @notice Transfers the asset amount from the AmmTreasury to the AssetManagement. Action available only to the IPOR Protocol Owner.
    /// @param asset Address of asset representing specific pool
    /// @param assetAmount Amount of asset to transfer
    function depositToAssetManagement(address asset, uint256 assetAmount) external;

    /// @notice Transfers the asset amount from the AssetManagement to the AmmTreasury. Action available only to the IPOR Protocol Owner.
    /// @param asset Address of asset representing specific pool
    /// @param assetAmount Amount of asset to transfer
    function withdrawFromAssetManagement(address asset, uint256 assetAmount) external;

    /// @notice Transfers all of the asset from the AssetManagement to the AmmTreasury. Action available only to the IPOR Protocol Owner.
    /// @param asset Address of the asset representing specific pool
    function withdrawAllFromAssetManagement(address asset) external;

    /// @notice Transfers the asset amount from the AmmTreasury to the Treasury Wallet. Action available only to the AMM Treasury Manager.
    /// @dev The AMM collects a part of swap's opening fee adn accounts it towards the "treasury".
    /// @param asset Address of asset representing specific pool
    /// @param assetAmount Amount of asset to transfer
    function transferToTreasury(address asset, uint256 assetAmount) external;

    /// @notice Transfers the asset amount from the AmmTreasury to Oracle Treasury Wallet. Action available only to the  AMM Charlie Treasury Manager.
    /// @dev A specific balance known as "iporPublicationFee" exists in AmmTreasury, which is used to collect IPOR publication fees from traders when they initiate swaps.
    /// @dev Within the AmmTreasury, there exists a distinct balance known as "iporPublicationFee," which is utilized by the AMM to accumulate IPOR publication fees from traders as they open swaps.
    /// @param asset Address of asset representing specific pool
    /// @param assetAmount Amount of asset to transfer
    function transferToCharlieTreasury(address asset, uint256 assetAmount) external;

    /// @notice Adds an account to the list of swap liquidators for a given asset. Action available only to IPOR Protocol Owner.
    /// @param asset Address of asset representing specific pool
    /// @param account Address of an account added to the list of swap liquidators
    function addSwapLiquidator(address asset, address account) external;

    /// @notice Removes an account from the list of swap liquidators for a given asset. Action available only to IPOR Protocol Owner.
    /// @param asset Address of asset representing specific pool
    /// @param account Address of an account removed to the list of swap liquidators
    function removeSwapLiquidator(address asset, address account) external;

    /// @notice Add an account to the list of addresses appointed to rebalance AMM for given asset. Action available only to the IPOR Protocol Owner.
    /// @param asset Address of asset representing specific pool
    /// @param account Address of an account added to the list of addresses appointed to rebalance in AMM
    /// @dev Rebalancing the AMM is a process of moving liquidity between the AMM and the AssetManagement in the amount defined in param called "ammTreasuryAndAssetManagementRatio".
    function addAppointedToRebalanceInAmm(address asset, address account) external;

    /// @notice Remove account from the list of appointed to rebalance in AMM for given asset.
    /// @param asset Address of asset which represents specific pool
    /// @param account Address of account which is removed from the list of appointed to rebalance in AMM
    /// @dev Rebalancing the AMM is a process of moving liquidity between the AMM and the AssetManagement in the amount defined in param called "ammTreasuryAndAssetManagementRatio".
    function removeAppointedToRebalanceInAmm(address asset, address account) external;

    /// @notice Sets AMM Pools params for a given asset (pool). Action available only to IPOR Protocol Owner.
    /// @param asset Address of asset representing specific pool
    /// @param newMaxLiquidityPoolBalance New max liquidity pool balance threshold. Value represented WITHOUT 18 decimals.
    /// @param newAutoRebalanceThreshold New auto rebalance threshold (for stablecoins represented in thousands). Value represented WITHOUT 18 decimals. For stablecoins value represents multiplication of 1000.
    /// @param newAmmTreasuryAndAssetManagementRatio New AMM Treasury and Asset Management ratio, represented WITHOUT 18 decimals, value represents percentage with 2 decimals. Example: 65% = 6500, 99,99% = 9999. The value determines what percentage of total funds remains in AMM treasury, while the rest goes to asset management.
    function setAmmPoolsParams(
        address asset,
        uint32 newMaxLiquidityPoolBalance,
        uint32 newAutoRebalanceThreshold,
        uint16 newAmmTreasuryAndAssetManagementRatio
    ) external;
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;

/// @title Interface for interacting with AmmGovernanceLens. Interface responsible for reading data from AMM Governance.
interface IAmmGovernanceLens {
    /// @notice Structure of common params described AMM Pool configuration
    struct AmmGovernancePoolConfiguration {
        /// @notice address of asset which represents specific pool
        address asset;
        /// @notice asset decimals
        uint256 decimals;
        /// @notice address of AMM Storage
        address ammStorage;
        /// @notice address of AMM Treasury
        address ammTreasury;
        /// @notice address of AMM Asset Management
        address ammVault;
        /// @notice address of AMM Pools Treasury Wallet
        address ammPoolsTreasury;
        /// @notice address of user which is allowed to manage AMM Pools Treasury Wallet
        address ammPoolsTreasuryManager;
        /// @notice address of AMM Charlie Treasury Wallet
        address ammCharlieTreasury;
        /// @notice address of user which is allowed to manage AMM Charlie Treasury Wallet
        address ammCharlieTreasuryManager;
    }

    /// @dev A struct to represent a pool's parameters configuration.
    struct AmmPoolsParamsConfiguration {
        /// @dev max liquidity pool balance in the asset pool, represented in 18 decimals
        uint256 maxLiquidityPoolBalance;
        /// @dev The threshold for auto-rebalancing the pool. Value represented without 18 decimals.
        uint256 autoRebalanceThreshold;
        /// @dev asset management ratio, represented without 18 decimals, value represents percentage with 2 decimals
        /// 65% = 6500, 99,99% = 9999, this is a percentage which stay in Amm Treasury in opposite to Asset Management
        /// based on AMM Treasury balance (100%).
        uint256 ammTreasuryAndAssetManagementRatio;
    }

    /// @notice Gets the structure or common params described AMM Pool configuration
    /// @param asset Address of asset which represents specific pool
    /// @return poolConfiguration Structure of common params described AMM Pool configuration
    function getAmmGovernancePoolConfiguration(
        address asset
    ) external view returns (AmmGovernancePoolConfiguration memory);

    /// @notice Flag which indicates if given account is an liquidator for given asset
    /// @param asset Address of asset which represents specific pool
    /// @param account Address of account which is checked if is an liquidator
    /// @return isSwapLiquidator Flag which indicates if given account is an liquidator for given asset
    function isSwapLiquidator(address asset, address account) external view returns (bool);

    /// @notice Flag which indicates if given account is an appointed to rebalance in AMM for given asset
    /// @param asset Address of asset which represents specific pool
    /// @param account Address of account which is checked if is an appointed to rebalance in AMM
    /// @return isAppointedToRebalanceInAmm Flag which indicates if given account is an appointed to rebalance in AMM for given asset
    function isAppointedToRebalanceInAmm(address asset, address account) external view returns (bool);

    /// @notice Gets the structure or common params described AMM Pool configuration
    /// @param asset Address of asset which represents specific pool
    /// @return ammPoolsParams Structure of common params described AMM Pool configuration
    function getAmmPoolsParams(address asset) external view returns (AmmPoolsParamsConfiguration memory);
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;

/// @title Interface of the service allowing to open new swaps.
interface IAmmOpenSwapLens {
    /// @notice Structure representing configuration of the AmmOpenSwapServicePool for specific asset (pool).
    struct AmmOpenSwapServicePoolConfiguration {
        /// @notice address of the asset
        address asset;
        /// @notice asset decimals
        uint256 decimals;
        /// @notice address of the AMM Storage
        address ammStorage;
        /// @notice address of the AMM Treasury
        address ammTreasury;
        /// @notice ipor publication fee, fee used when opening swap, represented in 18 decimals.
        uint256 iporPublicationFee;
        /// @notice maximum swap collateral amount, represented in 18 decimals.
        uint256 maxSwapCollateralAmount;
        /// @notice liquidation deposit amount, represented WITHOUT 18 decimals. Example 25 = 25 USDT.
        uint256 liquidationDepositAmount;
        /// @notice minimum leverage, represented in 18 decimals.
        uint256 minLeverage;
        /// @notice swap's opening fee rate, represented in 18 decimals. 1e18 = 100%
        uint256 openingFeeRate;
        /// @notice swap's opening fee rate, portion of the rate which is allocated to "treasury" balance
        /// @dev Value describes what percentage of opening fee amount is allocated to "treasury" balance. Value represented in 18 decimals. 1e18 = 100%
        uint256 openingFeeTreasuryPortionRate;
    }

    /// @notice Returns configuration of the AmmOpenSwapServicePool for specific asset (pool).
    /// @param asset address of the asset
    /// @return AmmOpenSwapServicePoolConfiguration structure representing configuration of the AmmOpenSwapServicePool for specific asset (pool).
    function getAmmOpenSwapServicePoolConfiguration(
        address asset
    ) external view returns (AmmOpenSwapServicePoolConfiguration memory);
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;

import "./types/AmmTypes.sol";

/// @title Interface of the service allowing to open new swaps.
interface IAmmOpenSwapService {
    /// @notice Emitted when the trader opens new swap.
    event OpenSwap(
        /// @notice swap ID.
        uint256 indexed swapId,
        /// @notice trader that opened the swap
        address indexed buyer,
        /// @notice underlying asset
        address asset,
        /// @notice swap direction, Pay Fixed Receive Floating or Pay Floating Receive Fixed.
        AmmTypes.SwapDirection direction,
        /// @notice technical structure with amounts related with this swap
        AmmTypes.OpenSwapAmount amounts,
        /// @notice the moment when swap was opened
        uint256 openTimestamp,
        /// @notice the moment when swap will achieve maturity
        uint256 endTimestamp,
        /// @notice specific indicators related with this swap
        AmmTypes.IporSwapIndicator indicator
    );

    /// @notice It opens a swap for USDT pay-fixed receive-floating with a tenor of 28 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param totalAmount total amount used by sender to open the swap, represented in decimals specific to the asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @param riskIndicatorsInputs technical structure with risk indicators inputs
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapPayFixed28daysUsdt(
        address beneficiary,
        uint256 totalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external returns (uint256);

    /// @notice It opens a swap for USDT pay-fixed receive-floating with a tenor of 60 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param totalAmount total amount used by sender to open the swap, represented in decimals specific to the asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @param riskIndicatorsInputs technical structure with risk indicators inputs
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapPayFixed60daysUsdt(
        address beneficiary,
        uint256 totalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external returns (uint256);

    /// @notice It opens a swap for USDT pay-fixed receive-floating with a tenor of 90 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param totalAmount total amount used by sender to open the swap, represented in decimals specific to the asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @param riskIndicatorsInputs technical structure with risk indicators inputs
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapPayFixed90daysUsdt(
        address beneficiary,
        uint256 totalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external returns (uint256);

    /// @notice It opens a swap for USDT receive-fixed pay-floating with a tenor of 28 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param totalAmount total amount used by sender to open the swap, represented in decimals specific to the asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @param riskIndicatorsInputs technical structure with risk indicators inputs
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapReceiveFixed28daysUsdt(
        address beneficiary,
        uint256 totalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external returns (uint256);

    /// @notice It opens a swap for USDT receive-fixed pay-floating with a tenor of 60 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param totalAmount total amount used by sender to open the swap, represented in decimals specific to the asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @param riskIndicatorsInputs technical structure with risk indicators inputs
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapReceiveFixed60daysUsdt(
        address beneficiary,
        uint256 totalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external returns (uint256);

    /// @notice It opens a swap for USDT receive-fixed pay-floating with a tenor of 90 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param totalAmount total amount used by sender to open the swap, represented in decimals specific to the asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @param riskIndicatorsInputs technical structure with risk indicators inputs
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapReceiveFixed90daysUsdt(
        address beneficiary,
        uint256 totalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external returns (uint256);

    /// @notice It opens a swap for USDC pay-fixed receive-floating with a tenor of 28 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param totalAmount total amount used by sender to open the swap, represented in decimals specific to the asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @param riskIndicatorsInputs technical structure with risk indicators inputs
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapPayFixed28daysUsdc(
        address beneficiary,
        uint256 totalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external returns (uint256);

    /// @notice It opens a swap for USDC pay-fixed receive-floating with a tenor of 60 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param totalAmount total amount used by sender to open the swap, represented in decimals specific to the asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @param riskIndicatorsInputs technical structure with risk indicators inputs
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapPayFixed60daysUsdc(
        address beneficiary,
        uint256 totalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external returns (uint256);

    /// @notice It opens a swap for USDC pay-fixed receive-floating with a tenor of 90 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param totalAmount total amount used by sender to open the swap, represented in decimals specific to the asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @param riskIndicatorsInputs technical structure with risk indicators inputs
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapPayFixed90daysUsdc(
        address beneficiary,
        uint256 totalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external returns (uint256);

    /// @notice It opens a swap for USDC receive-fixed pay-floating with a tenor of 28 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param totalAmount total amount used by sender to open the swap, represented in decimals specific to the asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @param riskIndicatorsInputs technical structure with risk indicators inputs
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapReceiveFixed28daysUsdc(
        address beneficiary,
        uint256 totalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external returns (uint256);

    /// @notice It opens a swap for USDC receive-fixed pay-floating with a tenor of 60 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param totalAmount total amount used by sender to open the swap, represented in decimals specific to the asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @param riskIndicatorsInputs technical structure with risk indicators inputs
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapReceiveFixed60daysUsdc(
        address beneficiary,
        uint256 totalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external returns (uint256);

    /// @notice It opens a swap for USDC receive-fixed pay-floating with a tenor of 90 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param totalAmount total amount used by sender to open the swap, represented in decimals specific to the asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @param riskIndicatorsInputs technical structure with risk indicators inputs
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapReceiveFixed90daysUsdc(
        address beneficiary,
        uint256 totalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external returns (uint256);

    /// @notice It opens a swap for DAI pay-fixed receive-floating with a tenor of 28 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param totalAmount total amount used by sender to open the swap, represented in decimals specific to the asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @param riskIndicatorsInputs technical structure with risk indicators inputs
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapPayFixed28daysDai(
        address beneficiary,
        uint256 totalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external returns (uint256);

    /// @notice It opens a swap for DAI pay-fixed receive-floating with a tenor of 60 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param totalAmount total amount used by sender to open the swap, represented in decimals specific to the asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @param riskIndicatorsInputs technical structure with risk indicators inputs
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapPayFixed60daysDai(
        address beneficiary,
        uint256 totalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external returns (uint256);

    /// @notice It opens a swap for DAI pay-fixed receive-floating with a tenor of 90 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param totalAmount total amount used by sender to open the swap, represented in decimals specific to the asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @param riskIndicatorsInputs technical structure with risk indicators inputs
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapPayFixed90daysDai(
        address beneficiary,
        uint256 totalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external returns (uint256);

    /// @notice It opens a swap for DAI receive-fixed pay-floating with a tenor of 28 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param totalAmount total amount used by sender to open the swap, represented in decimals specific to the asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @param riskIndicatorsInputs technical structure with risk indicators inputs
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapReceiveFixed28daysDai(
        address beneficiary,
        uint256 totalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external returns (uint256);

    /// @notice It opens a swap for DAI receive-fixed pay-floating with a tenor of 60 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param totalAmount total amount used by sender to open the swap, represented in decimals specific to the asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @param riskIndicatorsInputs technical structure with risk indicators inputs
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapReceiveFixed60daysDai(
        address beneficiary,
        uint256 totalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external returns (uint256);

    /// @notice It opens a swap for DAI receive-fixed pay-floating with a tenor of 90 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param totalAmount total amount used by sender to open the swap, represented in decimals specific to the asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @param riskIndicatorsInputs technical structure with risk indicators inputs
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapReceiveFixed90daysDai(
        address beneficiary,
        uint256 totalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external returns (uint256);
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;

import "./types/AmmTypes.sol";

/// @title Interface of the service allowing to open new swaps.
interface IAmmOpenSwapServiceStEth {
    /// @notice It opens a swap for stETH pay-fixed receive-floating with a tenor of 28 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param inputAsset address of the entered asset used by sender to open the swap which is accounted in underlying asset.
    /// @param inputAssetTotalAmount total amount of input asset used by sender to open the swap, represented in decimals of the input asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapPayFixed28daysStEth(
        address beneficiary,
        address inputAsset,
        uint256 inputAssetTotalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external payable returns (uint256);

    /// @notice It opens a swap for stETH pay-fixed receive-floating with a tenor of 60 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param inputAsset address of the entered asset used by sender to open the swap which is accounted in underlying asset.
    /// @param inputAssetTotalAmount total amount of input asset used by sender to open the swap, represented in decimals of the input asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapPayFixed60daysStEth(
        address beneficiary,
        address inputAsset,
        uint256 inputAssetTotalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external payable returns (uint256);

    /// @notice It opens a swap for stETH pay-fixed receive-floating with a tenor of 90 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param inputAsset address of the entered asset used by sender to open the swap which is accounted in underlying asset.
    /// @param inputAssetTotalAmount total amount of input asset used by sender to open the swap, represented in decimals of the input asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapPayFixed90daysStEth(
        address beneficiary,
        address inputAsset,
        uint256 inputAssetTotalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external payable returns (uint256);

    /// @notice It opens a swap for stETH receive-fixed pay-floating with a tenor of 28 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param inputAsset address of the entered asset used by sender to open the swap which is accounted in underlying asset.
    /// @param inputAssetTotalAmount total amount of input asset used by sender to open the swap, represented in decimals of the input asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapReceiveFixed28daysStEth(
        address beneficiary,
        address inputAsset,
        uint256 inputAssetTotalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external payable returns (uint256);

    /// @notice It opens a swap for stETH receive-fixed pay-floating with a tenor of 60 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param inputAsset address of the entered asset used by sender to open the swap which is accounted in underlying asset.
    /// @param inputAssetTotalAmount total amount of input asset used by sender to open the swap, represented in decimals of the input asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapReceiveFixed60daysStEth(
        address beneficiary,
        address inputAsset,
        uint256 inputAssetTotalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external payable returns (uint256);

    /// @notice It opens a swap for stETH receive-fixed pay-floating with a tenor of 90 days.
    /// @param beneficiary address of the owner of the swap.
    /// @param inputAsset address of the entered asset used by sender to open the swap which is accounted in underlying asset.
    /// @param inputAssetTotalAmount total amount of input asset used by sender to open the swap, represented in decimals of the input asset.
    /// @param acceptableFixedInterestRate acceptable fixed interest rate, represented in 18 decimals.
    /// @param leverage swap leverage, represented in 18 decimals.
    /// @return swapId ID of the opened swap.
    /// @dev The address `beneficiary` is the swap's owner. Sender pays for the swap.
    function openSwapReceiveFixed90daysStEth(
        address beneficiary,
        address inputAsset,
        uint256 inputAssetTotalAmount,
        uint256 acceptableFixedInterestRate,
        uint256 leverage,
        AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs
    ) external payable returns (uint256);
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;

import "./types/AmmTypes.sol";

/// @title Interface of the service allowing to close swaps.
interface IAmmCloseSwapServiceUsdt {
    /// @notice Closes batch of USDT swaps on both legs.
    /// @param beneficiary account - receiver of liquidation deposit.
    /// @param payFixedSwapIds array of pay-fixed swap IDs.
    /// @param receiveFixedSwapIds array of receive-fixed swap IDs.
    /// @param riskIndicatorsInput risk indicators input
    /// @dev Swap PnL is always transferred to the swaps's owner.
    /// @return closedPayFixedSwaps array of closed pay-fixed swaps.
    /// @return closedReceiveFixedSwaps array of closed receive-fixed swaps.
    function closeSwapsUsdt(
        address beneficiary,
        uint256[] memory payFixedSwapIds,
        uint256[] memory receiveFixedSwapIds,
        AmmTypes.CloseSwapRiskIndicatorsInput calldata riskIndicatorsInput
    )
        external
        returns (
            AmmTypes.IporSwapClosingResult[] memory closedPayFixedSwaps,
            AmmTypes.IporSwapClosingResult[] memory closedReceiveFixedSwaps
        );

    /// @notice Closes batch of USDT swaps on both legs in emergency mode by Owner of Ipor Protocol Router.
    /// @param payFixedSwapIds array of pay-fixed swap IDs.
    /// @param receiveFixedSwapIds array of receive-fixed swap IDs.
    /// @param riskIndicatorsInput risk indicators input
    /// @return closedPayFixedSwaps array of closed pay-fixed swaps.
    /// @return closedReceiveFixedSwaps array of closed receive-fixed swaps.
    function emergencyCloseSwapsUsdt(
        uint256[] memory payFixedSwapIds,
        uint256[] memory receiveFixedSwapIds,
        AmmTypes.CloseSwapRiskIndicatorsInput calldata riskIndicatorsInput
    )
        external
        returns (
            AmmTypes.IporSwapClosingResult[] memory closedPayFixedSwaps,
            AmmTypes.IporSwapClosingResult[] memory closedReceiveFixedSwaps
        );
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;

import "./types/AmmTypes.sol";

/// @title Interface of the service allowing to close swaps.
interface IAmmCloseSwapServiceUsdc {
    /// @notice Closes batch of USDC swaps on both legs.
    /// @param beneficiary account - receiver of liquidation deposit.
    /// @param payFixedSwapIds array of pay-fixed swap IDs.
    /// @param receiveFixedSwapIds array of receive-fixed swap IDs.
    /// @param riskIndicatorsInput risk indicators input
    /// @dev Swap PnL is always transferred to the swaps's owner.
    /// @return closedPayFixedSwaps array of closed pay-fixed swaps.
    /// @return closedReceiveFixedSwaps array of closed receive-fixed swaps.
    function closeSwapsUsdc(
        address beneficiary,
        uint256[] memory payFixedSwapIds,
        uint256[] memory receiveFixedSwapIds,
        AmmTypes.CloseSwapRiskIndicatorsInput calldata riskIndicatorsInput
    )
        external
        returns (
            AmmTypes.IporSwapClosingResult[] memory closedPayFixedSwaps,
            AmmTypes.IporSwapClosingResult[] memory closedReceiveFixedSwaps
        );

    /// @notice Closes batch of USDC swaps on both legs in emergency mode by Owner of Ipor Protocol Router.
    /// @param payFixedSwapIds array of pay-fixed swap IDs.
    /// @param receiveFixedSwapIds array of receive-fixed swap IDs.
    /// @param riskIndicatorsInput risk indicators input
    /// @return closedPayFixedSwaps array of closed pay-fixed swaps.
    /// @return closedReceiveFixedSwaps array of closed receive-fixed swaps.
    function emergencyCloseSwapsUsdc(
        uint256[] memory payFixedSwapIds,
        uint256[] memory receiveFixedSwapIds,
        AmmTypes.CloseSwapRiskIndicatorsInput calldata riskIndicatorsInput
    )
        external
        returns (
            AmmTypes.IporSwapClosingResult[] memory closedPayFixedSwaps,
            AmmTypes.IporSwapClosingResult[] memory closedReceiveFixedSwaps
        );
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;

import "./types/AmmTypes.sol";

/// @title Interface of the service allowing to close swaps.
interface IAmmCloseSwapServiceDai {
    /// @notice Closes batch of DAI swaps on both legs.
    /// @param beneficiary account - receiver of liquidation deposit.
    /// @param payFixedSwapIds array of pay-fixed swap IDs.
    /// @param receiveFixedSwapIds array of receive-fixed swap IDs.
    /// @param riskIndicatorsInput risk indicators input
    /// @dev Swap PnL is always transferred to the swaps's owner.
    /// @return closedPayFixedSwaps array of closed pay-fixed swaps.
    /// @return closedReceiveFixedSwaps array of closed receive-fixed swaps.
    function closeSwapsDai(
        address beneficiary,
        uint256[] memory payFixedSwapIds,
        uint256[] memory receiveFixedSwapIds,
        AmmTypes.CloseSwapRiskIndicatorsInput calldata riskIndicatorsInput
    )
        external
        returns (
            AmmTypes.IporSwapClosingResult[] memory closedPayFixedSwaps,
            AmmTypes.IporSwapClosingResult[] memory closedReceiveFixedSwaps
        );

    /// @notice Closes batch of DAI swaps on both legs in emergency mode by Owner of Ipor Protocol Router.
    /// @param payFixedSwapIds array of pay-fixed swap IDs.
    /// @param receiveFixedSwapIds array of receive-fixed swap IDs.
    /// @param riskIndicatorsInput risk indicators input
    /// @return closedPayFixedSwaps array of closed pay-fixed swaps.
    /// @return closedReceiveFixedSwaps array of closed receive-fixed swaps.
    function emergencyCloseSwapsDai(
        uint256[] memory payFixedSwapIds,
        uint256[] memory receiveFixedSwapIds,
        AmmTypes.CloseSwapRiskIndicatorsInput calldata riskIndicatorsInput
    )
        external
        returns (
            AmmTypes.IporSwapClosingResult[] memory closedPayFixedSwaps,
            AmmTypes.IporSwapClosingResult[] memory closedReceiveFixedSwaps
        );
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;

import "./types/AmmTypes.sol";

/// @title Interface of the service allowing to close swaps in stETH AMM.
interface IAmmCloseSwapServiceStEth {
    /// @notice Closes batch of stETH swaps on both legs.
    /// @param beneficiary account - receiver of liquidation deposit.
    /// @param payFixedSwapIds array of pay fixed swap IDs.
    /// @param receiveFixedSwapIds array of receive fixed swap IDs.
    /// @dev Swap PnL is always transferred to the swaps's owner.
    /// @return closedPayFixedSwaps array of closed pay-fixed swaps.
    /// @return closedReceiveFixedSwaps array of closed receive-fixed swaps.
    function closeSwapsStEth(
        address beneficiary,
        uint256[] memory payFixedSwapIds,
        uint256[] memory receiveFixedSwapIds,
        AmmTypes.CloseSwapRiskIndicatorsInput calldata riskIndicatorsInput
    )
        external
        returns (
            AmmTypes.IporSwapClosingResult[] memory closedPayFixedSwaps,
            AmmTypes.IporSwapClosingResult[] memory closedReceiveFixedSwaps
        );

    /// @notice Closes batch of stETH swaps on both legs in emergency mode by Owner of Ipor Protocol Router.
    /// @param payFixedSwapIds array of pay-fixed swap IDs.
    /// @param receiveFixedSwapIds array of receive-fixed swap IDs.
    /// @return closedPayFixedSwaps array of closed pay-fixed swaps.
    /// @return closedReceiveFixedSwaps array of closed receive-fixed swaps.
    function emergencyCloseSwapsStEth(
        uint256[] memory payFixedSwapIds,
        uint256[] memory receiveFixedSwapIds,
        AmmTypes.CloseSwapRiskIndicatorsInput calldata riskIndicatorsInput
    )
        external
        returns (
            AmmTypes.IporSwapClosingResult[] memory closedPayFixedSwaps,
            AmmTypes.IporSwapClosingResult[] memory closedReceiveFixedSwaps
        );
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;

import "./types/AmmTypes.sol";

/// @title Interface of the CloseSwap Lens.
interface IAmmCloseSwapLens {
    /// @notice Structure representing the configuration of the AmmCloseSwapService for a given pool (asset).
    struct AmmCloseSwapServicePoolConfiguration {
        /// @notice asset address
        address asset;
        /// @notice asset decimals
        uint256 decimals;
        /// @notice Amm Storage contract address
        address ammStorage;
        /// @notice Amm Treasury contract address
        address ammTreasury;
        /// @notice Asset Management contract address, for stETH is empty, because stETH doesn't have asset management module
        address assetManagement;
        /// @notice Spread address, for USDT, USDC, DAI is a spread router address, for stETH is a spread address
        address spread;
        /// @notice Unwinding Fee Rate for unwinding the swap, represented in 18 decimals, 1e18 = 100%
        uint256 unwindingFeeRate;
        /// @notice Unwinding Fee Rate for unwinding the swap, part earmarked for the treasury, represented in 18 decimals, 1e18 = 100%
        uint256 unwindingFeeTreasuryPortionRate;
        /// @notice Max number of swaps (per leg) that can be liquidated in one call, represented without decimals
        uint256 maxLengthOfLiquidatedSwapsPerLeg;
        /// @notice Time before maturity when the community is allowed to close the swap, represented in seconds
        uint256 timeBeforeMaturityAllowedToCloseSwapByCommunity;
        /// @notice Time before maturity then the swap owner can close it, for tenor 28 days, represented in seconds
        uint256 timeBeforeMaturityAllowedToCloseSwapByBuyerTenor28days;
        /// @notice Time before maturity then the swap owner can close it, for tenor 60 days, represented in seconds
        uint256 timeBeforeMaturityAllowedToCloseSwapByBuyerTenor60days;
        /// @notice Time before maturity then the swap owner can close it, for tenor 90 days, represented in seconds
        uint256 timeBeforeMaturityAllowedToCloseSwapByBuyerTenor90days;
        /// @notice Min liquidation threshold allowing community to close the swap ahead of maturity, represented in 18 decimals
        uint256 minLiquidationThresholdToCloseBeforeMaturityByCommunity;
        /// @notice Min liquidation threshold allowing the owner to close the swap ahead of maturity, represented in 18 decimals
        uint256 minLiquidationThresholdToCloseBeforeMaturityByBuyer;
        /// @notice Min leverage of the virtual swap used in unwinding, represented in 18 decimals
        uint256 minLeverage;
        /// @notice Time after open swap when it is allowed to close swap with unwinding, for tenor 28 days, represented in seconds
        uint256 timeAfterOpenAllowedToCloseSwapWithUnwindingTenor28days;
        /// @notice Time after open swap when it is allowed to close swap with unwinding, for tenor 60 days, represented in seconds
        uint256 timeAfterOpenAllowedToCloseSwapWithUnwindingTenor60days;
        /// @notice Time after open swap when it is allowed to close swap with unwinding, for tenor 90 days, represented in seconds
        uint256 timeAfterOpenAllowedToCloseSwapWithUnwindingTenor90days;
    }

    /// @notice Returns the configuration of the AmmCloseSwapService for a given pool (asset).
    /// @param asset asset address
    /// @return AmmCloseSwapServicePoolConfiguration struct representing the configuration of the AmmCloseSwapService for a given pool (asset).
    function getAmmCloseSwapServicePoolConfiguration(
        address asset
    ) external view returns (AmmCloseSwapServicePoolConfiguration memory);

    /// @notice Returns the closing swap details for a given swap and closing timestamp.
    /// @param asset asset address
    /// @param account account address for which are returned closing swap details, for example closableStatus depends on the account
    /// @param direction swap direction
    /// @param swapId swap id
    /// @param closeTimestamp closing timestamp
    /// @param riskIndicatorsInput risk indicators input
    /// @return closingSwapDetails struct representing the closing swap details for a given swap and closing timestamp.
    function getClosingSwapDetails(
        address asset,
        address account,
        AmmTypes.SwapDirection direction,
        uint256 swapId,
        uint256 closeTimestamp,
        AmmTypes.CloseSwapRiskIndicatorsInput calldata riskIndicatorsInput
    ) external view returns (AmmTypes.ClosingSwapDetails memory closingSwapDetails);
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;

/// @title Interface responsible for managing liquidity in the AMM Pools.
interface IAmmPoolsService {
    /// @notice A struct to represent a pool configuration in AmmPoolsService.
    struct AmmPoolsServicePoolConfiguration {
        /// @notice The address of the asset.
        address asset;
        /// @notice The number of decimals the asset uses.
        uint256 decimals;
        /// @notice The address of the ipToken associated with the asset.
        address ipToken;
        /// @notice The address of the AMM's storage contract.
        address ammStorage;
        /// @notice The address of the AMM's treasury contract.
        address ammTreasury;
        /// @notice The address of the asset management contract.
        address assetManagement;
        /// @notice Redeem fee rate, value represented in 18 decimals. 1e18 = 100%
        /// @dev Percentage of redeemed amount which stay in liquidity pool balance.
        uint256 redeemFeeRate;
        /// @notice Redeem liquidity pool max collateral ratio. Value describes what is maximal allowed collateral ratio for liquidity pool.
        /// @dev Collateral ratio is a proportion between liquidity pool balance and sum of all active swap collateral. Value represented in 18 decimals. 1e18 = 100%
        uint256 redeemLpMaxCollateralRatio;
    }

    /// @notice Emitted when `from` account provides liquidity (ERC20 token supported by IPOR Protocol) to AmmTreasury Liquidity Pool
    event ProvideLiquidity(
        /// @notice address that provides liquidity
        address indexed from,
        /// @notice Address that will receive ipTokens representing the provided liquidity.
        address indexed beneficiary,
        /// @notice AmmTreasury's address where liquidity is received
        address indexed to,
        /// @notice current ipToken exchange rate
        /// @dev value represented in 18 decimals
        uint256 exchangeRate,
        /// @notice amount of asset provided by user to AmmTreasury's liquidity pool
        /// @dev value represented in 18 decimals
        uint256 assetAmount,
        /// @notice amount of ipToken issued to represent user's share in the liquidity pool.
        /// @dev value represented in 18 decimals
        uint256 ipTokenAmount
    );

    /// @notice Emitted when `to` account executes redeem ipTokens
    event Redeem(
        /// @notice Address of the AMM Treasury contract
        address indexed ammTreasury,
        /// @notice AmmTreasury's address from which underlying asset - ERC20 Tokens, are transferred to `to` account
        address indexed from,
        /// @notice account where underlying asset tokens are transferred after redeem
        address indexed beneficiary,
        /// @notice ipToken exchange rate used for calculating `assetAmount`
        /// @dev value represented in 18 decimals
        uint256 exchangeRate,
        /// @notice underlying asset value calculated based on `exchangeRate` and `ipTokenAmount`
        /// @dev value represented in 18 decimals
        uint256 assetAmount,
        /// @notice redeemed IP Token value
        /// @dev value represented in 18 decimals
        uint256 ipTokenAmount,
        /// @notice underlying asset fee deducted when redeeming ipToken.
        /// @dev value represented in 18 decimals
        uint256 redeemFee,
        /// @notice net asset amount transferred from AmmTreasury to `to`/sender's account, reduced by the redeem fee
        /// @dev value represented in 18 decimals
        uint256 redeemAmount
    );

    /// @notice Gets the configuration of the pool for the given asset in AmmPoolsService.
    /// @param asset The address of the asset.
    /// @return The pool configuration.
    function getAmmPoolServiceConfiguration(
        address asset
    ) external view returns (AmmPoolsServicePoolConfiguration memory);

    /// @notice Providing USDT to the AMM Liquidity Pool by the sender on behalf of beneficiary.
    /// @dev Emits {ProvideLiquidity} event and transfers ERC20 tokens from the sender to the AmmTreasury,
    /// emits {Transfer} event from ERC20 asset, emits {Mint} event from ipToken.
    /// Transfers minted ipTokens to the beneficiary. Amount of transferred ipTokens is based on current ipToken exchange rate
    /// @param beneficiary Account receiving receive ipUSDT liquidity tokens.
    /// @param assetAmount Amount of ERC20 tokens transferred from the sender to the AmmTreasury. Represented in decimals specific for asset. Value represented in 18 decimals.
    function provideLiquidityUsdt(address beneficiary, uint256 assetAmount) external;

    /// @notice Providing USDC to the AMM Liquidity Pool by the sender on behalf of beneficiary.
    /// @dev Emits {ProvideLiquidity} event and transfers ERC20 tokens from the sender to the AmmTreasury,
    /// emits {Transfer} event from ERC20 asset, emits {Mint} event from ipToken.
    /// @param beneficiary Account receiving receive ipUSDT liquidity tokens.
    /// @param assetAmount Amount of ERC20 tokens transferred from the sender to the AmmTreasury. Represented in decimals specific for asset. Value represented in 18 decimals.
    function provideLiquidityUsdc(address beneficiary, uint256 assetAmount) external;

    /// @notice Providing DAI to the AMM Liquidity Pool by the sender on behalf of beneficiary.
    /// @dev Emits {ProvideLiquidity} event and transfers ERC20 tokens from the sender tothe AmmTreasury,
    /// emits {Transfer} event from ERC20 asset, emits {Mint} event from ipToken.
    /// @param beneficiary Account receiving receive ipUSDT liquidity tokens.
    /// @param assetAmount Amount of ERC20 tokens transferred from the sender to the AmmTreasury. Represented in decimals specific for asset. Value represented in 18 decimals.
    /// @dev Value represented in 18 decimals.
    function provideLiquidityDai(address beneficiary, uint256 assetAmount) external;

    /// @notice Redeems `ipTokenAmount` ipUSDT for underlying asset
    /// @dev Emits {Redeem} event, emits {Transfer} event from ERC20 asset, emits {Burn} event from ipToken.
    /// Transfers ERC20 tokens from the AmmTreasury to the beneficiary based on current exchange rate of ipUSDT.
    /// @param beneficiary Account receiving underlying tokens.
    /// @param ipTokenAmount redeem amount of ipUSDT tokens, represented in 18 decimals.
    /// @dev sender's ipUSDT tokens are burned, asset: USDT tokens are transferred to the beneficiary.
    function redeemFromAmmPoolUsdt(address beneficiary, uint256 ipTokenAmount) external;

    /// @notice Redeems `ipTokenAmount` ipUSDC for underlying asset
    /// @dev Emits {Redeem} event, emits {Transfer} event from ERC20 asset, emits {Burn} event from ipToken.
    /// Transfers ERC20 tokens from the AmmTreasury to the beneficiary based on current exchange rate of ipUSDC.
    /// @param beneficiary Account receiving underlying tokens.
    /// @param ipTokenAmount redeem amount of ipUSDC tokens, represented in 18 decimals.
    /// @dev sender's ipUSDC tokens are burned, asset: USDC tokens are transferred to the beneficiary.
    function redeemFromAmmPoolUsdc(address beneficiary, uint256 ipTokenAmount) external;

    /// @notice Redeems `ipTokenAmount` ipDAI for underlying asset
    /// @dev Emits {Redeem} event, emits {Transfer} event from ERC20 asset, emits {Burn} event from ipToken.
    /// Transfers ERC20 tokens from the AmmTreasury to the beneficiary based on current exchange rate of ipDAI.
    /// @param beneficiary Account receiving underlying tokens.
    /// @param ipTokenAmount redeem amount of ipDAI tokens, represented in 18 decimals.
    /// @dev sender's ipDAI tokens are burned, asset: DAI tokens are transferred to the beneficiary.
    function redeemFromAmmPoolDai(address beneficiary, uint256 ipTokenAmount) external;

    /// @notice Rebalances given assets between the AmmTreasury and the AssetManagement, based on configuration stored
    /// in the `AmmPoolsParamsValue.ammTreasuryAndAssetManagementRatio` field .
    /// @dev Emits {Deposit} or {Withdraw} event from AssetManagement depends on current asset balance on AmmTreasury and AssetManagement.
    /// @dev Emits {Transfer} from ERC20 asset.
    /// @param asset Address of the asset.
    function rebalanceBetweenAmmTreasuryAndAssetManagement(address asset) external;
}

// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.26;

/// @title Interface for interaction with PowerToken and LiquidityMining contracts.
interface IPowerTokenFlowsService {
    /// @notice Claims rewards for the caller by transferring them from the LiquidityMining contract to the PowerToken contract.
    /// @param lpTokens An array of LP tokens for which the rewards are to be claimed.
    /// @dev This function calls the `claim` function of the `ILiquidityMiningV2` contract to retrieve the rewards amount to transfer.
    /// It then adds the staked tokens to the `powerToken` contract and transfers the rewards from the `liquidityMining` contract to the `powerToken` contract.
    /// @dev Reverts if the `lpTokens` array is empty.
    /// @dev Reverts if there are no rewards to claim.
    function claimRewardsFromLiquidityMining(address[] calldata lpTokens) external;

    /// @notice Updates the indicators for a given account and LP tokens.
    /// @param account The account address for which the indicators are to be updated.
    /// @param lpTokens An array of LP tokens for which the indicators are to be updated.
    /// @dev This function calls the `updateIndicators` function of the `ILiquidityMiningV2` contract to update the indicators.
    /// @dev Reverts if the `lpTokens` array is empty.
    function updateIndicatorsInLiquidityMining(address account, address[] calldata lpTokens) external;

    /// @notice Delegates staked tokens by providing LP tokens and corresponding amounts.
    /// @param lpTokens An array of LP tokens to delegate.
    /// @param lpTokenAmounts An array of corresponding amounts of LP tokens to delegate.
    /// @dev This function allows the caller to delegate their staked tokens by providing the LP tokens and their corresponding amounts.
    /// @dev It requires that the length of `lpTokens` is equal to the length of `lpTokenAmounts`.
    /// @dev It reverts if either `lpTokens` or `lpTokenAmounts` arrays are empty.
    function delegatePwTokensToLiquidityMining(address[] calldata lpTokens, uint256[] calldata lpTokenAmounts) external;

    /// @notice Undelegates staked tokens by providing LP tokens and corresponding amounts.
    /// @param lpTokens An array of LP tokens to undelegate.
    /// @param lpTokenAmounts An array of corresponding amounts of LP tokens to undelegate.
    /// @dev This function allows the caller to undelegate their staked tokens by providing the LP tokens and their corresponding amounts.
    /// @dev It requires that the length of `lpTokens` is equal to the length of `lpTokenAmounts`.
    /// @dev It reverts if either `lpTokens` or `lpTokenAmounts` arrays are empty.
    /// @dev It reverts if the total staked token amount to undelegate is not greater than zero.
    function undelegatePwTokensFromLiquidityMining(
        address[] calldata lpTokens,
        uint256[] calldata lpTokenAmounts
    ) external;
}

// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.26;

/// @title Interface for interaction with PowerToken and LiquidityMining contracts.
interface IPowerTokenStakeService {
    /// @notice Stakes the specified amounts of LP tokens into the LiquidityMining contract.
    /// @dev This function allows the caller to stake their LP tokens on behalf of another address (`beneficiary`).
    /// @param beneficiary The address on behalf of which the LP tokens are being staked.
    /// @param lpTokens An array of LP token addresses to be staked.
    /// @param lpTokenAmounts An array of corresponding LP token amounts to be staked, represented with 18 decimals.
    /// @dev Both `lpTokens` and `lpTokenAmounts` arrays must have the same length.
    /// @dev The `beneficiary` address must not be the zero address.
    /// @dev The function ensures that the provided LP token addresses are valid and the amounts to be staked are greater than zero.
    /// @dev The function transfers the LP tokens from the caller's address to the LiquidityMining contract.
    /// @dev Finally, the function calls the `addLpTokens` function of the LiquidityMining contract to update the staked LP tokens.
    /// @dev Reverts if any of the requirements is not met or if the transfer of LP tokens fails.
    function stakeLpTokensToLiquidityMining(
        address beneficiary,
        address[] calldata lpTokens,
        uint256[] calldata lpTokenAmounts
    ) external;

    /// @notice Unstakes the specified amounts of LP tokens from the LiquidityMining contract and transfers them to the specified address.
    /// @param transferTo The address to which the unstaked LP tokens will be transferred.
    /// @param lpTokens An array of LP token addresses to be unstaked.
    /// @param lpTokenAmounts An array of corresponding LP token amounts to be unstaked, represented with 18 decimals.
    /// @dev Both `lpTokens` and `lpTokenAmounts` arrays must have the same length.
    /// @dev The function ensures that the provided LP token addresses are valid and the amounts to be unstaked are greater than zero.
    /// @dev The function calls the `removeLpTokens` function of the LiquidityMining contract to update the unstaked LP tokens.
    /// @dev Finally, the function transfers the unstaked LP tokens from the LiquidityMining contract to the specified address.
    /// @dev Reverts if any of the requirements is not met or if the transfer of LP tokens fails.
    function unstakeLpTokensFromLiquidityMining(
        address transferTo,
        address[] calldata lpTokens,
        uint256[] calldata lpTokenAmounts
    ) external;

    /// @notice Stakes the specified amount of IPOR tokens on behalf of the specified address.
    /// @param beneficiary The address on whose behalf the IPOR tokens will be staked.
    /// @param iporTokenAmount The amount of IPOR tokens to be staked, represented with 18 decimals.
    /// @dev The function ensures that the provided `beneficiary` address is valid and the `iporTokenAmount` is greater than zero.
    /// @dev The function calls the `addStakedToken` function of the PowerToken contract to update the staked IPOR tokens.
    /// @dev Finally, the function transfers the IPOR tokens from the sender to the PowerToken contract for staking.
    /// @dev Reverts if any of the requirements is not met or if the transfer of IPOR tokens fails.
    function stakeGovernanceTokenToPowerToken(address beneficiary, uint256 iporTokenAmount) external;

    /// @notice Stakes a specified amount of governance tokens and delegates power tokens to a specific beneficiary.
    /// @param beneficiary The address on whose behalf the governance tokens will be staked and power tokens will be delegated.
    /// @param governanceTokenAmount The amount of governance tokens to be staked, represented with 18 decimals.
    /// @param lpTokens An array of addresses representing the liquidity pool tokens.
    /// @param pwTokenAmounts An array of amounts of power tokens to be delegated corresponding to each liquidity pool token.
    /// @dev The function ensures that the `beneficiary` address is valid and the `governanceTokenAmount` is greater than zero.
    /// @dev The function also requires that the length of the `lpTokens` array is equal to the length of the `pwTokenAmounts` array.
    /// @dev For each liquidity pool token in `lpTokens`, the function creates an `UpdatePwToken` structure to be used for updating the power tokens in the Liquidity Mining contract.
    /// @dev The function checks if the total amount of power tokens to be delegated is less or equal to the amount of staked governance tokens.
    /// @dev The function calls the `addGovernanceTokenInternal` function of the PowerToken contract to update the staked governance tokens for the `beneficiary`.
    /// @dev The function transfers the governance tokens from the sender to the PowerToken contract for staking.
    /// @dev The function calls the `delegateInternal` function of the PowerToken contract to delegate power tokens to the `beneficiary`.
    /// @dev Finally, the function calls the `addPwTokensInternal` function of the Liquidity Mining contract to update the staked power tokens.
    /// @dev Reverts if any of the requirements is not met or if the transfer of governance tokens fails.
    function stakeGovernanceTokenToPowerTokenAndDelegate(
        address beneficiary,
        uint256 governanceTokenAmount,
        address[] calldata lpTokens,
        uint256[] calldata pwTokenAmounts
    ) external;

    /// @notice Unstakes the specified amount of IPOR tokens and transfers them to the specified address.
    /// @param transferTo The address to which the unstaked IPOR tokens will be transferred.
    /// @param iporTokenAmount The amount of IPOR tokens to be unstaked, represented with 18 decimals.
    /// @dev The function ensures that the `iporTokenAmount` is greater than zero.
    /// @dev The function calls the `removeStakedTokenWithFee` function of the PowerToken contract to remove the staked IPOR tokens.
    /// @dev Finally, the function transfers the corresponding staked token amount to the `transferTo` address.
    /// @dev Reverts if the `iporTokenAmount` is not greater than zero, or if the transfer of staked tokens fails.
    function unstakeGovernanceTokenFromPowerToken(address transferTo, uint256 iporTokenAmount) external;

    /// @notice Initiates a cooldown period for the specified amount of Power Tokens.
    /// @param pwTokenAmount The amount of Power Tokens to be put into cooldown, represented with 18 decimals.
    /// @dev The function ensures that the `pwTokenAmount` is greater than zero.
    /// @dev The function calls the `cooldown` function of the PowerToken contract to initiate the cooldown.
    /// @dev Reverts if the `pwTokenAmount` is not greater than zero.
    function pwTokenCooldown(uint256 pwTokenAmount) external;

    /// @notice Cancels the active cooldown for the sender.
    /// @dev The function calls the `cancelCooldown` function of the PowerToken contract to cancel the cooldown.
    function pwTokenCancelCooldown() external;

    /// @notice Redeems Power Tokens and transfers the corresponding Staked Tokens to the specified address.
    /// @dev The function calls the `redeem` function of the PowerToken contract to redeem Power Tokens.
    /// @param transferTo The address to which the Staked Tokens will be transferred.
    function redeemPwToken(address transferTo) external;
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;

/// @title Interface of the AmmPoolsServiceEth contract.
interface IAmmPoolsServiceStEth {
    /// @notice Allows the router to provide liquidity in the form of stEth to the AMM pool.
    /// @param beneficiary Address that will receive the minted ipstEth tokens in exchange for the provided stEth.
    /// @param stEthAmount Amount of stEth tokens to be provided as liquidity. Represented in 18 decimals.
    /// @dev This function can only be called by the router. It calculates the new pool balance, checks if it's within the allowed limit,
    /// calculates the exchange rate, transfers the stEth from the sender to the AmmTreasury contract, and mints ipstEth tokens to the beneficiary.
    /// An event IAmmPoolsServiceStEth.ProvideLiquidityStEth is emitted after the liquidity is provided.
    /// require the new pool balance after adding the provided stEth should not exceed the maximum allowed pool balance.
    function provideLiquidityStEth(address beneficiary, uint256 stEthAmount) external payable;

    /// @notice Allows the router to provide liquidity in the form of wEth to the AMM pool.
    /// @param beneficiary Address that will benefit from the provided liquidity.
    /// @param assetAmount Amount of wEth tokens to be provided as liquidity. Represented in 18 decimals.
    /// @dev This function can only be called by the router. It checks the validity of the provided wEth amount and beneficiary address,
    /// calculates the new pool balance, checks if it's within the allowed limit.
    /// @dev Flow is following: Transfers the wEth from the sender to Router contract, Router withdraws the wEth to convert it to Ether,
    /// Router submit  the Ether to stETH contract and transfer stETH to AmmTreasury contract, mints ipstETH to the beneficiary.
    /// An event IAmmPoolsServiceStEth.ProvideLiquidityEth is emitted after the liquidity is provided.
    /// require The provided wEth amount should be greater than zero.
    /// require The beneficiary address should not be the zero address.
    /// require The new pool balance after adding the provided wEth should not exceed the maximum allowed pool balance.
    function provideLiquidityWEth(address beneficiary, uint256 assetAmount) external payable;

    /// @notice Allows the router to provide liquidity in the form of Ether to the AMM pool.
    /// @param beneficiary Address that will benefit from the provided liquidity.
    /// @param assetAmount Amount of Ether to be provided as liquidity. Represented in 18 decimals.
    /// @dev This function can only be called by the router. It checks the validity of the provided Ether amount, the sent Ether value,
    /// and the beneficiary address, calculates the new pool balance, and checks if it's within the allowed limit.
    /// @dev Flow is following: User transfer to Router ETH, Router submit ETH to stETH contract and transfer stETH to AmmTreasury contract,
    /// Router mints ipstETH to the beneficiary.
    /// An event IAmmPoolsServiceStEth.ProvideLiquidityEth is emitted after the liquidity is provided.
    /// require The provided Ether amount should be greater than zero.
    /// require The sent Ether value with the transaction should be greater than zero.
    /// require The beneficiary address should not be the zero address.
    /// require The new pool balance after adding the provided Ether should not exceed the maximum allowed pool balance.
    function provideLiquidityEth(address beneficiary, uint256 assetAmount) external payable;

    /// @notice Allows the router to redeem stEth from the AMM pool in exchange for ipstEth tokens.
    /// @param beneficiary Address that will receive the redeemed stEth.
    /// @param ipTokenAmount Amount of ipstEth tokens to be redeemed. Represented in 18 decimals.
    /// @dev This function can only be called by the router. It checks the validity of the provided ipstEth amount and beneficiary address,
    /// calculates the exchange rate, determines the amount of stEth equivalent to the provided ipstEth, and transfers the stEth to the beneficiary.
    /// The function also accounts for a redemption fee. An event is emitted after the redemption.
    /// require The provided ipstEth amount should be greater than zero and less than or equal to the sender's balance.
    /// require The beneficiary address should not be the zero address.
    /// require The calculated stEth amount to redeem after accounting for the fee should be greater than zero.
    function redeemFromAmmPoolStEth(address beneficiary, uint256 ipTokenAmount) external;

    /// @notice Rebalances stETH assets between the AmmTreasury and the AssetManagement, based on configuration stored
    /// in the `AmmPoolsParamsValue.ammTreasuryAndAssetManagementRatio` field.
    /// @dev Emits {Deposit} or {Withdraw} event from AssetManagement depends on current asset balance on AmmTreasury and AssetManagement.
    /// @dev Emits {Transfer} from ERC20 asset.
    function rebalanceBetweenAmmTreasuryAndAssetManagementStEth() external;

    /// @notice Error appeared when submitted ETH amount to in stETH contract is too high.
    /// @param amount Amount of ETH which was submitted to stETH contract.
    /// @param errorCode IPOR Protocol error code.
    error StEthSubmitFailed(uint256 amount, string errorCode);

    /// @notice Event emitted when liquidity is provided in the form of stEth.
    /// @param from Address of the sender.
    /// @param beneficiary Address that will receive the minted ipstEth tokens in exchange for the provided stEth.
    /// @param to Address of the AMM treasury.
    /// @param exchangeRate Exchange rate between stEth and ipstEth.
    /// @param assetAmount Amount of stEth tokens provided as liquidity.
    /// @param ipTokenAmount Amount of ipstEth tokens minted in exchange for the provided stEth.
    event ProvideLiquidityStEth(
        address indexed from,
        address indexed beneficiary,
        address indexed to,
        uint256 exchangeRate,
        uint256 assetAmount,
        uint256 ipTokenAmount
    );

    /// @notice Event emitted when liquidity is provided in the form of wEth or ETH.
    /// @param from Address of the sender.
    /// @param beneficiary Address that will benefit from the provided liquidity.
    /// @param to Address of the AMM treasury.
    /// @param exchangeRate Exchange rate between wEth and ipstEth.
    /// @param amountEth Amount of ETH provided as liquidity.
    /// @param amountStEth Amount of stEth tokens submitted to StETH contract based on amountEth
    /// @param ipTokenAmount Amount of ipstEth tokens minted in exchange for the provided stEth.
    event ProvideLiquidityEth(
        address indexed from,
        address indexed beneficiary,
        address indexed to,
        uint256 exchangeRate,
        uint256 amountEth,
        uint256 amountStEth,
        uint256 ipTokenAmount
    );

    /// @notice Event emitted when liquidity is redeemed from the AMM pool in exchange for stEth.
    /// @param ammTreasuryEth Address of the AMM Treasury stETH contract.
    /// @param from Address of the sender. From who ipstEth tokens were burned.
    /// @param beneficiary Address that will receive the redeemed stEth tokens.
    /// @param exchangeRate Exchange rate between stEth and ipstEth.
    /// @param amountStEth Amount of stEth tokens redeemed.
    /// @param redeemedAmountStEth Amount of stEth tokens redeemed after accounting for the fee.
    /// @param ipTokenAmount Amount of ipstEth tokens redeemed.
    event RedeemStEth(
        address indexed ammTreasuryEth,
        address indexed from,
        address indexed beneficiary,
        uint256 exchangeRate,
        uint256 amountStEth,
        uint256 redeemedAmountStEth,
        uint256 ipTokenAmount
    );
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;

/// @title Interface of the AmmPoolsServiceWeEth contract.
interface IAmmPoolsServiceWeEth {
    function provideLiquidityWeEthToAmmPoolWeEth(address beneficiary, uint256 weEthAmount) external;

    function provideLiquidity(
        address poolAsset,
        address inputAsset,
        address beneficiary,
        uint256 inputAssetAmount
    ) external payable returns (uint256 ipTokenAmount);

    function redeemFromAmmPoolWeEth(address beneficiary, uint256 ipTokenAmount) external;

    function rebalanceBetweenAmmTreasuryAndAssetManagementWeEth() external;

    error ProvideLiquidityFailed(address poolAsset, string errorCode, string errorMessage);
}

File 22 of 43 : IporErrors.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;

library IporErrors {
    /// @notice Error when address is wrong
    error WrongAddress(string errorCode, address wrongAddress, string message);

    /// @notice Error when amount is wrong
    error WrongAmount(string errorCode, uint256 value);

    /// @notice Error when caller is not an ipor protocol router
    error CallerNotIporProtocolRouter(string errorCode, address caller);

    /// @notice Error when caller is not a pause guardian
    error CallerNotPauseGuardian(string errorCode, address caller);

    /// @notice Error when given direction is not supported
    error UnsupportedDirection(string errorCode, uint256 direction);

    /// @notice Error when given asset is not supported
    error UnsupportedAsset(string errorCode, address asset);

    /// @notice Error when given asset is not supported
    error UnsupportedAssetPair(string errorCode, address poolAsset, address inputAsset);

    /// @notice Error when given module is not supported
    error UnsupportedModule(string errorCode, address asset);

    /// @notice Error when given tenor is not supported
    error UnsupportedTenor(string errorCode, uint256 tenor);

    /// @notice Error when Input Asset total amount is too low
    error InputAssetTotalAmountTooLow(string errorCode, uint256 value);

    /// @dev Error appears if user/account doesn't have enough balance to open a swap with a specific totalAmount
    error InputAssetBalanceTooLow(string errorCode, address inputAsset, uint256 inputAssetBalance, uint256 totalAmount);

    error AssetMismatch(address assetOne, address assetTwo);

    // 000-199 - general codes

    /// @notice General problem, address is wrong
    string public constant WRONG_ADDRESS = "IPOR_000";

    /// @notice General problem. Wrong decimals
    string public constant WRONG_DECIMALS = "IPOR_001";

    /// @notice General problem, addresses mismatch
    string public constant ADDRESSES_MISMATCH = "IPOR_002";

    /// @notice Sender's asset balance is too low to transfer and to open a swap
    string public constant SENDER_ASSET_BALANCE_TOO_LOW = "IPOR_003";

    /// @notice Value is not greater than zero
    string public constant VALUE_NOT_GREATER_THAN_ZERO = "IPOR_004";

    /// @notice Input arrays length mismatch
    string public constant INPUT_ARRAYS_LENGTH_MISMATCH = "IPOR_005";

    /// @notice Amount is too low to transfer
    string public constant NOT_ENOUGH_AMOUNT_TO_TRANSFER = "IPOR_006";

    /// @notice msg.sender is not an appointed owner, so cannot confirm his appointment to be an owner of a specific smart contract
    string public constant SENDER_NOT_APPOINTED_OWNER = "IPOR_007";

    /// @notice only Router can have access to function
    string public constant CALLER_NOT_IPOR_PROTOCOL_ROUTER = "IPOR_008";

    /// @notice Chunk size is equal to zero
    string public constant CHUNK_SIZE_EQUAL_ZERO = "IPOR_009";

    /// @notice Chunk size is too big
    string public constant CHUNK_SIZE_TOO_BIG = "IPOR_010";

    /// @notice Caller is not a pause guardian
    string public constant CALLER_NOT_PAUSE_GUARDIAN = "IPOR_011";

    /// @notice Request contains invalid method signature, which is not supported by the Ipor Protocol Router
    string public constant ROUTER_INVALID_SIGNATURE = "IPOR_012";

    /// @notice Only AMM Treasury can have access to function
    string public constant CALLER_NOT_AMM_TREASURY = "IPOR_013";

    /// @notice Caller is not an owner
    string public constant CALLER_NOT_OWNER = "IPOR_014";

    /// @notice Method is paused
    string public constant METHOD_PAUSED = "IPOR_015";

    /// @notice Reentrancy appears
    string public constant REENTRANCY = "IPOR_016";

    /// @notice Asset is not supported
    string public constant ASSET_NOT_SUPPORTED = "IPOR_017";

    /// @notice Return back ETH failed in Ipor Protocol Router
    string public constant ROUTER_RETURN_BACK_ETH_FAILED = "IPOR_018";

    /// @notice Risk indicators are expired
    string public constant RISK_INDICATORS_EXPIRED = "IPOR_019";

    /// @notice Signature is invalid for risk indicators
    string public constant RISK_INDICATORS_SIGNATURE_INVALID = "IPOR_020";

    /// @notice Input Asset used by user is not supported
    string public constant INPUT_ASSET_NOT_SUPPORTED = "IPOR_021";

    /// @notice Module Asset Management is not supported
    string public constant UNSUPPORTED_MODULE_ASSET_MANAGEMENT = "IPOR_022";
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;

import "./errors/IporErrors.sol";

library IporContractValidator {
    function checkAddress(address addr) internal pure returns (address) {
        require(addr != address(0), IporErrors.WRONG_ADDRESS);
        return addr;
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;

import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {IProxyImplementation} from "../interfaces/IProxyImplementation.sol";
import {IporErrors} from "../libraries/errors/IporErrors.sol";
import {AccessControl} from "./AccessControl.sol";
import {StorageLibBaseV1} from "../base/libraries/StorageLibBaseV1.sol";
import {OwnerManager} from "../security/OwnerManager.sol";
import {StorageSlotUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol";

/// @title Entry point for IPOR protocol
abstract contract IporProtocolRouterAbstract is UUPSUpgradeable, AccessControl, IProxyImplementation {
    using Address for address;

    uint256 private constant SINGLE_OPERATION = 0;
    uint256 private constant BATCH_OPERATION = 1;

    fallback(bytes calldata input) external payable returns (bytes memory) {
        return _delegate(_getRouterImplementation(msg.sig, SINGLE_OPERATION));
    }

    function initialize(bool pausedInput) external initializer {
        __UUPSUpgradeable_init();
        OwnerManager.transferOwnership(msg.sender);
        StorageLibBaseV1.getReentrancyStatus().value = _NOT_ENTERED;
    }

    /// @notice Gets the implementation of the router
    /// @return implementation address
    function getImplementation() external view override returns (address) {
        return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;
    }

    /// @notice Allows to execute batch of calls in one transaction using IPOR protocol business methods
    /// @param calls array of encoded calls
    function batchExecutor(bytes[] calldata calls) external payable nonReentrant returns (bytes[] memory) {
        uint256 length = calls.length;
        address implementation;
        bytes[] memory returnData = new bytes[](length);

        for (uint256 i; i != length; ) {
            implementation = _getRouterImplementation(bytes4(calls[i][:4]), BATCH_OPERATION);
            returnData[i] = implementation.functionDelegateCall(calls[i]);
            unchecked {
                ++i;
            }
        }

        _returnBackRemainingEth();

        return returnData;
    }

    receive() external payable {}

    function _getRouterImplementation(bytes4 sig, uint256 batchOperation) internal virtual returns (address);

    function _delegate(address implementation) private returns (bytes memory) {
        bytes memory returnData = implementation.functionDelegateCall(msg.data);
        _returnBackRemainingEth();
        _nonReentrantAfter();
        return returnData;
    }

    function _returnBackRemainingEth() private {
        uint256 routerEthBalance = address(this).balance;

        if (routerEthBalance > 0) {
            /// @dev if view method then return back ETH is skipped
            if (StorageLibBaseV1.getReentrancyStatus().value == _ENTERED) {
                (bool success, ) = msg.sender.call{value: routerEthBalance}("");

                if (!success) {
                    revert(IporErrors.ROUTER_RETURN_BACK_ETH_FAILED);
                }
            }
        }
    }

    //solhint-disable no-empty-blocks
    function _authorizeUpgrade(address) internal view override onlyOwner {}
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;

/// @title Interface of the AmmPoolsServiceUsdm contract.
interface IAmmPoolsServiceUsdm {
    function provideLiquidityUsdmToAmmPoolUsdm(address beneficiary, uint256 usdmAmount) external payable;

    function redeemFromAmmPoolUsdm(address beneficiary, uint256 ipTokenAmount) external;
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;

import {StorageLibBaseV1} from "../libraries/StorageLibBaseV1.sol";

interface IAmmGovernanceServiceBaseV1 {
    function setMessageSigner(address messageSigner) external;

    function setAssetLensData(address asset, StorageLibBaseV1.AssetLensDataValue memory assetLensData) external;

    function setAssetServices(address asset, StorageLibBaseV1.AssetServicesValue memory assetServices) external;

    function setAmmGovernancePoolConfiguration(
        address asset,
        StorageLibBaseV1.AssetGovernancePoolConfigValue calldata assetGovernancePoolConfig
    ) external;
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;

/// @title Storage ID's associated with the IPOR Protocol Router.
library StorageLibBaseV1 {
    uint256 constant STORAGE_SLOT_BASE = 1_000_000;

    // append only
    enum StorageId {
        /// @dev The address of the contract owner.
        Owner,
        AppointedOwner,
        Paused,
        PauseGuardian,
        ReentrancyStatus,
        RouterFunctionPaused,
        AmmSwapsLiquidators,
        AmmPoolsAppointedToRebalance,
        AmmPoolsParams,
        MessageSigner, /// @dev The address of the IPOR Message Signer.
        AssetLensData, /// @dev Mapping of asset address to asset lens data.
        AssetGovernancePoolConfig, /// @dev Mapping of asset address to asset governance data.
        AssetServices /// @dev Mapping of asset address to set of services per pool.
    }

    /// @notice Struct for one asset which contains services for a specific asset pool.
    struct AssetServicesValue {
        address ammPoolsService;
        address ammOpenSwapService;
        address ammCloseSwapService;
    }

    /// @notice Struct which contains services for a specific asset pool.
    struct AssetServicesStorage {
        mapping(address asset => AssetServicesValue) value;
    }

    /// @notice Struct for one asset combining all data required for lens services related to a specific asset pool.
    struct AssetLensDataValue {
        uint8 decimals;
        address ipToken;
        address ammStorage;
        address ammTreasury;
        address ammVault;
        address spread;
    }

    /// @notice Struct combining all data required for lens services related to a specific asset pool.
    struct AssetLensDataStorage {
        mapping(address asset => AssetLensDataValue) value;
    }

    /// @notice Struct which contains governance configuration for a specific asset pool.
    struct AssetGovernancePoolConfigValue {
        uint8 decimals;
        address ammStorage;
        address ammTreasury;
        address ammVault;
        address ammPoolsTreasury;
        address ammPoolsTreasuryManager;
        address ammCharlieTreasury;
        address ammCharlieTreasuryManager;
    }

    /// @notice Struct which contains governance configuration for a specific asset pool.
    struct AssetGovernancePoolConfigStorage {
        mapping(address asset => AssetGovernancePoolConfigValue) value;
    }

    struct MessageSignerStorage {
        address value;
    }

    /// @notice Struct which contains owner address of IPOR Protocol Router.
    struct OwnerStorage {
        address owner;
    }

    /// @notice Struct which contains appointed owner address of IPOR Protocol Router.
    struct AppointedOwnerStorage {
        address appointedOwner;
    }

    /// @notice Struct which contains reentrancy status of IPOR Protocol Router.
    struct ReentrancyStatusStorage {
        uint256 value;
    }

    /// @notice Struct which contains information about swap liquidators.
    /// @dev First key is an asset (pool), second key is an liquidator address in the asset pool,
    /// value is a flag to indicate whether account is a liquidator.
    /// True - account is a liquidator, False - account is not a liquidator.
    struct AmmSwapsLiquidatorsStorage {
        mapping(address asset => mapping(address account => bool isLiquidator)) value;
    }

    /// @notice Struct which contains information about accounts appointed to rebalance.
    /// @dev first key - asset address, second key - account address which is allowed to rebalance in the asset pool,
    /// value - flag to indicate whether account is allowed to rebalance. True - allowed, False - not allowed.
    struct AmmPoolsAppointedToRebalanceStorage {
        mapping(address asset => mapping(address account => bool isAppointedToRebalance)) value;
    }

    struct AmmPoolsParamsValue {
        /// @dev max liquidity pool balance in the asset pool, represented without 18 decimals
        uint32 maxLiquidityPoolBalance;
        /// @dev The threshold for auto-rebalancing the pool. Value represented without 18 decimals.
        uint32 autoRebalanceThreshold;
        /// @dev asset management ratio, represented without 18 decimals, value represents percentage with 2 decimals
        /// 65% = 6500, 99,99% = 9999, this is a percentage which stay in Amm Treasury in opposite to Asset Management
        /// based on AMM Treasury balance (100%).
        uint16 ammTreasuryAndAssetManagementRatio;
    }

    /// @dev key - asset address, value - struct AmmOpenSwapParamsValue
    struct AmmPoolsParamsStorage {
        mapping(address asset => AmmPoolsParamsValue) value;
    }

    /// @dev key - function sig, value - 1 if function is paused, 0 if not
    struct RouterFunctionPausedStorage {
        mapping(bytes4 sig => uint256 isPaused) value;
    }

    /// @notice Gets Ipor Protocol Router owner address.
    function getOwner() internal pure returns (OwnerStorage storage owner) {
        uint256 slot = _getStorageSlot(StorageId.Owner);
        assembly {
            owner.slot := slot
        }
    }

    /// @notice Gets Ipor Protocol Router appointed owner address.
    function getAppointedOwner() internal pure returns (AppointedOwnerStorage storage appointedOwner) {
        uint256 slot = _getStorageSlot(StorageId.AppointedOwner);
        assembly {
            appointedOwner.slot := slot
        }
    }

    /// @notice Gets Ipor Protocol Router reentrancy status.
    function getReentrancyStatus() internal pure returns (ReentrancyStatusStorage storage reentrancyStatus) {
        uint256 slot = _getStorageSlot(StorageId.ReentrancyStatus);
        assembly {
            reentrancyStatus.slot := slot
        }
    }

    /// @notice Gets information if function is paused in Ipor Protocol Router.
    function getRouterFunctionPaused() internal pure returns (RouterFunctionPausedStorage storage paused) {
        uint256 slot = _getStorageSlot(StorageId.RouterFunctionPaused);
        assembly {
            paused.slot := slot
        }
    }

    /// @notice Gets point to pause guardian storage.
    function getPauseGuardianStorage() internal pure returns (mapping(address => bool) storage store) {
        uint256 slot = _getStorageSlot(StorageId.PauseGuardian);
        assembly {
            store.slot := slot
        }
    }

    /// @notice Gets point to liquidators storage.
    /// @return store - point to liquidators storage.
    function getAmmSwapsLiquidatorsStorage() internal pure returns (AmmSwapsLiquidatorsStorage storage store) {
        uint256 slot = _getStorageSlot(StorageId.AmmSwapsLiquidators);
        assembly {
            store.slot := slot
        }
    }

    /// @notice Gets point to accounts appointed to rebalance storage.
    /// @return store - point to accounts appointed to rebalance storage.
    function getAmmPoolsAppointedToRebalanceStorage()
        internal
        pure
        returns (AmmPoolsAppointedToRebalanceStorage storage store)
    {
        uint256 slot = _getStorageSlot(StorageId.AmmPoolsAppointedToRebalance);
        assembly {
            store.slot := slot
        }
    }

    /// @notice Gets point to amm pools params storage.
    /// @return store - point to amm pools params storage.
    function getAmmPoolsParamsStorage() internal pure returns (AmmPoolsParamsStorage storage store) {
        uint256 slot = _getStorageSlot(StorageId.AmmPoolsParams);
        assembly {
            store.slot := slot
        }
    }

    function getMessageSignerStorage() internal pure returns (MessageSignerStorage storage store) {
        uint256 slot = _getStorageSlot(StorageId.MessageSigner);
        assembly {
            store.slot := slot
        }
    }

    function getAssetLensDataStorage() internal pure returns (AssetLensDataStorage storage store) {
        uint256 slot = _getStorageSlot(StorageId.AssetLensData);
        assembly {
            store.slot := slot
        }
    }

    function getAssetGovernancePoolConfigStorage()
        internal
        pure
        returns (AssetGovernancePoolConfigStorage storage store)
    {
        uint256 slot = _getStorageSlot(StorageId.AssetGovernancePoolConfig);
        assembly {
            store.slot := slot
        }
    }

    function getAssetServicesStorage() internal pure returns (AssetServicesStorage storage store) {
        uint256 slot = _getStorageSlot(StorageId.AssetServices);
        assembly {
            store.slot := slot
        }
    }

    function _getStorageSlot(StorageId storageId) private pure returns (uint256 slot) {
        return uint256(storageId) + STORAGE_SLOT_BASE;
    }
}

File 28 of 43 : IporTypes.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;

/// @title Struct used across various interfaces in IPOR Protocol.
library IporTypes {
    /// @notice enum describing Swap's state, ACTIVE - when the swap is opened, INACTIVE when it's closed
    enum SwapState {
        INACTIVE,
        ACTIVE
    }

    /// @notice enum describing Swap's duration, 28 days, 60 days or 90 days
    enum SwapTenor {
        DAYS_28,
        DAYS_60,
        DAYS_90
    }

    /// @notice The struct describing the IPOR and its params calculated for the time when it was most recently updated and the change that took place since the update.
    /// Namely, the interest that would be computed into IBT should the rebalance occur.
    struct AccruedIpor {
        /// @notice IPOR Index Value
        /// @dev value represented in 18 decimals
        uint256 indexValue;
        /// @notice IBT Price (IBT - Interest Bearing Token). For more information refer to the documentation:
        /// https://ipor-labs.gitbook.io/ipor-labs/interest-rate-derivatives/ibt
        /// @dev value represented in 18 decimals
        uint256 ibtPrice;
    }

    /// @notice Struct representing balances used internally for asset calculations
    /// @dev all balances in 18 decimals
    struct AmmBalancesMemory {
        /// @notice Sum of all collateral put forward by the derivative buyer's on  Pay Fixed & Receive Floating leg.
        uint256 totalCollateralPayFixed;
        /// @notice Sum of all collateral put forward by the derivative buyer's on  Pay Floating & Receive Fixed leg.
        uint256 totalCollateralReceiveFixed;
        /// @notice Liquidity Pool Balance. This balance is where the liquidity from liquidity providers and the opening fee are accounted for,
        /// @dev Amount of opening fee accounted in this balance is defined by _OPENING_FEE_FOR_TREASURY_PORTION_RATE param.
        uint256 liquidityPool;
        /// @notice Vault's balance, describes how much asset has been transferred to Asset Management Vault (AssetManagement)
        uint256 vault;
    }

    struct AmmBalancesForOpenSwapMemory {
        /// @notice Sum of all collateral put forward by the derivative buyer's on  Pay Fixed & Receive Floating leg.
        uint256 totalCollateralPayFixed;
        /// @notice Total notional amount of all swaps on  Pay Fixed leg (denominated in 18 decimals).
        uint256 totalNotionalPayFixed;
        /// @notice Sum of all collateral put forward by the derivative buyer's on  Pay Floating & Receive Fixed leg.
        uint256 totalCollateralReceiveFixed;
        /// @notice Total notional amount of all swaps on  Receive Fixed leg (denominated in 18 decimals).
        uint256 totalNotionalReceiveFixed;
        /// @notice Liquidity Pool Balance.
        uint256 liquidityPool;
    }

    struct SpreadInputs {
        //// @notice Swap's assets DAI/USDC/USDT
        address asset;
        /// @notice Swap's notional value
        uint256 swapNotional;
        /// @notice demand spread factor used in demand spread calculation
        uint256 demandSpreadFactor;
        /// @notice Base spread
        int256 baseSpreadPerLeg;
        /// @notice Swap's balance for Pay Fixed leg
        uint256 totalCollateralPayFixed;
        /// @notice Swap's balance for Receive Fixed leg
        uint256 totalCollateralReceiveFixed;
        /// @notice Liquidity Pool's Balance
        uint256 liquidityPoolBalance;
        /// @notice Ipor index value at the time of swap creation
        uint256 iporIndexValue;
        // @notice fixed rate cap for given leg for offered rate without demandSpread in 18 decimals
        uint256 fixedRateCapPerLeg;
    }
}

File 29 of 43 : AmmTypes.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;
import "./IporTypes.sol";
import "../IAmmCloseSwapLens.sol";

/// @title Types used in interfaces strictly related to AMM (Automated Market Maker).
/// @dev Used by IAmmTreasury and IAmmStorage interfaces.
library AmmTypes {
    /// @notice Struct describing AMM Pool's core addresses.
    struct AmmPoolCoreModel {
        /// @notice asset address
        address asset;
        /// @notice asset decimals
        uint256 assetDecimals;
        /// @notice ipToken address associated to the asset
        address ipToken;
        /// @notice AMM Storage address
        address ammStorage;
        /// @notice AMM Treasury address
        address ammTreasury;
        /// @notice Asset Management address
        address assetManagement;
        /// @notice IPOR Oracle address
        address iporOracle;
    }

    /// @notice Structure which represents Swap's data that will be saved in the storage.
    /// Refer to the documentation https://ipor-labs.gitbook.io/ipor-labs/automated-market-maker/ipor-swaps for more information.
    struct NewSwap {
        /// @notice Account / trader who opens the Swap
        address buyer;
        /// @notice Epoch timestamp of when position was opened by the trader.
        uint256 openTimestamp;
        /// @notice Swap's collateral amount.
        /// @dev value represented in 18 decimals
        uint256 collateral;
        /// @notice Swap's notional amount.
        /// @dev value represented in 18 decimals
        uint256 notional;
        /// @notice Quantity of Interest Bearing Token (IBT) at moment when position was opened.
        /// @dev value represented in 18 decimals
        uint256 ibtQuantity;
        /// @notice Fixed interest rate at which the position has been opened.
        /// @dev value represented in 18 decimals
        uint256 fixedInterestRate;
        /// @notice Liquidation deposit is retained when the swap is opened. It is then paid back to agent who closes the derivative at maturity.
        /// It can be both trader or community member. Trader receives the deposit back when he chooses to close the derivative before maturity.
        /// @dev value represented WITHOUT 18 decimals for USDT, USDC, DAI pool. Notice! Value represented in 6 decimals for stETH pool.
        /// @dev Example value in 6 decimals: 25000000 (in 6 decimals) = 25 stETH = 25.000000
        uint256 liquidationDepositAmount;
        /// @notice Opening fee amount part which is allocated in Liquidity Pool Balance. This fee is calculated as a rate of the swap's collateral.
        /// @dev value represented in 18 decimals
        uint256 openingFeeLPAmount;
        /// @notice Opening fee amount part which is allocated in Treasury Balance. This fee is calculated as a rate of the swap's collateral.
        /// @dev value represented in 18 decimals
        uint256 openingFeeTreasuryAmount;
        /// @notice Swap's tenor, 0 - 28 days, 1 - 60 days or 2 - 90 days
        IporTypes.SwapTenor tenor;
    }

    /// @notice Struct representing swap item, used for listing and in internal calculations
    struct Swap {
        /// @notice Swap's unique ID
        uint256 id;
        /// @notice Swap's buyer
        address buyer;
        /// @notice Swap opening epoch timestamp
        uint256 openTimestamp;
        /// @notice Swap's tenor
        IporTypes.SwapTenor tenor;
        /// @notice Index position of this Swap in an array of swaps' identification associated to swap buyer
        /// @dev Field used for gas optimization purposes, it allows for quick removal by id in the array.
        /// During removal the last item in the array is switched with the one that just has been removed.
        uint256 idsIndex;
        /// @notice Swap's collateral
        /// @dev value represented in 18 decimals
        uint256 collateral;
        /// @notice Swap's notional amount
        /// @dev value represented in 18 decimals
        uint256 notional;
        /// @notice Swap's notional amount denominated in the Interest Bearing Token (IBT)
        /// @dev value represented in 18 decimals
        uint256 ibtQuantity;
        /// @notice Fixed interest rate at which the position has been opened
        /// @dev value represented in 18 decimals
        uint256 fixedInterestRate;
        /// @notice Liquidation deposit amount
        /// @dev value represented in 18 decimals
        uint256 liquidationDepositAmount;
        /// @notice State of the swap
        /// @dev 0 - INACTIVE, 1 - ACTIVE
        IporTypes.SwapState state;
    }

    /// @notice Struct representing amounts related to Swap that is presently being opened.
    /// @dev all values represented in 18 decimals
    struct OpenSwapAmount {
        /// @notice Total Amount of asset that is sent from buyer to AmmTreasury when opening swap.
        uint256 totalAmount;
        /// @notice Swap's collateral
        uint256 collateral;
        /// @notice Swap's notional
        uint256 notional;
        /// @notice Opening Fee - part allocated as a profit of the Liquidity Pool
        uint256 openingFeeLPAmount;
        /// @notice  Part of the fee set aside for subsidizing the oracle that publishes IPOR rate. Flat fee set by the DAO.
        /// @notice Opening Fee - part allocated in Treasury balance. Part of the fee set asside for subsidising the oracle that publishes IPOR rate. Flat fee set by the DAO.
        uint256 openingFeeTreasuryAmount;
        /// @notice Fee set aside for subsidizing the oracle that publishes IPOR rate. Flat fee set by the DAO.
        uint256 iporPublicationFee;
        /// @notice Liquidation deposit is retained when the swap is opened. Value represented in 18 decimals.
        uint256 liquidationDepositAmount;
    }

    /// @notice Structure describes one swap processed by closeSwaps method, information about swap ID and flag if this swap was closed during execution closeSwaps method.
    struct IporSwapClosingResult {
        /// @notice Swap ID
        uint256 swapId;
        /// @notice Flag describe if swap was closed during this execution
        bool closed;
    }

    /// @notice Technical structure used for storing information about amounts used during redeeming assets from liquidity pool.
    struct RedeemAmount {
        /// @notice Asset amount represented in 18 decimals
        /// @dev Asset amount is a sum of wadRedeemFee and wadRedeemAmount
        uint256 wadAssetAmount;
        /// @notice Redeemed amount represented in decimals of asset
        uint256 redeemAmount;
        /// @notice Redeem fee value represented in 18 decimals
        uint256 wadRedeemFee;
        /// @notice Redeem amount represented in 18 decimals
        uint256 wadRedeemAmount;
    }

    struct UnwindParams {
        /// @notice Risk Indicators Inputs signer
        address messageSigner;
        /// @notice Spread Router contract address
        address spreadRouter;
        address ammStorage;
        address ammTreasury;
        SwapDirection direction;
        uint256 closeTimestamp;
        int256 swapPnlValueToDate;
        uint256 indexValue;
        Swap swap;
        IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration poolCfg;
        CloseSwapRiskIndicatorsInput riskIndicatorsInputs;
    }

    /// @notice Swap direction (long = Pay Fixed and Receive a Floating or short = receive fixed and pay a floating)
    enum SwapDirection {
        /// @notice When taking the "long" position the trader will pay a fixed rate and receive a floating rate.
        /// for more information refer to the documentation https://ipor-labs.gitbook.io/ipor-labs/automated-market-maker/ipor-swaps
        PAY_FIXED_RECEIVE_FLOATING,
        /// @notice When taking the "short" position the trader will pay a floating rate and receive a fixed rate.
        PAY_FLOATING_RECEIVE_FIXED
    }
    /// @notice List of closable statuses for a given swap
    /// @dev Closable status is a one of the following values:
    /// 0 - Swap is closable
    /// 1 - Swap is already closed
    /// 2 - Swap state required Buyer or Liquidator to close. Sender is not Buyer nor Liquidator.
    /// 3 - Cannot close swap, closing is too early for Community
    /// 4 - Cannot close swap with unwind because action is too early from the moment when swap was opened, validation based on Close Service configuration
    enum SwapClosableStatus {
        SWAP_IS_CLOSABLE,
        SWAP_ALREADY_CLOSED,
        SWAP_REQUIRED_BUYER_OR_LIQUIDATOR_TO_CLOSE,
        SWAP_CANNOT_CLOSE_CLOSING_TOO_EARLY_FOR_COMMUNITY,
        SWAP_CANNOT_CLOSE_WITH_UNWIND_ACTION_IS_TOO_EARLY
    }

    /// @notice Collection of swap attributes connected with IPOR Index and swap itself.
    /// @dev all values are in 18 decimals
    struct IporSwapIndicator {
        /// @notice IPOR Index value at the time of swap opening
        uint256 iporIndexValue;
        /// @notice IPOR Interest Bearing Token (IBT) price at the time of swap opening
        uint256 ibtPrice;
        /// @notice Swap's notional denominated in IBT
        uint256 ibtQuantity;
        /// @notice Fixed interest rate at which the position has been opened,
        /// it is quote from spread documentation
        uint256 fixedInterestRate;
    }

    /// @notice Risk indicators calculated for swap opening
    struct OpenSwapRiskIndicators {
        /// @notice Maximum collateral ratio in general
        uint256 maxCollateralRatio;
        /// @notice Maximum collateral ratio for a given leg
        uint256 maxCollateralRatioPerLeg;
        /// @notice Maximum leverage for a given leg
        uint256 maxLeveragePerLeg;
        /// @notice Base Spread for a given leg (without demand part)
        int256 baseSpreadPerLeg;
        /// @notice Fixed rate cap
        uint256 fixedRateCapPerLeg;
        /// @notice Demand spread factor used to calculate demand spread
        uint256 demandSpreadFactor;
    }

    /// @notice Risk indicators calculated for swap opening
    struct RiskIndicatorsInputs {
        /// @notice Maximum collateral ratio in general
        uint256 maxCollateralRatio;
        /// @notice Maximum collateral ratio for a given leg
        uint256 maxCollateralRatioPerLeg;
        /// @notice Maximum leverage for a given leg
        uint256 maxLeveragePerLeg;
        /// @notice Base Spread for a given leg (without demand part)
        int256 baseSpreadPerLeg;
        /// @notice Fixed rate cap
        uint256 fixedRateCapPerLeg;
        /// @notice Demand spread factor used to calculate demand spread
        uint256 demandSpreadFactor;
        /// @notice expiration date in seconds
        uint256 expiration;
        /// @notice signature of data (maxCollateralRatio, maxCollateralRatioPerLeg,maxLeveragePerLeg,baseSpreadPerLeg,fixedRateCapPerLeg,demandSpreadFactor,expiration,asset,tenor,direction)
        /// asset - address
        /// tenor - uint256
        /// direction - uint256
        bytes signature;
    }

    struct CloseSwapRiskIndicatorsInput {
        RiskIndicatorsInputs payFixed;
        RiskIndicatorsInputs receiveFixed;
    }

    /// @notice Structure containing information about swap's closing status, unwind values and PnL for a given swap and time.
    struct ClosingSwapDetails {
        /// @notice Swap's closing status
        AmmTypes.SwapClosableStatus closableStatus;
        /// @notice Flag indicating if swap unwind is required
        bool swapUnwindRequired;
        /// @notice Swap's unwind PnL Value, part of PnL corresponded to virtual swap (unwinded swap), represented in 18 decimals
        int256 swapUnwindPnlValue;
        /// @notice Unwind opening fee amount it is a sum of `swapUnwindFeeLPAmount` and `swapUnwindFeeTreasuryAmount`
        uint256 swapUnwindOpeningFeeAmount;
        /// @notice Part of unwind opening fee allocated as a profit of the Liquidity Pool
        uint256 swapUnwindFeeLPAmount;
        /// @notice Part of unwind opening fee allocated in Treasury Balance
        uint256 swapUnwindFeeTreasuryAmount;
        /// @notice Final Profit and Loss which takes into account the swap unwind and limits the PnL to the collateral amount. Represented in 18 decimals.
        int256 pnlValue;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     *
     * Furthermore, `isContract` will also return true if the target contract within
     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
     * which only has an effect at the end of a transaction.
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)

pragma solidity ^0.8.0;

import "../../interfaces/draft-IERC1822Upgradeable.sol";
import "../ERC1967/ERC1967UpgradeUpgradeable.sol";
import "./Initializable.sol";

/**
 * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
 * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
 *
 * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
 * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
 * `UUPSUpgradeable` with a custom implementation of upgrades.
 *
 * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
 *
 * _Available since v4.1._
 */
abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {
    function __UUPSUpgradeable_init() internal onlyInitializing {
    }

    function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
    }
    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
    address private immutable __self = address(this);

    /**
     * @dev Check that the execution is being performed through a delegatecall call and that the execution context is
     * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
     * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
     * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
     * fail.
     */
    modifier onlyProxy() {
        require(address(this) != __self, "Function must be called through delegatecall");
        require(_getImplementation() == __self, "Function must be called through active proxy");
        _;
    }

    /**
     * @dev Check that the execution is not being performed through a delegate call. This allows a function to be
     * callable on the implementing contract but not through proxies.
     */
    modifier notDelegated() {
        require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
        _;
    }

    /**
     * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
     * implementation. It is used to validate the implementation's compatibility when performing an upgrade.
     *
     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
     * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
     */
    function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
        return _IMPLEMENTATION_SLOT;
    }

    /**
     * @dev Upgrade the implementation of the proxy to `newImplementation`.
     *
     * Calls {_authorizeUpgrade}.
     *
     * Emits an {Upgraded} event.
     *
     * @custom:oz-upgrades-unsafe-allow-reachable delegatecall
     */
    function upgradeTo(address newImplementation) public virtual onlyProxy {
        _authorizeUpgrade(newImplementation);
        _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
    }

    /**
     * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
     * encoded in `data`.
     *
     * Calls {_authorizeUpgrade}.
     *
     * Emits an {Upgraded} event.
     *
     * @custom:oz-upgrades-unsafe-allow-reachable delegatecall
     */
    function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
        _authorizeUpgrade(newImplementation);
        _upgradeToAndCallUUPS(newImplementation, data, true);
    }

    /**
     * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
     * {upgradeTo} and {upgradeToAndCall}.
     *
     * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
     *
     * ```solidity
     * function _authorizeUpgrade(address) internal override onlyOwner {}
     * ```
     */
    function _authorizeUpgrade(address newImplementation) internal virtual;

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}

File 32 of 43 : IProxyImplementation.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;

/// @title Technical interface for reading data related to the UUPS proxy pattern in Ipor Protocol.
interface IProxyImplementation {
    /// @notice Retrieves the address of the implementation contract for UUPS proxy.
    /// @return The address of the implementation contract.
    /// @dev The function returns the value stored in the implementation storage slot.
    function getImplementation() external view returns (address);
}

// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.26;

import {IporErrors} from "../libraries/errors/IporErrors.sol";
import {StorageLibBaseV1} from "../base/libraries/StorageLibBaseV1.sol";

import {PauseManager} from "../security/PauseManager.sol";
import {OwnerManager} from "../security/OwnerManager.sol";
import {IRouterAccessControl} from "../interfaces/IRouterAccessControl.sol";

/// @title Smart contract responsible for managing access to administrative functions in IporProtocolRouter
contract AccessControl is IRouterAccessControl {
    /// @dev Reentrancy - flag when thread is left method
    uint256 internal constant _NOT_ENTERED = 1;
    /// @dev Reentrancy - flag when thread is entered to method
    uint256 internal constant _ENTERED = 2;

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[49] private __gap;

    /// @notice Checks if sender is owner
    modifier onlyOwner() {
        _onlyOwner();
        _;
    }

    /// @notice Checks if sender is appointed owner
    modifier onlyAppointedOwner() {
        require(StorageLibBaseV1.getAppointedOwner().appointedOwner == msg.sender, IporErrors.SENDER_NOT_APPOINTED_OWNER);
        _;
    }

    /// @notice Checks if sender is pause guardian
    modifier onlyPauseGuardian() {
        require(PauseManager.isPauseGuardian(msg.sender), IporErrors.CALLER_NOT_PAUSE_GUARDIAN);
        _;
    }

    /// @notice Steps before and after method execution to prevent reentrancy
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    /// @notice Gets IPOR Protocol Owner on Router
    /// @return IPOR Protocol Owner address
    function owner() external view override returns (address) {
        return OwnerManager.getOwner();
    }

    /// @notice Appoint new account to ownership
    /// @param appointedOwner New appointed owner address
    function appointToOwnership(address appointedOwner) public override onlyOwner {
        OwnerManager.appointToOwnership(appointedOwner);
    }

    /// @notice Confirm appointed ownership
    function confirmAppointmentToOwnership() public override onlyAppointedOwner {
        OwnerManager.confirmAppointmentToOwnership();
    }

    /// @notice Renounce ownership
    function renounceOwnership() public virtual override onlyOwner {
        OwnerManager.renounceOwnership();
    }

    /// @notice Checks if function is paused
    /// @param functionSig Function signature
    /// @return 1 if function is paused, 0 otherwise
    function paused(bytes4 functionSig) external view override returns (uint256) {
        return StorageLibBaseV1.getRouterFunctionPaused().value[functionSig];
    }

    /// @notice Pauses list of functions in IporProtocolRouter
    /// @dev Can be called only by pause guardian
    function pause(bytes4[] calldata functionSigs) external override onlyPauseGuardian {
        uint256 len = functionSigs.length;
        for (uint256 i; i < len; ) {
            StorageLibBaseV1.getRouterFunctionPaused().value[functionSigs[i]] = 1;
            unchecked {
                ++i;
            }
        }
    }

    /// @notice Unpauses list of functions in IporProtocolRouter
    /// @dev Can be called only by Owner of Ipor Protocol Router
    function unpause(bytes4[] calldata functionSigs) external override onlyOwner {
        uint256 len = functionSigs.length;
        for (uint256 i; i < len; ) {
            StorageLibBaseV1.getRouterFunctionPaused().value[functionSigs[i]] = 0;
            unchecked {
                ++i;
            }
        }
    }

    /// @notice Checks if address is pause guardian
    /// @param account Pause guardian address
    /// @return true if address is pause guardian, false otherwise
    function isPauseGuardian(address account) external view override returns (bool) {
        return PauseManager.isPauseGuardian(account);
    }

    /// @notice Adds new pause guardians
    /// @param guardians List of new pause guardians addresses
    function addPauseGuardians(address[] calldata guardians) external override onlyOwner {
        PauseManager.addPauseGuardians(guardians);
    }

    /// @notice Removes pause guardian
    /// @param guardians List of pause guardians addresses
    function removePauseGuardians(address[] calldata guardians) external override onlyOwner {
        PauseManager.removePauseGuardians(guardians);
    }

    function _checkFunctionSigAndIsNotPause(bytes4 functionSig, bytes4 expectedSig) internal view returns (bool) {
        if (functionSig == expectedSig) {
            require(StorageLibBaseV1.getRouterFunctionPaused().value[functionSig] == 0, IporErrors.METHOD_PAUSED);
            return true;
        }
        return false;
    }

    function _onlyOwner() internal view {
        require(StorageLibBaseV1.getOwner().owner == msg.sender, IporErrors.CALLER_NOT_OWNER);
    }

    function _nonReentrantBefore() internal {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(StorageLibBaseV1.getReentrancyStatus().value != _ENTERED, IporErrors.REENTRANCY);

        // Any calls to nonReentrant after this point will fail
        StorageLibBaseV1.getReentrancyStatus().value = _ENTERED;
    }

    function _nonReentrantAfter() internal {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        if (StorageLibBaseV1.getReentrancyStatus().value == _ENTERED) {
            StorageLibBaseV1.getReentrancyStatus().value = _NOT_ENTERED;
        }
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;

import "../libraries/errors/IporErrors.sol";
import {StorageLibBaseV1} from "../base/libraries/StorageLibBaseV1.sol";

/// @title Ipor Protocol Router Owner Manager library
library OwnerManager {
    /// @notice Emitted when account is appointed to transfer ownership
    /// @param appointedOwner Address of appointed owner
    event AppointedToTransferOwnership(address indexed appointedOwner);

    /// @notice Emitted when ownership is transferred
    /// @param previousOwner Address of previous owner
    /// @param newOwner Address of new owner
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /// @notice Gets the current owner of Ipor Protocol Router
    function getOwner() internal view returns (address) {
        return StorageLibBaseV1.getOwner().owner;
    }

    /// @notice Oppoint account to transfer ownership
    /// @param newAppointedOwner Address of appointed owner
    function appointToOwnership(address newAppointedOwner) internal {
        require(newAppointedOwner != address(0), IporErrors.WRONG_ADDRESS);
        StorageLibBaseV1.AppointedOwnerStorage storage appointedOwnerStorage = StorageLibBaseV1.getAppointedOwner();
        appointedOwnerStorage.appointedOwner = newAppointedOwner;
        emit AppointedToTransferOwnership(newAppointedOwner);
    }

    /// @notice Confirm appointment to ownership
    /// @dev This is real transfer ownership in second step by appointed account
    function confirmAppointmentToOwnership() internal {
        StorageLibBaseV1.AppointedOwnerStorage storage appointedOwnerStorage = StorageLibBaseV1.getAppointedOwner();
        appointedOwnerStorage.appointedOwner = address(0);
        transferOwnership(msg.sender);
    }

    /// @notice Renounce ownership
    function renounceOwnership() internal {
        transferOwnership(address(0));
        StorageLibBaseV1.AppointedOwnerStorage storage appointedOwnerStorage = StorageLibBaseV1.getAppointedOwner();
        appointedOwnerStorage.appointedOwner = address(0);
    }

    /// @notice Immediately transfers ownership
    function transferOwnership(address newOwner) internal {
        StorageLibBaseV1.OwnerStorage storage ownerStorage = StorageLibBaseV1.getOwner();
        address oldOwner = ownerStorage.owner;
        ownerStorage.owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.0;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
 * _Available since v4.9 for `string`, `bytes`._
 */
library StorageSlotUpgradeable {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }
}

File 36 of 43 : draft-IERC1822Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)

pragma solidity ^0.8.0;

/**
 * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
 * proxy whose upgrades are fully controlled by the current implementation.
 */
interface IERC1822ProxiableUpgradeable {
    /**
     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
     * address.
     *
     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
     * function revert if invoked through a proxy.
     */
    function proxiableUUID() external view returns (bytes32);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)

pragma solidity ^0.8.2;

import "../beacon/IBeaconUpgradeable.sol";
import "../../interfaces/IERC1967Upgradeable.sol";
import "../../interfaces/draft-IERC1822Upgradeable.sol";
import "../../utils/AddressUpgradeable.sol";
import "../../utils/StorageSlotUpgradeable.sol";
import "../utils/Initializable.sol";

/**
 * @dev This abstract contract provides getters and event emitting update functions for
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
 *
 * _Available since v4.1._
 */
abstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable {
    function __ERC1967Upgrade_init() internal onlyInitializing {
    }

    function __ERC1967Upgrade_init_unchained() internal onlyInitializing {
    }
    // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;

    /**
     * @dev Storage slot with the address of the current implementation.
     * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /**
     * @dev Returns the current implementation address.
     */
    function _getImplementation() internal view returns (address) {
        return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 implementation slot.
     */
    function _setImplementation(address newImplementation) private {
        require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract");
        StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
    }

    /**
     * @dev Perform implementation upgrade
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeTo(address newImplementation) internal {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
    }

    /**
     * @dev Perform implementation upgrade with additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
        _upgradeTo(newImplementation);
        if (data.length > 0 || forceCall) {
            AddressUpgradeable.functionDelegateCall(newImplementation, data);
        }
    }

    /**
     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
        // Upgrades from old implementations will perform a rollback test. This test requires the new
        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
        // this special case will break upgrade paths from old UUPS implementation to new ones.
        if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {
            _setImplementation(newImplementation);
        } else {
            try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
            } catch {
                revert("ERC1967Upgrade: new implementation is not UUPS");
            }
            _upgradeToAndCall(newImplementation, data, forceCall);
        }
    }

    /**
     * @dev Storage slot with the admin of the contract.
     * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    /**
     * @dev Returns the current admin.
     */
    function _getAdmin() internal view returns (address) {
        return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 admin slot.
     */
    function _setAdmin(address newAdmin) private {
        require(newAdmin != address(0), "ERC1967: new admin is the zero address");
        StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
    }

    /**
     * @dev Changes the admin of the proxy.
     *
     * Emits an {AdminChanged} event.
     */
    function _changeAdmin(address newAdmin) internal {
        emit AdminChanged(_getAdmin(), newAdmin);
        _setAdmin(newAdmin);
    }

    /**
     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
     */
    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;

    /**
     * @dev Returns the current beacon.
     */
    function _getBeacon() internal view returns (address) {
        return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;
    }

    /**
     * @dev Stores a new beacon in the EIP1967 beacon slot.
     */
    function _setBeacon(address newBeacon) private {
        require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract");
        require(
            AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),
            "ERC1967: beacon implementation is not a contract"
        );
        StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;
    }

    /**
     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
     *
     * Emits a {BeaconUpgraded} event.
     */
    function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
        _setBeacon(newBeacon);
        emit BeaconUpgraded(newBeacon);
        if (data.length > 0 || forceCall) {
            AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);
        }
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.2;

import "../../utils/AddressUpgradeable.sol";

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```solidity
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 *
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     * @custom:oz-retyped-from bool
     */
    uint8 private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint8 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
     * constructor.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        bool isTopLevelCall = !_initializing;
        require(
            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
            "Initializable: contract is already initialized"
        );
        _initialized = 1;
        if (isTopLevelCall) {
            _initializing = true;
        }
        _;
        if (isTopLevelCall) {
            _initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: setting the version to 255 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint8 version) {
        require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
        _initialized = version;
        _initializing = true;
        _;
        _initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        require(_initializing, "Initializable: contract is not initializing");
        _;
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        require(!_initializing, "Initializable: contract is initializing");
        if (_initialized != type(uint8).max) {
            _initialized = type(uint8).max;
            emit Initialized(type(uint8).max);
        }
    }

    /**
     * @dev Returns the highest version that has been initialized. See {reinitializer}.
     */
    function _getInitializedVersion() internal view returns (uint8) {
        return _initialized;
    }

    /**
     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
     */
    function _isInitializing() internal view returns (bool) {
        return _initializing;
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;

import {StorageLibBaseV1} from "../base/libraries/StorageLibBaseV1.sol";

/// @title Ipor Protocol Router Pause Manager library
library PauseManager {
    /// @notice Emitted when new pause guardian is added
    /// @param guardians List of addresses of guardian
    event PauseGuardiansAdded(address[] indexed guardians);

    /// @notice Emitted when pause guardian is removed
    /// @param guardians List of addresses of guardian
    event PauseGuardiansRemoved(address[] indexed guardians);

    /// @notice Checks if account is Ipor Protocol Router pause guardian
    /// @param account Address of guardian
    /// @return true if account is Ipor Protocol Router pause guardian
    function isPauseGuardian(address account) internal view returns (bool) {
        mapping(address => bool) storage pauseGuardians = StorageLibBaseV1.getPauseGuardianStorage();
        return pauseGuardians[account];
    }

    /// @notice Adds Ipor Protocol Router pause guardian
    /// @param newGuardians Addresses of guardians
    function addPauseGuardians(address[] calldata newGuardians) internal {
        uint256 length = newGuardians.length;
        if (length == 0) {
            return;
        }

        mapping(address => bool) storage pauseGuardians = StorageLibBaseV1.getPauseGuardianStorage();

        for (uint256 i; i < length; ) {
            pauseGuardians[newGuardians[i]] = true;
            unchecked {
                i++;
            }
        }
        emit PauseGuardiansAdded(newGuardians);
    }

    /// @notice Removes Ipor Protocol Router pause guardian
    /// @param guardians Addresses of guardians
    function removePauseGuardians(address[] calldata guardians) internal {
        uint256 length = guardians.length;

        if (length == 0) {
            return;
        }

        mapping(address => bool) storage pauseGuardians = StorageLibBaseV1.getPauseGuardianStorage();

        for (uint256 i; i < length; ) {
            pauseGuardians[guardians[i]] = false;
            unchecked {
                i++;
            }
        }
        emit PauseGuardiansRemoved(guardians);
    }
}

// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.26;

interface IRouterAccessControl {
    function owner() external view returns (address);

    function appointToOwnership(address appointedOwner) external;

    function confirmAppointmentToOwnership() external;

    function renounceOwnership() external;

    function paused(bytes4 functionSig) external view returns (uint256);

    function pause(bytes4[] calldata functionSigs) external;

    function unpause(bytes4[] calldata functionSigs) external;

    function isPauseGuardian(address account) external view returns (bool);

    function addPauseGuardians(address[] calldata guardians) external;

    function removePauseGuardians(address[] calldata guardians) external;
}

File 41 of 43 : IBeaconUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)

pragma solidity ^0.8.0;

/**
 * @dev This is the interface that {BeaconProxy} expects of its beacon.
 */
interface IBeaconUpgradeable {
    /**
     * @dev Must return an address that can be used as a delegate call target.
     *
     * {BeaconProxy} will check that this address is a contract.
     */
    function implementation() external view returns (address);
}

File 42 of 43 : IERC1967Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)

pragma solidity ^0.8.0;

/**
 * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
 *
 * _Available since v4.8.3._
 */
interface IERC1967Upgradeable {
    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementation);

    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);

    /**
     * @dev Emitted when the beacon is changed.
     */
    event BeaconUpgraded(address indexed beacon);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     *
     * Furthermore, `isContract` will also return true if the target contract within
     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
     * which only has an effect at the end of a transaction.
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

Settings
{
  "remappings": [
    "@ensdomains/=node_modules/@ensdomains/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "eth-gas-reporter/=node_modules/eth-gas-reporter/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "@ipor-protocol/contracts/=contracts/",
    "@ipor-protocol/test/=test/",
    "abdk-libraries-solidity/=node_modules/abdk-libraries-solidity/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 1000000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": false
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"components":[{"internalType":"address","name":"ammSwapsLens","type":"address"},{"internalType":"address","name":"ammPoolsLens","type":"address"},{"internalType":"address","name":"ammPoolsLensBaseV1","type":"address"},{"internalType":"address","name":"assetManagementLens","type":"address"},{"internalType":"address","name":"ammOpenSwapService","type":"address"},{"internalType":"address","name":"ammCloseSwapServiceUsdt","type":"address"},{"internalType":"address","name":"ammCloseSwapServiceUsdc","type":"address"},{"internalType":"address","name":"ammCloseSwapServiceDai","type":"address"},{"internalType":"address","name":"ammCloseSwapLens","type":"address"},{"internalType":"address","name":"ammPoolsService","type":"address"},{"internalType":"address","name":"ammGovernanceService","type":"address"},{"internalType":"address","name":"liquidityMiningLens","type":"address"},{"internalType":"address","name":"powerTokenLens","type":"address"},{"internalType":"address","name":"flowService","type":"address"},{"internalType":"address","name":"stakeService","type":"address"},{"internalType":"address","name":"stEth","type":"address"},{"internalType":"address","name":"weEth","type":"address"},{"internalType":"address","name":"usdm","type":"address"}],"internalType":"struct IporProtocolRouterEthereum.DeployedContracts","name":"deployedContracts","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"appointedOwner","type":"address"}],"name":"AppointedToTransferOwnership","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address[]","name":"guardians","type":"address[]"}],"name":"PauseGuardiansAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address[]","name":"guardians","type":"address[]"}],"name":"PauseGuardiansRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address[]","name":"guardians","type":"address[]"}],"name":"addPauseGuardians","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ammCloseSwapLens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ammCloseSwapServiceDai","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ammCloseSwapServiceUsdc","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ammCloseSwapServiceUsdt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ammGovernanceService","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ammOpenSwapService","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ammPoolsLens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ammPoolsLensBaseV1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ammPoolsService","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ammSwapsLens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"appointedOwner","type":"address"}],"name":"appointToOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"assetManagementLens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"calls","type":"bytes[]"}],"name":"batchExecutor","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"confirmAppointmentToOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flowService","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConfiguration","outputs":[{"components":[{"internalType":"address","name":"ammSwapsLens","type":"address"},{"internalType":"address","name":"ammPoolsLens","type":"address"},{"internalType":"address","name":"ammPoolsLensBaseV1","type":"address"},{"internalType":"address","name":"assetManagementLens","type":"address"},{"internalType":"address","name":"ammOpenSwapService","type":"address"},{"internalType":"address","name":"ammCloseSwapServiceUsdt","type":"address"},{"internalType":"address","name":"ammCloseSwapServiceUsdc","type":"address"},{"internalType":"address","name":"ammCloseSwapServiceDai","type":"address"},{"internalType":"address","name":"ammCloseSwapLens","type":"address"},{"internalType":"address","name":"ammPoolsService","type":"address"},{"internalType":"address","name":"ammGovernanceService","type":"address"},{"internalType":"address","name":"liquidityMiningLens","type":"address"},{"internalType":"address","name":"powerTokenLens","type":"address"},{"internalType":"address","name":"flowService","type":"address"},{"internalType":"address","name":"stakeService","type":"address"},{"internalType":"address","name":"stEth","type":"address"},{"internalType":"address","name":"weEth","type":"address"},{"internalType":"address","name":"usdm","type":"address"}],"internalType":"struct IporProtocolRouterEthereum.DeployedContracts","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"pausedInput","type":"bool"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isPauseGuardian","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidityMiningLens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4[]","name":"functionSigs","type":"bytes4[]"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"functionSig","type":"bytes4"}],"name":"paused","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"powerTokenLens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"guardians","type":"address[]"}],"name":"removePauseGuardians","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stEth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakeService","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4[]","name":"functionSigs","type":"bytes4[]"}],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"usdm","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weEth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

6102e060405230608052348015610014575f80fd5b506040516155f73803806155f7833981016040819052610033916103c7565b8051610047906001600160a01b0316610267565b6001600160a01b0390811660a05260208201516100649116610267565b6001600160a01b0390811660c05260408201516100819116610267565b6001600160a01b0390811660e05261010082015161009f9116610267565b6001600160a01b03908116610100526101408201516100be9116610267565b6001600160a01b03908116610120526101a08201516100dd9116610267565b6001600160a01b03908116610140526101c08201516100fc9116610267565b6001600160a01b039081166101605261018082015161011b9116610267565b6001600160a01b039081166101805261016082015161013a9116610267565b6001600160a01b039081166101a05260a08201516101589116610267565b6001600160a01b039081166101c05260c08201516101769116610267565b6001600160a01b039081166101e05260e08201516101949116610267565b6001600160a01b039081166102005260808201516101b29116610267565b6001600160a01b03908116610220526101208201516101d19116610267565b6001600160a01b039081166102405260608201516101ef9116610267565b6001600160a01b03908116610260526101e082015161020e9116610267565b6001600160a01b039081166102805261020082015161022d9116610267565b6001600160a01b039081166102a05261022082015161024c9116610267565b6001600160a01b03166102c0526102616102bf565b5061055e565b604080518082019091526008815267049504f525f3030360c41b60208201525f906001600160a01b0383166102b85760405162461bcd60e51b81526004016102af9190610529565b60405180910390fd5b5090919050565b5f54610100900460ff16156103265760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b60648201526084016102af565b5f5460ff90811614610375575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b60405161024081016001600160401b03811182821017156103a657634e487b7160e01b5f52604160045260245ffd5b60405290565b80516001600160a01b03811681146103c2575f80fd5b919050565b5f6102408284031280156103d9575f80fd5b506103e2610377565b6103eb836103ac565b81526103f9602084016103ac565b602082015261040a604084016103ac565b604082015261041b606084016103ac565b606082015261042c608084016103ac565b608082015261043d60a084016103ac565b60a082015261044e60c084016103ac565b60c082015261045f60e084016103ac565b60e082015261047161010084016103ac565b61010082015261048461012084016103ac565b61012082015261049761014084016103ac565b6101408201526104aa61016084016103ac565b6101608201526104bd61018084016103ac565b6101808201526104d06101a084016103ac565b6101a08201526104e36101c084016103ac565b6101c08201526104f66101e084016103ac565b6101e082015261050961020084016103ac565b61020082015261051c61022084016103ac565b6102208201529392505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516102a0516102c051614e7961077e5f395f81816108da01528181610c3e0152818161188601526126c801525f81816102aa0152818161089e01528181611638015261267201525f818161086201528181610a4901528181610e53015281816112840152818161150f015261261d01525f818161059201528181610b01015261280601525f81816106fa01528181610caf015281816117d40152612da501525f81816105ce015281816109af0152818161120201526122b201525f818161068201528181610b8601526113cd01525f81816106460152818161097c015261136801525f81816103550152818161060a015261130301525f818161077201528181610a7c01526129f301525f81816107ae01528181610b340152612c7801525f81816103bd015281816108260152611a5201525f81816107ea01528181610c0b0152611b4701525f818161073601528181610ce201528181611c13015261224201525f818161040f015281816106be0152612d3501525f818161055601528181610a16015261271d01525f818161051a01528181610949015281816125a8015261274601525f81816104de01528181610bd801526124eb01525f8181612f590152818161300901528181613131015281816131e101526132f30152614e795ff3fe608060405260043610610237575f3560e01c806391d88cf811610137578063d2fdb662116100af578063ee138d0f1161007e578063f8ddf39711610063578063f8ddf39714610c7f578063fa8dea6514610c9e578063fad18f1c14610cd15761023e565b8063ee138d0f14610c2d578063f85e61a714610c605761023e565b8063d2fdb66214610b75578063d53a822f14610ba8578063dcfee2ab14610bc7578063e20953f614610bfa5761023e565b8063ac522e2411610106578063b9344efe116100eb578063b9344efe14610af0578063bfaabe0d14610b23578063c43b668714610b565761023e565b8063ac522e2414610ab2578063ac544a0414610ad15761023e565b806391d88cf814610a0557806399940ece14610a38578063a93b3dcd14610a6b578063aaf10f4214610a9e5761023e565b806359237eba116101ca57806373a129cc1161019957806381e1176a1161017e57806381e1176a1461099e5780638adc2cfd146109d15780638da5cb5b146109f15761023e565b806373a129cc146109385780637c6a87b81461096b5761023e565b806359237eba146103df57806359f41cc9146103fe5780636bd50cef14610431578063715018a6146109245761023e565b80634ce5cc6b116102065780634ce5cc6b146103445780634f1ef2861461037757806352d1902d1461038a578063542d2bf1146103ac5761023e565b806304b4c226146102835780632f2e4bee146102995780633659cfe6146102f65780634261f4d8146103155761023e565b3661023e57005b5f3660606102776102725f357fffffffff00000000000000000000000000000000000000000000000000000000165f610d04565b612e3d565b80519350602001915050f35b34801561028e575f80fd5b50610297612ea8565b005b3480156102a4575f80fd5b506102cc7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610301575f80fd5b50610297610310366004614638565b612f42565b348015610320575f80fd5b5061033461032f366004614638565b613110565b60405190151581526020016102ed565b34801561034f575f80fd5b506102cc7f000000000000000000000000000000000000000000000000000000000000000081565b61029761038536600461467e565b61311a565b348015610395575f80fd5b5061039e6132da565b6040519081526020016102ed565b3480156103b7575f80fd5b506102cc7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103ea575f80fd5b5061039e6103f936600461477f565b6133c5565b348015610409575f80fd5b506102cc7f000000000000000000000000000000000000000000000000000000000000000081565b34801561043c575f80fd5b5061091760408051610240810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e0810182905261020081018290526102208101919091526040518061024001604052807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102ed91906147be565b34801561092f575f80fd5b50610297613405565b348015610943575f80fd5b506102cc7f000000000000000000000000000000000000000000000000000000000000000081565b348015610976575f80fd5b506102cc7f000000000000000000000000000000000000000000000000000000000000000081565b3480156109a9575f80fd5b506102cc7f000000000000000000000000000000000000000000000000000000000000000081565b6109e46109df366004614ae7565b613415565b6040516102ed9190614b72565b3480156109fc575f80fd5b506102cc613573565b348015610a10575f80fd5b506102cc7f000000000000000000000000000000000000000000000000000000000000000081565b348015610a43575f80fd5b506102cc7f000000000000000000000000000000000000000000000000000000000000000081565b348015610a76575f80fd5b506102cc7f000000000000000000000000000000000000000000000000000000000000000081565b348015610aa9575f80fd5b506102cc613581565b348015610abd575f80fd5b50610297610acc366004614ae7565b6135c0565b348015610adc575f80fd5b50610297610aeb366004614ae7565b6135d2565b348015610afb575f80fd5b506102cc7f000000000000000000000000000000000000000000000000000000000000000081565b348015610b2e575f80fd5b506102cc7f000000000000000000000000000000000000000000000000000000000000000081565b348015610b61575f80fd5b50610297610b70366004614ae7565b613656565b348015610b80575f80fd5b506102cc7f000000000000000000000000000000000000000000000000000000000000000081565b348015610bb3575f80fd5b50610297610bc2366004614bf3565b613668565b348015610bd2575f80fd5b506102cc7f000000000000000000000000000000000000000000000000000000000000000081565b348015610c05575f80fd5b506102cc7f000000000000000000000000000000000000000000000000000000000000000081565b348015610c38575f80fd5b506102cc7f000000000000000000000000000000000000000000000000000000000000000081565b348015610c6b575f80fd5b50610297610c7a366004614638565b613808565b348015610c8a575f80fd5b50610297610c99366004614ae7565b613819565b348015610ca9575f80fd5b506102cc7f000000000000000000000000000000000000000000000000000000000000000081565b348015610cdc575f80fd5b506102cc7f000000000000000000000000000000000000000000000000000000000000000081565b5f610d2f837fa9c659c300000000000000000000000000000000000000000000000000000000613908565b80610d5f5750610d5f837fbf9645cc00000000000000000000000000000000000000000000000000000000613908565b80610d8f5750610d8f837f53ee8fa000000000000000000000000000000000000000000000000000000000613908565b80610dbf5750610dbf837fa8e36d8500000000000000000000000000000000000000000000000000000000613908565b80610def5750610def837f6e40733300000000000000000000000000000000000000000000000000000000613908565b80610e1f5750610e1f837fb82ebe8700000000000000000000000000000000000000000000000000000000613908565b15610e9157815f03610e3357610e336139ef565b5f610e3c613a75565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081165f908152602092909252604090912060010154169150612e379050565b610ebb837fb60aebf900000000000000000000000000000000000000000000000000000000613908565b80610eeb5750610eeb837fe48acfc200000000000000000000000000000000000000000000000000000000613908565b80610f1b5750610f1b837f92f91ca100000000000000000000000000000000000000000000000000000000613908565b80610f4b5750610f4b837f33cb3bc000000000000000000000000000000000000000000000000000000000613908565b80610f7b5750610f7b837f8420dd4800000000000000000000000000000000000000000000000000000000613908565b80610fab5750610fab837f54fa316900000000000000000000000000000000000000000000000000000000613908565b80610fdb5750610fdb837f57a4aa3000000000000000000000000000000000000000000000000000000000613908565b8061100b575061100b837f4de364ad00000000000000000000000000000000000000000000000000000000613908565b8061103b575061103b837f913a88c300000000000000000000000000000000000000000000000000000000613908565b8061106b575061106b837fe8ac562700000000000000000000000000000000000000000000000000000000613908565b8061109b575061109b837ffdb4ecd800000000000000000000000000000000000000000000000000000000613908565b806110cb57506110cb837fed2b4a5400000000000000000000000000000000000000000000000000000000613908565b806110fb57506110fb837f4097184100000000000000000000000000000000000000000000000000000000613908565b8061112b575061112b837f5b22c18800000000000000000000000000000000000000000000000000000000613908565b8061115b575061115b837f6089131400000000000000000000000000000000000000000000000000000000613908565b8061118b575061118b837fa35158d900000000000000000000000000000000000000000000000000000000613908565b806111bb57506111bb837f13aac10b00000000000000000000000000000000000000000000000000000000613908565b806111eb57506111eb837f0d441a9700000000000000000000000000000000000000000000000000000000613908565b1561122657815f036111ff576111ff6139ef565b507f0000000000000000000000000000000000000000000000000000000000000000612e37565b611250837f9606f78100000000000000000000000000000000000000000000000000000000613908565b156112c257815f03611264576112646139ef565b5f61126d613a75565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081165f908152602092909252604090912060020154169150612e379050565b6112ec837fef04a40e00000000000000000000000000000000000000000000000000000000613908565b1561132757815f03611300576113006139ef565b507f0000000000000000000000000000000000000000000000000000000000000000612e37565b611351837fa545026400000000000000000000000000000000000000000000000000000000613908565b1561138c57815f03611365576113656139ef565b507f0000000000000000000000000000000000000000000000000000000000000000612e37565b6113b6837fd0aa46b100000000000000000000000000000000000000000000000000000000613908565b156113f157815f036113ca576113ca6139ef565b507f0000000000000000000000000000000000000000000000000000000000000000612e37565b61141b837f137a359500000000000000000000000000000000000000000000000000000000613908565b8061144b575061144b837f05b1eb0500000000000000000000000000000000000000000000000000000000613908565b8061147b575061147b837ff727e8e500000000000000000000000000000000000000000000000000000000613908565b806114ab57506114ab837f0d2ef99800000000000000000000000000000000000000000000000000000000613908565b806114db57506114db837fd93af4e100000000000000000000000000000000000000000000000000000000613908565b1561154a57815f036114ef576114ef6139ef565b5f6114f8613a75565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081165f908152602092909252604090912054169150612e379050565b611574837fa1d8efe500000000000000000000000000000000000000000000000000000000613908565b806115a457506115a4837f0e2b403e00000000000000000000000000000000000000000000000000000000613908565b806115d457506115d4837f8f8f778300000000000000000000000000000000000000000000000000000000613908565b806116045750611604837f6454aef200000000000000000000000000000000000000000000000000000000613908565b1561167357815f03611618576116186139ef565b5f611621613a75565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081165f908152602092909252604090912054169150612e379050565b61169d837fd800fe8f00000000000000000000000000000000000000000000000000000000613908565b806116cd57506116cd837fe8bd543f00000000000000000000000000000000000000000000000000000000613908565b806116fd57506116fd837f4cac99d000000000000000000000000000000000000000000000000000000000613908565b8061172d575061172d837f54653e9700000000000000000000000000000000000000000000000000000000613908565b8061175d575061175d837f4e854bd900000000000000000000000000000000000000000000000000000000613908565b8061178d575061178d837fd2c1fc6800000000000000000000000000000000000000000000000000000000613908565b806117bd57506117bd837f69c9749300000000000000000000000000000000000000000000000000000000613908565b156117f857815f036117d1576117d16139ef565b507f0000000000000000000000000000000000000000000000000000000000000000612e37565b611822837ff004023100000000000000000000000000000000000000000000000000000000613908565b806118525750611852837f5c30fe3700000000000000000000000000000000000000000000000000000000613908565b156118c157815f03611866576118666139ef565b5f61186f613a75565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081165f908152602092909252604090912054169150612e379050565b6118eb837fbeba0f9d00000000000000000000000000000000000000000000000000000000613908565b8061191b575061191b837fd062999100000000000000000000000000000000000000000000000000000000613908565b8061194b575061194b837f993430ce00000000000000000000000000000000000000000000000000000000613908565b8061197b575061197b837f887737eb00000000000000000000000000000000000000000000000000000000613908565b806119ab57506119ab837fa752abd800000000000000000000000000000000000000000000000000000000613908565b806119db57506119db837f1add351700000000000000000000000000000000000000000000000000000000613908565b80611a0b5750611a0b837f7485597f00000000000000000000000000000000000000000000000000000000613908565b80611a3b5750611a3b837f27c6677c00000000000000000000000000000000000000000000000000000000613908565b15611a7657815f03611a4f57611a4f6139ef565b507f0000000000000000000000000000000000000000000000000000000000000000612e37565b611aa0837f7243828900000000000000000000000000000000000000000000000000000000613908565b80611ad05750611ad0837f24afd78800000000000000000000000000000000000000000000000000000000613908565b80611b005750611b00837fce65e12200000000000000000000000000000000000000000000000000000000613908565b80611b305750611b30837f7c599a2900000000000000000000000000000000000000000000000000000000613908565b15611b6b57815f03611b4457611b446139ef565b507f0000000000000000000000000000000000000000000000000000000000000000612e37565b7fffffffff0000000000000000000000000000000000000000000000000000000083167f9dd267e6000000000000000000000000000000000000000000000000000000001480611bfc57507fffffffff0000000000000000000000000000000000000000000000000000000083167fdb3454ea00000000000000000000000000000000000000000000000000000000145b15611c3757815f03611c1057611c106139ef565b507f0000000000000000000000000000000000000000000000000000000000000000612e37565b7fffffffff0000000000000000000000000000000000000000000000000000000083167f6eb1f154000000000000000000000000000000000000000000000000000000001480611cc857507fffffffff0000000000000000000000000000000000000000000000000000000083167f36bfb76b00000000000000000000000000000000000000000000000000000000145b80611d1457507fffffffff0000000000000000000000000000000000000000000000000000000083167fe09da46500000000000000000000000000000000000000000000000000000000145b80611d6057507fffffffff0000000000000000000000000000000000000000000000000000000083167f040a26c700000000000000000000000000000000000000000000000000000000145b80611dac57507fffffffff0000000000000000000000000000000000000000000000000000000083167ff2fea28e00000000000000000000000000000000000000000000000000000000145b80611df857507fffffffff0000000000000000000000000000000000000000000000000000000083167fc461f51c00000000000000000000000000000000000000000000000000000000145b80611e4457507fffffffff0000000000000000000000000000000000000000000000000000000083167fce36760700000000000000000000000000000000000000000000000000000000145b80611e9057507fffffffff0000000000000000000000000000000000000000000000000000000083167f16184ba300000000000000000000000000000000000000000000000000000000145b80611edc57507fffffffff0000000000000000000000000000000000000000000000000000000083167f4b36df5300000000000000000000000000000000000000000000000000000000145b80611f2857507fffffffff0000000000000000000000000000000000000000000000000000000083167fddc1b17a00000000000000000000000000000000000000000000000000000000145b80611f7457507fffffffff0000000000000000000000000000000000000000000000000000000083167f2ac2782600000000000000000000000000000000000000000000000000000000145b80611fc057507fffffffff0000000000000000000000000000000000000000000000000000000083167f671be91700000000000000000000000000000000000000000000000000000000145b15611fcd57611c10613a81565b7f1bcbf257000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000084160161201e57611264613a81565b7fb6d7407a000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000084160161206f57611300613a81565b7f4f9c6ae7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008416016120c057611365613a81565b7f04b3aae7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000841601612111576113ca613a81565b7fffffffff0000000000000000000000000000000000000000000000000000000083167f789543790000000000000000000000000000000000000000000000000000000014806121a257507fffffffff0000000000000000000000000000000000000000000000000000000083167ff7e3341200000000000000000000000000000000000000000000000000000000145b806121ee57507fffffffff0000000000000000000000000000000000000000000000000000000083167f1ba3163c00000000000000000000000000000000000000000000000000000000145b8061223a57507fffffffff0000000000000000000000000000000000000000000000000000000083167f6e8b13c400000000000000000000000000000000000000000000000000000000145b1561226657507f0000000000000000000000000000000000000000000000000000000000000000612e37565b7fd24423a6000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008416016122d657507f0000000000000000000000000000000000000000000000000000000000000000612e37565b7fffffffff0000000000000000000000000000000000000000000000000000000083167f1188de6200000000000000000000000000000000000000000000000000000000148061236757507fffffffff0000000000000000000000000000000000000000000000000000000083167f7eea00a800000000000000000000000000000000000000000000000000000000145b806123b357507fffffffff0000000000000000000000000000000000000000000000000000000083167fd83eb8ba00000000000000000000000000000000000000000000000000000000145b806123ff57507fffffffff0000000000000000000000000000000000000000000000000000000083167f635411b000000000000000000000000000000000000000000000000000000000145b8061244b57507fffffffff0000000000000000000000000000000000000000000000000000000083167fc34605c900000000000000000000000000000000000000000000000000000000145b8061249757507fffffffff0000000000000000000000000000000000000000000000000000000083167f046df83500000000000000000000000000000000000000000000000000000000145b806124e357507fffffffff0000000000000000000000000000000000000000000000000000000083167f99fcfbfc00000000000000000000000000000000000000000000000000000000145b1561250f57507f0000000000000000000000000000000000000000000000000000000000000000612e37565b7fffffffff0000000000000000000000000000000000000000000000000000000083167f6653b05b0000000000000000000000000000000000000000000000000000000014806125a057507fffffffff0000000000000000000000000000000000000000000000000000000083167fab0cd12700000000000000000000000000000000000000000000000000000000145b156125cc57507f0000000000000000000000000000000000000000000000000000000000000000612e37565b7ff84abf18000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000084160161276d575f60043590507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806126c057507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b8061271657507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b15612744577f0000000000000000000000000000000000000000000000000000000000000000915050612e37565b7f0000000000000000000000000000000000000000000000000000000000000000915050612e37565b7fffffffff0000000000000000000000000000000000000000000000000000000083167f386d19460000000000000000000000000000000000000000000000000000000014806127fe57507fffffffff0000000000000000000000000000000000000000000000000000000083167fc31d3e7d00000000000000000000000000000000000000000000000000000000145b1561282a57507f0000000000000000000000000000000000000000000000000000000000000000612e37565b7fffffffff0000000000000000000000000000000000000000000000000000000083167f287ab7940000000000000000000000000000000000000000000000000000000014806128bb57507fffffffff0000000000000000000000000000000000000000000000000000000083167fe10a2e1700000000000000000000000000000000000000000000000000000000145b8061290757507fffffffff0000000000000000000000000000000000000000000000000000000083167f6173847900000000000000000000000000000000000000000000000000000000145b8061295357507fffffffff0000000000000000000000000000000000000000000000000000000083167f79b7e3ba00000000000000000000000000000000000000000000000000000000145b8061299f57507fffffffff0000000000000000000000000000000000000000000000000000000083167f5dbe6fec00000000000000000000000000000000000000000000000000000000145b806129eb57507fffffffff0000000000000000000000000000000000000000000000000000000083167ff5c1272800000000000000000000000000000000000000000000000000000000145b15612a1757507f0000000000000000000000000000000000000000000000000000000000000000612e37565b7fffffffff0000000000000000000000000000000000000000000000000000000083167f51329a18000000000000000000000000000000000000000000000000000000001480612aa857507fffffffff0000000000000000000000000000000000000000000000000000000083167fc207160000000000000000000000000000000000000000000000000000000000145b80612af457507fffffffff0000000000000000000000000000000000000000000000000000000083167f24f9c70000000000000000000000000000000000000000000000000000000000145b80612b4057507fffffffff0000000000000000000000000000000000000000000000000000000083167f59fb6b5400000000000000000000000000000000000000000000000000000000145b80612b8c57507fffffffff0000000000000000000000000000000000000000000000000000000083167ff9d7118800000000000000000000000000000000000000000000000000000000145b80612bd857507fffffffff0000000000000000000000000000000000000000000000000000000083167f95b76bc500000000000000000000000000000000000000000000000000000000145b80612c2457507fffffffff0000000000000000000000000000000000000000000000000000000083167f68ad8fc600000000000000000000000000000000000000000000000000000000145b80612c7057507fffffffff0000000000000000000000000000000000000000000000000000000083167fbb9568fd00000000000000000000000000000000000000000000000000000000145b15612c9c57507f0000000000000000000000000000000000000000000000000000000000000000612e37565b7fffffffff0000000000000000000000000000000000000000000000000000000083167f0bcf52c7000000000000000000000000000000000000000000000000000000001480612d2d57507fffffffff0000000000000000000000000000000000000000000000000000000083167fd851cbda00000000000000000000000000000000000000000000000000000000145b15612d5957507f0000000000000000000000000000000000000000000000000000000000000000612e37565b7f5379ea9f000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000841601612dc957507f0000000000000000000000000000000000000000000000000000000000000000612e37565b604080518082018252600881527f49504f525f303132000000000000000000000000000000000000000000000000602082015290517f08c379a0000000000000000000000000000000000000000000000000000000008152612e2e9190600401614c12565b60405180910390fd5b92915050565b60605f612e965f368080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505073ffffffffffffffffffffffffffffffffffffffff871692915050613b10565b9050612ea0613b3c565b612e37613c05565b33612eb1613c1f565b5460408051808201909152600881527f49504f525f30303700000000000000000000000000000000000000000000000060208201529173ffffffffffffffffffffffffffffffffffffffff90911614612f37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2e9190614c12565b50612f40613c2b565b565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163003613007576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608401612e2e565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16613046613581565b73ffffffffffffffffffffffffffffffffffffffff16146130e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401612e2e565b6130f281613c65565b604080515f8082526020820190925261310d91839190613c6d565b50565b5f612e3782613e71565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630036131df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608401612e2e565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1661321e613581565b73ffffffffffffffffffffffffffffffffffffffff16146132c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401612e2e565b6132ca82613c65565b6132d682826001613c6d565b5050565b5f3073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146133a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401612e2e565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f6133ce613eaa565b7fffffffff000000000000000000000000000000000000000000000000000000009092165f90815260209290925250604090205490565b61340d613a81565b612f40613eb6565b606061341f6139ef565b815f808267ffffffffffffffff81111561343b5761343b614651565b60405190808252806020026020018201604052801561346e57816020015b60608152602001906001900390816134595790505b5090505f5b83811461355e576134bf87878381811061348f5761348f614c24565b90506020028101906134a19190614c51565b6134af916004915f91614cb2565b6134b891614cd9565b6001610d04565b92506135398787838181106134d6576134d6614c24565b90506020028101906134e89190614c51565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505073ffffffffffffffffffffffffffffffffffffffff871692915050613b10565b82828151811061354b5761354b614c24565b6020908102919091010152600101613473565b50613567613b3c565b92505050612e37613c05565b5f61357c613ef1565b905090565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6135c8613a81565b6132d68282613efa565b6135da613a81565b805f5b81811015613650575f6135ee613eaa565b5f86868581811061360157613601614c24565b9050602002016020810190613616919061477f565b7fffffffff0000000000000000000000000000000000000000000000000000000016815260208101919091526040015f20556001016135dd565b50505050565b61365e613a81565b6132d68282613fe7565b5f54610100900460ff161580801561368657505f54600160ff909116105b8061369f5750303b15801561369f57505f5460ff166001145b61372b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401612e2e565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015613787575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61378f6140d5565b6137983361416b565b60016137a26141ea565b5580156132d6575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b613810613a81565b61310d816141f6565b61382233613e71565b6040518060400160405280600881526020017f49504f525f30313100000000000000000000000000000000000000000000000081525090613890576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2e9190614c12565b50805f5b818110156136505760016138a6613eaa565b5f8686858181106138b9576138b9614c24565b90506020020160208101906138ce919061477f565b7fffffffff0000000000000000000000000000000000000000000000000000000016815260208101919091526040015f2055600101613894565b5f7fffffffff00000000000000000000000000000000000000000000000000000000808316908416036139e75761393d613eaa565b7fffffffff0000000000000000000000000000000000000000000000000000000084165f9081526020918252604090819020548151808301909252600882527f49504f525f3031350000000000000000000000000000000000000000000000009282019290925290156139dd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2e9190614c12565b5060019050612e37565b505f92915050565b60026139f96141ea565b5460408051808201909152600881527f49504f525f30313600000000000000000000000000000000000000000000000060208201529103613a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2e9190614c12565b506002613a726141ea565b55565b5f80612e37600c6142f2565b33613a8a614313565b5460408051808201909152600881527f49504f525f30313400000000000000000000000000000000000000000000000060208201529173ffffffffffffffffffffffffffffffffffffffff9091161461310d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2e9190614c12565b6060613b358383604051806060016040528060278152602001614e1d6027913961431e565b9392505050565b47801561310d576002613b4d6141ea565b540361310d576040515f90339083908381818185875af1925050503d805f8114613b92576040519150601f19603f3d011682016040523d82523d5f602084013e613b97565b606091505b50509050806132d657604080518082018252600881527f49504f525f303138000000000000000000000000000000000000000000000000602082015290517f08c379a0000000000000000000000000000000000000000000000000000000008152612e2e9190600401614c12565b6002613c0f6141ea565b5403612f40576001613a726141ea565b5f80612e3760016142f2565b5f613c34613c1f565b80547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155905061310d3361416b565b61310d613a81565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615613ca557613ca08361439f565b505050565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015613d2a575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252613d2791810190614d3e565b60015b613db6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f7420555550530000000000000000000000000000000000006064820152608401612e2e565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114613e65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c655555494400000000000000000000000000000000000000000000006064820152608401612e2e565b50613ca08383836144a9565b5f80613e7b6144cd565b73ffffffffffffffffffffffffffffffffffffffff9093165f9081526020939093525050604090205460ff1690565b5f80612e3760056142f2565b613ebf5f61416b565b5f613ec8613c1f565b80547fffffffffffffffffffffffff000000000000000000000000000000000000000016905550565b5f6135a4614313565b805f819003613f0857505050565b5f613f116144cd565b90505f5b82811015613fa1575f825f878785818110613f3257613f32614c24565b9050602002016020810190613f479190614638565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040015f2080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055600101613f15565b508383604051613fb2929190614d55565b604051908190038120907fe36d877f5755caee7e117ab1005d1acd030211e8a7ad495316fcaf980d0d054c905f90a250505050565b805f819003613ff557505050565b5f613ffe6144cd565b90505f5b8281101561408f576001825f87878581811061402057614020614c24565b90506020020160208101906140359190614638565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040015f2080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055600101614002565b5083836040516140a0929190614d55565b604051908190038120907f7802196382882a6ea8cc8c8a1d5f53efe52da8a8d8a0e6f6ce86662996f181df905f90a250505050565b5f54610100900460ff16612f40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401612e2e565b5f614174614313565b805473ffffffffffffffffffffffffffffffffffffffff8481167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117845560405193945091169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f80612e3760046142f2565b60408051808201909152600881527f49504f525f303030000000000000000000000000000000000000000000000000602082015273ffffffffffffffffffffffffffffffffffffffff8216614278576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2e9190614c12565b505f614282613c1f565b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081178255604051919250907f3ec7bb1d452f3c36260fa8ef678a597fd97574d8ec42f6dc98ffce3dbc91228f905f90a25050565b5f620f424082600c81111561430957614309614da1565b612e379190614dce565b5f80612e375f6142f2565b60605f808573ffffffffffffffffffffffffffffffffffffffff16856040516143479190614e06565b5f60405180830381855af49150503d805f811461437f576040519150601f19603f3d011682016040523d82523d5f602084013e614384565b606091505b5091509150614395868383876144d9565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81163b614443576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401612e2e565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6144b283614580565b5f825111806144be5750805b15613ca0576136508383613b10565b5f80612e3760036142f2565b6060831561456e5782515f036145675773ffffffffffffffffffffffffffffffffffffffff85163b614567576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401612e2e565b5081614578565b61457883836145cc565b949350505050565b6145898161439f565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b8151156145dc5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2e9190614c12565b803573ffffffffffffffffffffffffffffffffffffffff81168114614633575f80fd5b919050565b5f60208284031215614648575f80fd5b613b3582614610565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f806040838503121561468f575f80fd5b61469883614610565b9150602083013567ffffffffffffffff8111156146b3575f80fd5b8301601f810185136146c3575f80fd5b803567ffffffffffffffff8111156146dd576146dd614651565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160116810181811067ffffffffffffffff8211171561474957614749614651565b604052818152828201602001871015614760575f80fd5b816020840160208301375f602083830101528093505050509250929050565b5f6020828403121561478f575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114613b35575f80fd5b815173ffffffffffffffffffffffffffffffffffffffff16815261024081016020830151614804602084018273ffffffffffffffffffffffffffffffffffffffff169052565b50604083015161482c604084018273ffffffffffffffffffffffffffffffffffffffff169052565b506060830151614854606084018273ffffffffffffffffffffffffffffffffffffffff169052565b50608083015161487c608084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060a08301516148a460a084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c08301516148cc60c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060e08301516148f460e084018273ffffffffffffffffffffffffffffffffffffffff169052565b5061010083015161491e61010084018273ffffffffffffffffffffffffffffffffffffffff169052565b5061012083015161494861012084018273ffffffffffffffffffffffffffffffffffffffff169052565b5061014083015161497261014084018273ffffffffffffffffffffffffffffffffffffffff169052565b5061016083015161499c61016084018273ffffffffffffffffffffffffffffffffffffffff169052565b506101808301516149c661018084018273ffffffffffffffffffffffffffffffffffffffff169052565b506101a08301516149f06101a084018273ffffffffffffffffffffffffffffffffffffffff169052565b506101c0830151614a1a6101c084018273ffffffffffffffffffffffffffffffffffffffff169052565b506101e0830151614a446101e084018273ffffffffffffffffffffffffffffffffffffffff169052565b50610200830151614a6e61020084018273ffffffffffffffffffffffffffffffffffffffff169052565b50610220830151614a9861022084018273ffffffffffffffffffffffffffffffffffffffff169052565b5092915050565b5f8083601f840112614aaf575f80fd5b50813567ffffffffffffffff811115614ac6575f80fd5b6020830191508360208260051b8501011115614ae0575f80fd5b9250929050565b5f8060208385031215614af8575f80fd5b823567ffffffffffffffff811115614b0e575f80fd5b614b1a85828601614a9f565b90969095509350505050565b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b82811015614be7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0878603018452614bd2858351614b26565b94506020938401939190910190600101614b98565b50929695505050505050565b5f60208284031215614c03575f80fd5b81358015158114613b35575f80fd5b602081525f613b356020830184614b26565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614c84575f80fd5b83018035915067ffffffffffffffff821115614c9e575f80fd5b602001915036819003821315614ae0575f80fd5b5f8085851115614cc0575f80fd5b83861115614ccc575f80fd5b5050820193919092039150565b80357fffffffff000000000000000000000000000000000000000000000000000000008116906004841015614a98577fffffffff00000000000000000000000000000000000000000000000000000000808560040360031b1b82161691505092915050565b5f60208284031215614d4e575f80fd5b5051919050565b5f8184825b85811015614d965773ffffffffffffffffffffffffffffffffffffffff614d8083614610565b1683526020928301929190910190600101614d5a565b509095945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b80820180821115612e37577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f82518060208501845e5f92019182525091905056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e8cb1f97061bc71b2fc3c58651e3aa67a470d24cba7e5e2a311cdd748b652f1364736f6c634300081a0033000000000000000000000000476c44e60a377c1d23877e9dd2955c384b2dcd8c0000000000000000000000001f44c5ada019cbb0729e277775877ccdb940e04a000000000000000000000000ce96800a16791d68ee96706915ead714d67db70d0000000000000000000000001d4c4c07e34a6b43f104204d243aae084d5f6e090000000000000000000000004ef45eccc64e4bb36b9c46b9ad353855a48016d100000000000000000000000011a02a63e9142ed929b9fd95357762fc7bab56f90000000000000000000000009a9f60349e2da59250433276b3ef474f1f69f8e8000000000000000000000000735b3fbc2ea7fce1b4e17d9e50eceafe4e6fc3d9000000000000000000000000066cbd24d8285e25cb38222ea669735bdebbaac2000000000000000000000000912ae5d95bd86f4ae6e580a0fa14a124c998f337000000000000000000000000b64f71300626499d3d9f8e87bfa34f50c75f0470000000000000000000000000769d54d25dd9da2159fa690e67b27484eeb39e980000000000000000000000005a4fc8f98ca356b7e957d18c155bc62e32d21ec3000000000000000000000000d3486d81d52b52125b9fb1ae9d674645ece665ac0000000000000000000000003790383f8685b439391dc1bc56f7b3f82236f6c7000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe84000000000000000000000000cd5fe23c85820f7b72d0926fc9b05b43e359b7ee00000000000000000000000059d9356e565ab3a36dd77763fc0d87feaf85508c

Deployed Bytecode

0x608060405260043610610237575f3560e01c806391d88cf811610137578063d2fdb662116100af578063ee138d0f1161007e578063f8ddf39711610063578063f8ddf39714610c7f578063fa8dea6514610c9e578063fad18f1c14610cd15761023e565b8063ee138d0f14610c2d578063f85e61a714610c605761023e565b8063d2fdb66214610b75578063d53a822f14610ba8578063dcfee2ab14610bc7578063e20953f614610bfa5761023e565b8063ac522e2411610106578063b9344efe116100eb578063b9344efe14610af0578063bfaabe0d14610b23578063c43b668714610b565761023e565b8063ac522e2414610ab2578063ac544a0414610ad15761023e565b806391d88cf814610a0557806399940ece14610a38578063a93b3dcd14610a6b578063aaf10f4214610a9e5761023e565b806359237eba116101ca57806373a129cc1161019957806381e1176a1161017e57806381e1176a1461099e5780638adc2cfd146109d15780638da5cb5b146109f15761023e565b806373a129cc146109385780637c6a87b81461096b5761023e565b806359237eba146103df57806359f41cc9146103fe5780636bd50cef14610431578063715018a6146109245761023e565b80634ce5cc6b116102065780634ce5cc6b146103445780634f1ef2861461037757806352d1902d1461038a578063542d2bf1146103ac5761023e565b806304b4c226146102835780632f2e4bee146102995780633659cfe6146102f65780634261f4d8146103155761023e565b3661023e57005b5f3660606102776102725f357fffffffff00000000000000000000000000000000000000000000000000000000165f610d04565b612e3d565b80519350602001915050f35b34801561028e575f80fd5b50610297612ea8565b005b3480156102a4575f80fd5b506102cc7f000000000000000000000000cd5fe23c85820f7b72d0926fc9b05b43e359b7ee81565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b348015610301575f80fd5b50610297610310366004614638565b612f42565b348015610320575f80fd5b5061033461032f366004614638565b613110565b60405190151581526020016102ed565b34801561034f575f80fd5b506102cc7f00000000000000000000000011a02a63e9142ed929b9fd95357762fc7bab56f981565b61029761038536600461467e565b61311a565b348015610395575f80fd5b5061039e6132da565b6040519081526020016102ed565b3480156103b7575f80fd5b506102cc7f0000000000000000000000003790383f8685b439391dc1bc56f7b3f82236f6c781565b3480156103ea575f80fd5b5061039e6103f936600461477f565b6133c5565b348015610409575f80fd5b506102cc7f000000000000000000000000066cbd24d8285e25cb38222ea669735bdebbaac281565b34801561043c575f80fd5b5061091760408051610240810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e0810182905261020081018290526102208101919091526040518061024001604052807f000000000000000000000000476c44e60a377c1d23877e9dd2955c384b2dcd8c73ffffffffffffffffffffffffffffffffffffffff1681526020017f0000000000000000000000001f44c5ada019cbb0729e277775877ccdb940e04a73ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000ce96800a16791d68ee96706915ead714d67db70d73ffffffffffffffffffffffffffffffffffffffff1681526020017f0000000000000000000000001d4c4c07e34a6b43f104204d243aae084d5f6e0973ffffffffffffffffffffffffffffffffffffffff1681526020017f0000000000000000000000004ef45eccc64e4bb36b9c46b9ad353855a48016d173ffffffffffffffffffffffffffffffffffffffff1681526020017f00000000000000000000000011a02a63e9142ed929b9fd95357762fc7bab56f973ffffffffffffffffffffffffffffffffffffffff1681526020017f0000000000000000000000009a9f60349e2da59250433276b3ef474f1f69f8e873ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000735b3fbc2ea7fce1b4e17d9e50eceafe4e6fc3d973ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000066cbd24d8285e25cb38222ea669735bdebbaac273ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000912ae5d95bd86f4ae6e580a0fa14a124c998f33773ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000b64f71300626499d3d9f8e87bfa34f50c75f047073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000769d54d25dd9da2159fa690e67b27484eeb39e9873ffffffffffffffffffffffffffffffffffffffff1681526020017f0000000000000000000000005a4fc8f98ca356b7e957d18c155bc62e32d21ec373ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000d3486d81d52b52125b9fb1ae9d674645ece665ac73ffffffffffffffffffffffffffffffffffffffff1681526020017f0000000000000000000000003790383f8685b439391dc1bc56f7b3f82236f6c773ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe8473ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000cd5fe23c85820f7b72d0926fc9b05b43e359b7ee73ffffffffffffffffffffffffffffffffffffffff1681526020017f00000000000000000000000059d9356e565ab3a36dd77763fc0d87feaf85508c73ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102ed91906147be565b34801561092f575f80fd5b50610297613405565b348015610943575f80fd5b506102cc7f0000000000000000000000001f44c5ada019cbb0729e277775877ccdb940e04a81565b348015610976575f80fd5b506102cc7f0000000000000000000000009a9f60349e2da59250433276b3ef474f1f69f8e881565b3480156109a9575f80fd5b506102cc7f0000000000000000000000004ef45eccc64e4bb36b9c46b9ad353855a48016d181565b6109e46109df366004614ae7565b613415565b6040516102ed9190614b72565b3480156109fc575f80fd5b506102cc613573565b348015610a10575f80fd5b506102cc7f000000000000000000000000ce96800a16791d68ee96706915ead714d67db70d81565b348015610a43575f80fd5b506102cc7f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe8481565b348015610a76575f80fd5b506102cc7f000000000000000000000000769d54d25dd9da2159fa690e67b27484eeb39e9881565b348015610aa9575f80fd5b506102cc613581565b348015610abd575f80fd5b50610297610acc366004614ae7565b6135c0565b348015610adc575f80fd5b50610297610aeb366004614ae7565b6135d2565b348015610afb575f80fd5b506102cc7f0000000000000000000000001d4c4c07e34a6b43f104204d243aae084d5f6e0981565b348015610b2e575f80fd5b506102cc7f0000000000000000000000005a4fc8f98ca356b7e957d18c155bc62e32d21ec381565b348015610b61575f80fd5b50610297610b70366004614ae7565b613656565b348015610b80575f80fd5b506102cc7f000000000000000000000000735b3fbc2ea7fce1b4e17d9e50eceafe4e6fc3d981565b348015610bb3575f80fd5b50610297610bc2366004614bf3565b613668565b348015610bd2575f80fd5b506102cc7f000000000000000000000000476c44e60a377c1d23877e9dd2955c384b2dcd8c81565b348015610c05575f80fd5b506102cc7f000000000000000000000000d3486d81d52b52125b9fb1ae9d674645ece665ac81565b348015610c38575f80fd5b506102cc7f00000000000000000000000059d9356e565ab3a36dd77763fc0d87feaf85508c81565b348015610c6b575f80fd5b50610297610c7a366004614638565b613808565b348015610c8a575f80fd5b50610297610c99366004614ae7565b613819565b348015610ca9575f80fd5b506102cc7f000000000000000000000000912ae5d95bd86f4ae6e580a0fa14a124c998f33781565b348015610cdc575f80fd5b506102cc7f000000000000000000000000b64f71300626499d3d9f8e87bfa34f50c75f047081565b5f610d2f837fa9c659c300000000000000000000000000000000000000000000000000000000613908565b80610d5f5750610d5f837fbf9645cc00000000000000000000000000000000000000000000000000000000613908565b80610d8f5750610d8f837f53ee8fa000000000000000000000000000000000000000000000000000000000613908565b80610dbf5750610dbf837fa8e36d8500000000000000000000000000000000000000000000000000000000613908565b80610def5750610def837f6e40733300000000000000000000000000000000000000000000000000000000613908565b80610e1f5750610e1f837fb82ebe8700000000000000000000000000000000000000000000000000000000613908565b15610e9157815f03610e3357610e336139ef565b5f610e3c613a75565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe8481165f908152602092909252604090912060010154169150612e379050565b610ebb837fb60aebf900000000000000000000000000000000000000000000000000000000613908565b80610eeb5750610eeb837fe48acfc200000000000000000000000000000000000000000000000000000000613908565b80610f1b5750610f1b837f92f91ca100000000000000000000000000000000000000000000000000000000613908565b80610f4b5750610f4b837f33cb3bc000000000000000000000000000000000000000000000000000000000613908565b80610f7b5750610f7b837f8420dd4800000000000000000000000000000000000000000000000000000000613908565b80610fab5750610fab837f54fa316900000000000000000000000000000000000000000000000000000000613908565b80610fdb5750610fdb837f57a4aa3000000000000000000000000000000000000000000000000000000000613908565b8061100b575061100b837f4de364ad00000000000000000000000000000000000000000000000000000000613908565b8061103b575061103b837f913a88c300000000000000000000000000000000000000000000000000000000613908565b8061106b575061106b837fe8ac562700000000000000000000000000000000000000000000000000000000613908565b8061109b575061109b837ffdb4ecd800000000000000000000000000000000000000000000000000000000613908565b806110cb57506110cb837fed2b4a5400000000000000000000000000000000000000000000000000000000613908565b806110fb57506110fb837f4097184100000000000000000000000000000000000000000000000000000000613908565b8061112b575061112b837f5b22c18800000000000000000000000000000000000000000000000000000000613908565b8061115b575061115b837f6089131400000000000000000000000000000000000000000000000000000000613908565b8061118b575061118b837fa35158d900000000000000000000000000000000000000000000000000000000613908565b806111bb57506111bb837f13aac10b00000000000000000000000000000000000000000000000000000000613908565b806111eb57506111eb837f0d441a9700000000000000000000000000000000000000000000000000000000613908565b1561122657815f036111ff576111ff6139ef565b507f0000000000000000000000004ef45eccc64e4bb36b9c46b9ad353855a48016d1612e37565b611250837f9606f78100000000000000000000000000000000000000000000000000000000613908565b156112c257815f03611264576112646139ef565b5f61126d613a75565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe8481165f908152602092909252604090912060020154169150612e379050565b6112ec837fef04a40e00000000000000000000000000000000000000000000000000000000613908565b1561132757815f03611300576113006139ef565b507f00000000000000000000000011a02a63e9142ed929b9fd95357762fc7bab56f9612e37565b611351837fa545026400000000000000000000000000000000000000000000000000000000613908565b1561138c57815f03611365576113656139ef565b507f0000000000000000000000009a9f60349e2da59250433276b3ef474f1f69f8e8612e37565b6113b6837fd0aa46b100000000000000000000000000000000000000000000000000000000613908565b156113f157815f036113ca576113ca6139ef565b507f000000000000000000000000735b3fbc2ea7fce1b4e17d9e50eceafe4e6fc3d9612e37565b61141b837f137a359500000000000000000000000000000000000000000000000000000000613908565b8061144b575061144b837f05b1eb0500000000000000000000000000000000000000000000000000000000613908565b8061147b575061147b837ff727e8e500000000000000000000000000000000000000000000000000000000613908565b806114ab57506114ab837f0d2ef99800000000000000000000000000000000000000000000000000000000613908565b806114db57506114db837fd93af4e100000000000000000000000000000000000000000000000000000000613908565b1561154a57815f036114ef576114ef6139ef565b5f6114f8613a75565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe8481165f908152602092909252604090912054169150612e379050565b611574837fa1d8efe500000000000000000000000000000000000000000000000000000000613908565b806115a457506115a4837f0e2b403e00000000000000000000000000000000000000000000000000000000613908565b806115d457506115d4837f8f8f778300000000000000000000000000000000000000000000000000000000613908565b806116045750611604837f6454aef200000000000000000000000000000000000000000000000000000000613908565b1561167357815f03611618576116186139ef565b5f611621613a75565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000cd5fe23c85820f7b72d0926fc9b05b43e359b7ee81165f908152602092909252604090912054169150612e379050565b61169d837fd800fe8f00000000000000000000000000000000000000000000000000000000613908565b806116cd57506116cd837fe8bd543f00000000000000000000000000000000000000000000000000000000613908565b806116fd57506116fd837f4cac99d000000000000000000000000000000000000000000000000000000000613908565b8061172d575061172d837f54653e9700000000000000000000000000000000000000000000000000000000613908565b8061175d575061175d837f4e854bd900000000000000000000000000000000000000000000000000000000613908565b8061178d575061178d837fd2c1fc6800000000000000000000000000000000000000000000000000000000613908565b806117bd57506117bd837f69c9749300000000000000000000000000000000000000000000000000000000613908565b156117f857815f036117d1576117d16139ef565b507f000000000000000000000000912ae5d95bd86f4ae6e580a0fa14a124c998f337612e37565b611822837ff004023100000000000000000000000000000000000000000000000000000000613908565b806118525750611852837f5c30fe3700000000000000000000000000000000000000000000000000000000613908565b156118c157815f03611866576118666139ef565b5f61186f613a75565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000059d9356e565ab3a36dd77763fc0d87feaf85508c81165f908152602092909252604090912054169150612e379050565b6118eb837fbeba0f9d00000000000000000000000000000000000000000000000000000000613908565b8061191b575061191b837fd062999100000000000000000000000000000000000000000000000000000000613908565b8061194b575061194b837f993430ce00000000000000000000000000000000000000000000000000000000613908565b8061197b575061197b837f887737eb00000000000000000000000000000000000000000000000000000000613908565b806119ab57506119ab837fa752abd800000000000000000000000000000000000000000000000000000000613908565b806119db57506119db837f1add351700000000000000000000000000000000000000000000000000000000613908565b80611a0b5750611a0b837f7485597f00000000000000000000000000000000000000000000000000000000613908565b80611a3b5750611a3b837f27c6677c00000000000000000000000000000000000000000000000000000000613908565b15611a7657815f03611a4f57611a4f6139ef565b507f0000000000000000000000003790383f8685b439391dc1bc56f7b3f82236f6c7612e37565b611aa0837f7243828900000000000000000000000000000000000000000000000000000000613908565b80611ad05750611ad0837f24afd78800000000000000000000000000000000000000000000000000000000613908565b80611b005750611b00837fce65e12200000000000000000000000000000000000000000000000000000000613908565b80611b305750611b30837f7c599a2900000000000000000000000000000000000000000000000000000000613908565b15611b6b57815f03611b4457611b446139ef565b507f000000000000000000000000d3486d81d52b52125b9fb1ae9d674645ece665ac612e37565b7fffffffff0000000000000000000000000000000000000000000000000000000083167f9dd267e6000000000000000000000000000000000000000000000000000000001480611bfc57507fffffffff0000000000000000000000000000000000000000000000000000000083167fdb3454ea00000000000000000000000000000000000000000000000000000000145b15611c3757815f03611c1057611c106139ef565b507f000000000000000000000000b64f71300626499d3d9f8e87bfa34f50c75f0470612e37565b7fffffffff0000000000000000000000000000000000000000000000000000000083167f6eb1f154000000000000000000000000000000000000000000000000000000001480611cc857507fffffffff0000000000000000000000000000000000000000000000000000000083167f36bfb76b00000000000000000000000000000000000000000000000000000000145b80611d1457507fffffffff0000000000000000000000000000000000000000000000000000000083167fe09da46500000000000000000000000000000000000000000000000000000000145b80611d6057507fffffffff0000000000000000000000000000000000000000000000000000000083167f040a26c700000000000000000000000000000000000000000000000000000000145b80611dac57507fffffffff0000000000000000000000000000000000000000000000000000000083167ff2fea28e00000000000000000000000000000000000000000000000000000000145b80611df857507fffffffff0000000000000000000000000000000000000000000000000000000083167fc461f51c00000000000000000000000000000000000000000000000000000000145b80611e4457507fffffffff0000000000000000000000000000000000000000000000000000000083167fce36760700000000000000000000000000000000000000000000000000000000145b80611e9057507fffffffff0000000000000000000000000000000000000000000000000000000083167f16184ba300000000000000000000000000000000000000000000000000000000145b80611edc57507fffffffff0000000000000000000000000000000000000000000000000000000083167f4b36df5300000000000000000000000000000000000000000000000000000000145b80611f2857507fffffffff0000000000000000000000000000000000000000000000000000000083167fddc1b17a00000000000000000000000000000000000000000000000000000000145b80611f7457507fffffffff0000000000000000000000000000000000000000000000000000000083167f2ac2782600000000000000000000000000000000000000000000000000000000145b80611fc057507fffffffff0000000000000000000000000000000000000000000000000000000083167f671be91700000000000000000000000000000000000000000000000000000000145b15611fcd57611c10613a81565b7f1bcbf257000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000084160161201e57611264613a81565b7fb6d7407a000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000084160161206f57611300613a81565b7f4f9c6ae7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008416016120c057611365613a81565b7f04b3aae7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000841601612111576113ca613a81565b7fffffffff0000000000000000000000000000000000000000000000000000000083167f789543790000000000000000000000000000000000000000000000000000000014806121a257507fffffffff0000000000000000000000000000000000000000000000000000000083167ff7e3341200000000000000000000000000000000000000000000000000000000145b806121ee57507fffffffff0000000000000000000000000000000000000000000000000000000083167f1ba3163c00000000000000000000000000000000000000000000000000000000145b8061223a57507fffffffff0000000000000000000000000000000000000000000000000000000083167f6e8b13c400000000000000000000000000000000000000000000000000000000145b1561226657507f000000000000000000000000b64f71300626499d3d9f8e87bfa34f50c75f0470612e37565b7fd24423a6000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008416016122d657507f0000000000000000000000004ef45eccc64e4bb36b9c46b9ad353855a48016d1612e37565b7fffffffff0000000000000000000000000000000000000000000000000000000083167f1188de6200000000000000000000000000000000000000000000000000000000148061236757507fffffffff0000000000000000000000000000000000000000000000000000000083167f7eea00a800000000000000000000000000000000000000000000000000000000145b806123b357507fffffffff0000000000000000000000000000000000000000000000000000000083167fd83eb8ba00000000000000000000000000000000000000000000000000000000145b806123ff57507fffffffff0000000000000000000000000000000000000000000000000000000083167f635411b000000000000000000000000000000000000000000000000000000000145b8061244b57507fffffffff0000000000000000000000000000000000000000000000000000000083167fc34605c900000000000000000000000000000000000000000000000000000000145b8061249757507fffffffff0000000000000000000000000000000000000000000000000000000083167f046df83500000000000000000000000000000000000000000000000000000000145b806124e357507fffffffff0000000000000000000000000000000000000000000000000000000083167f99fcfbfc00000000000000000000000000000000000000000000000000000000145b1561250f57507f000000000000000000000000476c44e60a377c1d23877e9dd2955c384b2dcd8c612e37565b7fffffffff0000000000000000000000000000000000000000000000000000000083167f6653b05b0000000000000000000000000000000000000000000000000000000014806125a057507fffffffff0000000000000000000000000000000000000000000000000000000083167fab0cd12700000000000000000000000000000000000000000000000000000000145b156125cc57507f0000000000000000000000001f44c5ada019cbb0729e277775877ccdb940e04a612e37565b7ff84abf18000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000084160161276d575f60043590507f000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe8473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614806126c057507f000000000000000000000000cd5fe23c85820f7b72d0926fc9b05b43e359b7ee73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b8061271657507f00000000000000000000000059d9356e565ab3a36dd77763fc0d87feaf85508c73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b15612744577f000000000000000000000000ce96800a16791d68ee96706915ead714d67db70d915050612e37565b7f0000000000000000000000001f44c5ada019cbb0729e277775877ccdb940e04a915050612e37565b7fffffffff0000000000000000000000000000000000000000000000000000000083167f386d19460000000000000000000000000000000000000000000000000000000014806127fe57507fffffffff0000000000000000000000000000000000000000000000000000000083167fc31d3e7d00000000000000000000000000000000000000000000000000000000145b1561282a57507f0000000000000000000000001d4c4c07e34a6b43f104204d243aae084d5f6e09612e37565b7fffffffff0000000000000000000000000000000000000000000000000000000083167f287ab7940000000000000000000000000000000000000000000000000000000014806128bb57507fffffffff0000000000000000000000000000000000000000000000000000000083167fe10a2e1700000000000000000000000000000000000000000000000000000000145b8061290757507fffffffff0000000000000000000000000000000000000000000000000000000083167f6173847900000000000000000000000000000000000000000000000000000000145b8061295357507fffffffff0000000000000000000000000000000000000000000000000000000083167f79b7e3ba00000000000000000000000000000000000000000000000000000000145b8061299f57507fffffffff0000000000000000000000000000000000000000000000000000000083167f5dbe6fec00000000000000000000000000000000000000000000000000000000145b806129eb57507fffffffff0000000000000000000000000000000000000000000000000000000083167ff5c1272800000000000000000000000000000000000000000000000000000000145b15612a1757507f000000000000000000000000769d54d25dd9da2159fa690e67b27484eeb39e98612e37565b7fffffffff0000000000000000000000000000000000000000000000000000000083167f51329a18000000000000000000000000000000000000000000000000000000001480612aa857507fffffffff0000000000000000000000000000000000000000000000000000000083167fc207160000000000000000000000000000000000000000000000000000000000145b80612af457507fffffffff0000000000000000000000000000000000000000000000000000000083167f24f9c70000000000000000000000000000000000000000000000000000000000145b80612b4057507fffffffff0000000000000000000000000000000000000000000000000000000083167f59fb6b5400000000000000000000000000000000000000000000000000000000145b80612b8c57507fffffffff0000000000000000000000000000000000000000000000000000000083167ff9d7118800000000000000000000000000000000000000000000000000000000145b80612bd857507fffffffff0000000000000000000000000000000000000000000000000000000083167f95b76bc500000000000000000000000000000000000000000000000000000000145b80612c2457507fffffffff0000000000000000000000000000000000000000000000000000000083167f68ad8fc600000000000000000000000000000000000000000000000000000000145b80612c7057507fffffffff0000000000000000000000000000000000000000000000000000000083167fbb9568fd00000000000000000000000000000000000000000000000000000000145b15612c9c57507f0000000000000000000000005a4fc8f98ca356b7e957d18c155bc62e32d21ec3612e37565b7fffffffff0000000000000000000000000000000000000000000000000000000083167f0bcf52c7000000000000000000000000000000000000000000000000000000001480612d2d57507fffffffff0000000000000000000000000000000000000000000000000000000083167fd851cbda00000000000000000000000000000000000000000000000000000000145b15612d5957507f000000000000000000000000066cbd24d8285e25cb38222ea669735bdebbaac2612e37565b7f5379ea9f000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000841601612dc957507f000000000000000000000000912ae5d95bd86f4ae6e580a0fa14a124c998f337612e37565b604080518082018252600881527f49504f525f303132000000000000000000000000000000000000000000000000602082015290517f08c379a0000000000000000000000000000000000000000000000000000000008152612e2e9190600401614c12565b60405180910390fd5b92915050565b60605f612e965f368080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505073ffffffffffffffffffffffffffffffffffffffff871692915050613b10565b9050612ea0613b3c565b612e37613c05565b33612eb1613c1f565b5460408051808201909152600881527f49504f525f30303700000000000000000000000000000000000000000000000060208201529173ffffffffffffffffffffffffffffffffffffffff90911614612f37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2e9190614c12565b50612f40613c2b565b565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000cc735caf5354415308dbd826e9734a70b69461d6163003613007576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608401612e2e565b7f000000000000000000000000cc735caf5354415308dbd826e9734a70b69461d673ffffffffffffffffffffffffffffffffffffffff16613046613581565b73ffffffffffffffffffffffffffffffffffffffff16146130e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401612e2e565b6130f281613c65565b604080515f8082526020820190925261310d91839190613c6d565b50565b5f612e3782613e71565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000cc735caf5354415308dbd826e9734a70b69461d61630036131df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608401612e2e565b7f000000000000000000000000cc735caf5354415308dbd826e9734a70b69461d673ffffffffffffffffffffffffffffffffffffffff1661321e613581565b73ffffffffffffffffffffffffffffffffffffffff16146132c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401612e2e565b6132ca82613c65565b6132d682826001613c6d565b5050565b5f3073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000cc735caf5354415308dbd826e9734a70b69461d616146133a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401612e2e565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f6133ce613eaa565b7fffffffff000000000000000000000000000000000000000000000000000000009092165f90815260209290925250604090205490565b61340d613a81565b612f40613eb6565b606061341f6139ef565b815f808267ffffffffffffffff81111561343b5761343b614651565b60405190808252806020026020018201604052801561346e57816020015b60608152602001906001900390816134595790505b5090505f5b83811461355e576134bf87878381811061348f5761348f614c24565b90506020028101906134a19190614c51565b6134af916004915f91614cb2565b6134b891614cd9565b6001610d04565b92506135398787838181106134d6576134d6614c24565b90506020028101906134e89190614c51565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505073ffffffffffffffffffffffffffffffffffffffff871692915050613b10565b82828151811061354b5761354b614c24565b6020908102919091010152600101613473565b50613567613b3c565b92505050612e37613c05565b5f61357c613ef1565b905090565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6135c8613a81565b6132d68282613efa565b6135da613a81565b805f5b81811015613650575f6135ee613eaa565b5f86868581811061360157613601614c24565b9050602002016020810190613616919061477f565b7fffffffff0000000000000000000000000000000000000000000000000000000016815260208101919091526040015f20556001016135dd565b50505050565b61365e613a81565b6132d68282613fe7565b5f54610100900460ff161580801561368657505f54600160ff909116105b8061369f5750303b15801561369f57505f5460ff166001145b61372b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401612e2e565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015613787575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61378f6140d5565b6137983361416b565b60016137a26141ea565b5580156132d6575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b613810613a81565b61310d816141f6565b61382233613e71565b6040518060400160405280600881526020017f49504f525f30313100000000000000000000000000000000000000000000000081525090613890576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2e9190614c12565b50805f5b818110156136505760016138a6613eaa565b5f8686858181106138b9576138b9614c24565b90506020020160208101906138ce919061477f565b7fffffffff0000000000000000000000000000000000000000000000000000000016815260208101919091526040015f2055600101613894565b5f7fffffffff00000000000000000000000000000000000000000000000000000000808316908416036139e75761393d613eaa565b7fffffffff0000000000000000000000000000000000000000000000000000000084165f9081526020918252604090819020548151808301909252600882527f49504f525f3031350000000000000000000000000000000000000000000000009282019290925290156139dd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2e9190614c12565b5060019050612e37565b505f92915050565b60026139f96141ea565b5460408051808201909152600881527f49504f525f30313600000000000000000000000000000000000000000000000060208201529103613a67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2e9190614c12565b506002613a726141ea565b55565b5f80612e37600c6142f2565b33613a8a614313565b5460408051808201909152600881527f49504f525f30313400000000000000000000000000000000000000000000000060208201529173ffffffffffffffffffffffffffffffffffffffff9091161461310d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2e9190614c12565b6060613b358383604051806060016040528060278152602001614e1d6027913961431e565b9392505050565b47801561310d576002613b4d6141ea565b540361310d576040515f90339083908381818185875af1925050503d805f8114613b92576040519150601f19603f3d011682016040523d82523d5f602084013e613b97565b606091505b50509050806132d657604080518082018252600881527f49504f525f303138000000000000000000000000000000000000000000000000602082015290517f08c379a0000000000000000000000000000000000000000000000000000000008152612e2e9190600401614c12565b6002613c0f6141ea565b5403612f40576001613a726141ea565b5f80612e3760016142f2565b5f613c34613c1f565b80547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155905061310d3361416b565b61310d613a81565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615613ca557613ca08361439f565b505050565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015613d2a575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252613d2791810190614d3e565b60015b613db6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f7420555550530000000000000000000000000000000000006064820152608401612e2e565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114613e65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c655555494400000000000000000000000000000000000000000000006064820152608401612e2e565b50613ca08383836144a9565b5f80613e7b6144cd565b73ffffffffffffffffffffffffffffffffffffffff9093165f9081526020939093525050604090205460ff1690565b5f80612e3760056142f2565b613ebf5f61416b565b5f613ec8613c1f565b80547fffffffffffffffffffffffff000000000000000000000000000000000000000016905550565b5f6135a4614313565b805f819003613f0857505050565b5f613f116144cd565b90505f5b82811015613fa1575f825f878785818110613f3257613f32614c24565b9050602002016020810190613f479190614638565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040015f2080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055600101613f15565b508383604051613fb2929190614d55565b604051908190038120907fe36d877f5755caee7e117ab1005d1acd030211e8a7ad495316fcaf980d0d054c905f90a250505050565b805f819003613ff557505050565b5f613ffe6144cd565b90505f5b8281101561408f576001825f87878581811061402057614020614c24565b90506020020160208101906140359190614638565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040015f2080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055600101614002565b5083836040516140a0929190614d55565b604051908190038120907f7802196382882a6ea8cc8c8a1d5f53efe52da8a8d8a0e6f6ce86662996f181df905f90a250505050565b5f54610100900460ff16612f40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401612e2e565b5f614174614313565b805473ffffffffffffffffffffffffffffffffffffffff8481167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117845560405193945091169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f80612e3760046142f2565b60408051808201909152600881527f49504f525f303030000000000000000000000000000000000000000000000000602082015273ffffffffffffffffffffffffffffffffffffffff8216614278576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2e9190614c12565b505f614282613c1f565b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081178255604051919250907f3ec7bb1d452f3c36260fa8ef678a597fd97574d8ec42f6dc98ffce3dbc91228f905f90a25050565b5f620f424082600c81111561430957614309614da1565b612e379190614dce565b5f80612e375f6142f2565b60605f808573ffffffffffffffffffffffffffffffffffffffff16856040516143479190614e06565b5f60405180830381855af49150503d805f811461437f576040519150601f19603f3d011682016040523d82523d5f602084013e614384565b606091505b5091509150614395868383876144d9565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81163b614443576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401612e2e565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6144b283614580565b5f825111806144be5750805b15613ca0576136508383613b10565b5f80612e3760036142f2565b6060831561456e5782515f036145675773ffffffffffffffffffffffffffffffffffffffff85163b614567576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401612e2e565b5081614578565b61457883836145cc565b949350505050565b6145898161439f565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b8151156145dc5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2e9190614c12565b803573ffffffffffffffffffffffffffffffffffffffff81168114614633575f80fd5b919050565b5f60208284031215614648575f80fd5b613b3582614610565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f806040838503121561468f575f80fd5b61469883614610565b9150602083013567ffffffffffffffff8111156146b3575f80fd5b8301601f810185136146c3575f80fd5b803567ffffffffffffffff8111156146dd576146dd614651565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160116810181811067ffffffffffffffff8211171561474957614749614651565b604052818152828201602001871015614760575f80fd5b816020840160208301375f602083830101528093505050509250929050565b5f6020828403121561478f575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114613b35575f80fd5b815173ffffffffffffffffffffffffffffffffffffffff16815261024081016020830151614804602084018273ffffffffffffffffffffffffffffffffffffffff169052565b50604083015161482c604084018273ffffffffffffffffffffffffffffffffffffffff169052565b506060830151614854606084018273ffffffffffffffffffffffffffffffffffffffff169052565b50608083015161487c608084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060a08301516148a460a084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c08301516148cc60c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060e08301516148f460e084018273ffffffffffffffffffffffffffffffffffffffff169052565b5061010083015161491e61010084018273ffffffffffffffffffffffffffffffffffffffff169052565b5061012083015161494861012084018273ffffffffffffffffffffffffffffffffffffffff169052565b5061014083015161497261014084018273ffffffffffffffffffffffffffffffffffffffff169052565b5061016083015161499c61016084018273ffffffffffffffffffffffffffffffffffffffff169052565b506101808301516149c661018084018273ffffffffffffffffffffffffffffffffffffffff169052565b506101a08301516149f06101a084018273ffffffffffffffffffffffffffffffffffffffff169052565b506101c0830151614a1a6101c084018273ffffffffffffffffffffffffffffffffffffffff169052565b506101e0830151614a446101e084018273ffffffffffffffffffffffffffffffffffffffff169052565b50610200830151614a6e61020084018273ffffffffffffffffffffffffffffffffffffffff169052565b50610220830151614a9861022084018273ffffffffffffffffffffffffffffffffffffffff169052565b5092915050565b5f8083601f840112614aaf575f80fd5b50813567ffffffffffffffff811115614ac6575f80fd5b6020830191508360208260051b8501011115614ae0575f80fd5b9250929050565b5f8060208385031215614af8575f80fd5b823567ffffffffffffffff811115614b0e575f80fd5b614b1a85828601614a9f565b90969095509350505050565b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b82811015614be7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0878603018452614bd2858351614b26565b94506020938401939190910190600101614b98565b50929695505050505050565b5f60208284031215614c03575f80fd5b81358015158114613b35575f80fd5b602081525f613b356020830184614b26565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614c84575f80fd5b83018035915067ffffffffffffffff821115614c9e575f80fd5b602001915036819003821315614ae0575f80fd5b5f8085851115614cc0575f80fd5b83861115614ccc575f80fd5b5050820193919092039150565b80357fffffffff000000000000000000000000000000000000000000000000000000008116906004841015614a98577fffffffff00000000000000000000000000000000000000000000000000000000808560040360031b1b82161691505092915050565b5f60208284031215614d4e575f80fd5b5051919050565b5f8184825b85811015614d965773ffffffffffffffffffffffffffffffffffffffff614d8083614610565b1683526020928301929190910190600101614d5a565b509095945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b80820180821115612e37577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f82518060208501845e5f92019182525091905056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e8cb1f97061bc71b2fc3c58651e3aa67a470d24cba7e5e2a311cdd748b652f1364736f6c634300081a0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000476c44e60a377c1d23877e9dd2955c384b2dcd8c0000000000000000000000001f44c5ada019cbb0729e277775877ccdb940e04a000000000000000000000000ce96800a16791d68ee96706915ead714d67db70d0000000000000000000000001d4c4c07e34a6b43f104204d243aae084d5f6e090000000000000000000000004ef45eccc64e4bb36b9c46b9ad353855a48016d100000000000000000000000011a02a63e9142ed929b9fd95357762fc7bab56f90000000000000000000000009a9f60349e2da59250433276b3ef474f1f69f8e8000000000000000000000000735b3fbc2ea7fce1b4e17d9e50eceafe4e6fc3d9000000000000000000000000066cbd24d8285e25cb38222ea669735bdebbaac2000000000000000000000000912ae5d95bd86f4ae6e580a0fa14a124c998f337000000000000000000000000b64f71300626499d3d9f8e87bfa34f50c75f0470000000000000000000000000769d54d25dd9da2159fa690e67b27484eeb39e980000000000000000000000005a4fc8f98ca356b7e957d18c155bc62e32d21ec3000000000000000000000000d3486d81d52b52125b9fb1ae9d674645ece665ac0000000000000000000000003790383f8685b439391dc1bc56f7b3f82236f6c7000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe84000000000000000000000000cd5fe23c85820f7b72d0926fc9b05b43e359b7ee00000000000000000000000059d9356e565ab3a36dd77763fc0d87feaf85508c

-----Decoded View---------------
Arg [0] : deployedContracts (tuple):
Arg [1] : ammSwapsLens (address): 0x476C44E60a377C1D23877E9Dd2955C384b2DCD8c
Arg [2] : ammPoolsLens (address): 0x1F44C5ADA019CbB0729e277775877cCdb940E04a
Arg [3] : ammPoolsLensBaseV1 (address): 0xcE96800a16791D68ee96706915eAd714d67Db70D
Arg [4] : assetManagementLens (address): 0x1d4c4C07e34a6B43F104204D243aAE084D5F6e09
Arg [5] : ammOpenSwapService (address): 0x4EF45ECcc64E4Bb36b9C46B9AD353855A48016d1
Arg [6] : ammCloseSwapServiceUsdt (address): 0x11a02a63E9142ED929B9Fd95357762Fc7bab56F9
Arg [7] : ammCloseSwapServiceUsdc (address): 0x9A9f60349E2dA59250433276B3eF474F1f69f8E8
Arg [8] : ammCloseSwapServiceDai (address): 0x735B3fBc2EA7fcE1b4E17D9e50eCEAFe4e6fc3d9
Arg [9] : ammCloseSwapLens (address): 0x066Cbd24d8285e25cb38222EA669735BdeBbAaC2
Arg [10] : ammPoolsService (address): 0x912AE5D95BD86F4aE6E580a0fA14A124C998f337
Arg [11] : ammGovernanceService (address): 0xB64F71300626499D3D9f8E87bfA34F50c75f0470
Arg [12] : liquidityMiningLens (address): 0x769d54D25DD9da2159Fa690e67B27484eeB39e98
Arg [13] : powerTokenLens (address): 0x5a4fc8F98CA356B7E957d18c155bc62E32D21EC3
Arg [14] : flowService (address): 0xD3486D81D52B52125B9fb1AE9d674645ECe665Ac
Arg [15] : stakeService (address): 0x3790383f8685b439391dC1BC56F7B3F82236f6c7
Arg [16] : stEth (address): 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84
Arg [17] : weEth (address): 0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee
Arg [18] : usdm (address): 0x59D9356E565Ab3A36dD77763Fc0d87fEaf85508C


-----Encoded View---------------
18 Constructor Arguments found :
Arg [0] : 000000000000000000000000476c44e60a377c1d23877e9dd2955c384b2dcd8c
Arg [1] : 0000000000000000000000001f44c5ada019cbb0729e277775877ccdb940e04a
Arg [2] : 000000000000000000000000ce96800a16791d68ee96706915ead714d67db70d
Arg [3] : 0000000000000000000000001d4c4c07e34a6b43f104204d243aae084d5f6e09
Arg [4] : 0000000000000000000000004ef45eccc64e4bb36b9c46b9ad353855a48016d1
Arg [5] : 00000000000000000000000011a02a63e9142ed929b9fd95357762fc7bab56f9
Arg [6] : 0000000000000000000000009a9f60349e2da59250433276b3ef474f1f69f8e8
Arg [7] : 000000000000000000000000735b3fbc2ea7fce1b4e17d9e50eceafe4e6fc3d9
Arg [8] : 000000000000000000000000066cbd24d8285e25cb38222ea669735bdebbaac2
Arg [9] : 000000000000000000000000912ae5d95bd86f4ae6e580a0fa14a124c998f337
Arg [10] : 000000000000000000000000b64f71300626499d3d9f8e87bfa34f50c75f0470
Arg [11] : 000000000000000000000000769d54d25dd9da2159fa690e67b27484eeb39e98
Arg [12] : 0000000000000000000000005a4fc8f98ca356b7e957d18c155bc62e32d21ec3
Arg [13] : 000000000000000000000000d3486d81d52b52125b9fb1ae9d674645ece665ac
Arg [14] : 0000000000000000000000003790383f8685b439391dc1bc56f7b3f82236f6c7
Arg [15] : 000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe84
Arg [16] : 000000000000000000000000cd5fe23c85820f7b72d0926fc9b05b43e359b7ee
Arg [17] : 00000000000000000000000059d9356e565ab3a36dd77763fc0d87feaf85508c


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.