{"file_path":"project/contracts/core/PoolManager.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.26;\n\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { EnumerableSet } from \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\n\nimport { ICreditNote } from \"../interfaces/ICreditNote.sol\";\nimport { IFxUSDRegeneracy } from \"../interfaces/IFxUSDRegeneracy.sol\";\nimport { ILongPoolManager } from \"../interfaces/ILongPoolManager.sol\";\nimport { ILongPool } from \"../interfaces/ILongPool.sol\";\nimport { IPoolConfiguration } from \"../interfaces/IPoolConfiguration.sol\";\nimport { IPoolManager } from \"../interfaces/IPoolManager.sol\";\nimport { IShortPool } from \"../interfaces/IShortPool.sol\";\nimport { IReservePool } from \"../interfaces/IReservePool.sol\";\nimport { IFxUSDBasePool } from \"../interfaces/IFxUSDBasePool.sol\";\nimport { IRateProvider } from \"../rate-provider/interfaces/IRateProvider.sol\";\nimport { ISmartWalletChecker } from \"../voting-escrow/interfaces/ISmartWalletChecker.sol\";\nimport { WordCodec } from \"../common/codec/WordCodec.sol\";\nimport { AssetManagement } from \"../fund/AssetManagement.sol\";\nimport { FlashLoans } from \"./FlashLoans.sol\";\nimport { ProtocolFees } from \"./ProtocolFees.sol\";\n\ncontract PoolManager is ProtocolFees, FlashLoans, AssetManagement, ILongPoolManager {\n  using EnumerableSet for EnumerableSet.AddressSet;\n  using SafeERC20 for IERC20;\n  using WordCodec for bytes32;\n\n  /**********\n   * Errors *\n   **********/\n\n  error ErrorCollateralExceedCapacity();\n\n  error ErrorDebtExceedCapacity();\n\n  error ErrorPoolNotRegistered();\n\n  error ErrorInvalidPool();\n\n  error ErrorCallerNotFxUSDSave();\n\n  error ErrorRedeemExceedBalance();\n\n  error ErrorInsufficientRedeemedCollateral();\n\n  error ErrorBorrowExceedCapacity();\n\n  error ErrorCallerNotCounterparty();\n\n  error ErrorInvalidLongShortPair();\n\n  error ErrorStableRepayNotAllowed();\n\n  error ErrorInvalidOperation();\n\n  error ErrorRedeemDebtsTooSmall();\n\n  error ErrorRebalanceDebtsTooSmall();\n\n  error ErrorRedeemNotAllowed();\n\n  error ErrorLiquidateDebtsTooSmall();\n\n  error ErrorTopLevelCall();\n\n  /*************\n   * Constants *\n   *************/\n\n  /// @dev The role for emergency operations.\n  bytes32 public constant EMERGENCY_ROLE = keccak256(\"EMERGENCY_ROLE\");\n\n  /// @dev The role for debt reducer.\n  bytes32 public constant DEBT_REDUCER_ROLE = keccak256(\"DEBT_REDUCER_ROLE\");\n\n  /// @dev The role for harvester\n  bytes32 public constant HARVESTER_ROLE = keccak256(\"HARVESTER_ROLE\");\n\n  /// @dev The key for pool rewards treasury.\n  bytes32 private constant POOL_REWARDS_TREASURY_KEY = keccak256(\"PoolRewardsTreasury\");\n\n  /// @dev The key for pool funding treasury.\n  bytes32 private constant POOL_FUNDING_TREASURY_KEY = keccak256(\"PoolFundingTreasury\");\n\n  /// @dev The precision for token rate.\n  uint256 internal constant PRECISION = 1e18;\n\n  /// @dev The precision for token rate.\n  int256 internal constant PRECISION_I256 = 1e18;\n\n  uint256 private constant COLLATERAL_CAPACITY_OFFSET = 0;\n  uint256 private constant COLLATERAL_BALANCE_OFFSET = 85;\n  uint256 private constant RAW_COLLATERAL_BALANCE_OFFSET = 170;\n  uint256 private constant COLLATERAL_DATA_BITS = 85;\n  uint256 private constant RAW_COLLATERAL_DATA_BITS = 86;\n\n  uint256 private constant DEBT_CAPACITY_OFFSET = 0;\n  uint256 private constant DEBT_BALANCE_OFFSET = 96;\n  uint256 private constant DEBT_DATA_BITS = 96;\n\n  uint256 private constant MIN_REDEEM_DEBTS = 100 ether;\n\n  uint256 private constant MIN_REBALANCE_DEBTS = 1 ether;\n\n  uint256 private constant MIN_LIQUIDATE_DEBTS = 1 ether;\n\n  /***********************\n   * Immutable Variables *\n   ***********************/\n\n  /// @inheritdoc IPoolManager\n  address public immutable fxUSD;\n\n  /// @inheritdoc IPoolManager\n  address public immutable counterparty;\n\n  /// @inheritdoc IPoolManager\n  address public immutable configuration;\n\n  /// @inheritdoc ILongPoolManager\n  address public immutable fxBASE;\n\n  /// @notice The address of smart wallet whitelist.\n  address public immutable whitelist;\n\n  /***********\n   * Structs *\n   ***********/\n\n  /// @dev The struct for pool information.\n  /// @param collateralData The data for collateral.\n  ///   ```text\n  ///   * Field                     Bits    Index       Comments\n  ///   * collateral capacity       85      0           The maximum allowed amount of collateral tokens.\n  ///   * collateral balance        85      85          The amount of collateral tokens deposited.\n  ///   * raw collateral balance    86      170         The amount of raw collateral tokens (without token rate) managed in pool.\n  ///   ```\n  /// @param debtData The data for debt.\n  ///   ```text\n  ///   * Field             Bits    Index       Comments\n  ///   * debt capacity     96      0           The maximum allowed amount of debt tokens.\n  ///   * debt balance      96      96          The amount of debt tokens borrowed.\n  ///   * reserved          64      192         Reserved data.\n  ///   ```\n  struct PoolStruct {\n    bytes32 collateralData;\n    bytes32 debtData;\n  }\n\n  /// @dev The struct for token rate information.\n  /// @param scalar The token scalar to reach 18 decimals.\n  /// @param rateProvider The address of token rate provider.\n  struct TokenRate {\n    uint96 scalar;\n    address rateProvider;\n  }\n\n  /// @dev Memory variables for liquidate or rebalance.\n  /// @param stablePrice The USD price of stable token (with scalar).\n  /// @param scalingFactor The scaling factor for collateral token.\n  /// @param collateralToken The address of collateral token.\n  /// @param rawColls The amount of raw collateral tokens liquidated or rebalanced, including bonus.\n  /// @param bonusRawColls The amount of raw collateral tokens used as bonus.\n  /// @param rawDebts The amount of raw debt tokens liquidated or rebalanced.\n  struct LiquidateOrRebalanceMemoryVar {\n    uint256 stablePrice;\n    uint256 scalingFactor;\n    address collateralToken;\n    uint256 rawColls;\n    uint256 bonusRawColls;\n    uint256 rawDebts;\n  }\n\n  struct OperationMemoryVar {\n    uint256 stablePrice;\n    uint256 poolSupplyFeeRatio;\n    uint256 poolWithdrawFeeRatio;\n    uint256 poolBorrowFeeRatio;\n    uint256 poolRepayFeeRatio;\n    address referral;\n    uint256 referralSupplyFeeRatio;\n    uint256 referralWithdrawFeeRatio;\n    uint256 referralBorrowFeeRatio;\n    uint256 referralRepayFeeRatio;\n  }\n\n  /*********************\n   * Storage Variables *\n   *********************/\n\n  /// @dev The list of registered pools.\n  EnumerableSet.AddressSet private pools;\n\n  /// @notice Mapping to pool address to pool struct.\n  mapping(address => PoolStruct) private poolInfo;\n\n  /// @notice Mapping from pool address to rewards splitter.\n  /// @custom:deprecated This field is no longer used.\n  mapping(address => address) public rewardSplitter;\n\n  /// @notice Mapping from token address to token rate struct.\n  mapping(address => TokenRate) public tokenRates;\n\n  /// @notice The threshold for permissioned liquidate or rebalance.\n  uint256 public permissionedLiquidationThreshold;\n\n  /// @notice Mapping from pool address to corresponding short allocation.\n  mapping(address => uint256) public shortBorrowCapacityRatio;\n\n  /*************\n   * Modifiers *\n   *************/\n\n  modifier onlyRegisteredPool(address pool) {\n    if (!pools.contains(pool)) revert ErrorPoolNotRegistered();\n    _;\n  }\n\n  modifier onlyFxUSDSave() {\n    if (_msgSender() != fxBASE) {\n      // allow permissonless rebalance or liquidate when insufficient fxUSD/USDC in fxBASE.\n      // we use total supply to estimate the amount of fxUSD/USDC in fxBASE.\n      if (IERC20(fxBASE).totalSupply() >= permissionedLiquidationThreshold) {\n        revert ErrorCallerNotFxUSDSave();\n      }\n    }\n    _;\n  }\n\n  modifier onlyCounterparty() {\n    if (counterparty != _msgSender()) {\n      revert ErrorCallerNotCounterparty();\n    }\n    _;\n  }\n\n  modifier onlyTopLevelCall() {\n    uint256 codesize = msg.sender.code.length;\n    if (whitelist != address(0) && (codesize > 0 || msg.sender != tx.origin)) {\n      if (!ISmartWalletChecker(whitelist).check(msg.sender)) {\n        revert ErrorTopLevelCall();\n      }\n    }\n    _;\n  }\n\n  modifier lock() {\n    IPoolConfiguration(configuration).lock(address(this), msg.sig);\n    _;\n  }\n\n  /***************\n   * Constructor *\n   ***************/\n\n  constructor(address _fxUSD, address _fxBASE, address _counterparty, address _configuration, address _whitelist) {\n    fxUSD = _fxUSD;\n    fxBASE = _fxBASE;\n    counterparty = _counterparty;\n    configuration = _configuration;\n    whitelist = _whitelist;\n  }\n\n  function initialize(\n    address admin,\n    uint256 _expenseRatio,\n    uint256 _harvesterRatio,\n    uint256 _flashLoanFeeRatio,\n    address _treasury,\n    address _revenuePool,\n    address _reservePool\n  ) external initializer {\n    // comment out to reduce code size, since these functions are no-op for now.\n    // __Context_init();\n    // __AccessControl_init();\n    // __ERC165_init();\n\n    _grantRole(DEFAULT_ADMIN_ROLE, admin);\n\n    __ProtocolFees_init(_expenseRatio, _harvesterRatio, _flashLoanFeeRatio, _treasury, _revenuePool, _reservePool);\n    __FlashLoans_init();\n\n    // default 10000 fxUSD\n    // _updateThreshold(10000 ether);\n  }\n\n  /*\n  function initializeV2(address pool) external onlyRegisteredPool(pool) reinitializer(2) {\n    // fix state of pool\n    address collateralToken = ILongPool(pool).collateralToken();\n    uint256 scalingFactor = _getTokenScalingFactor(collateralToken);\n    uint256 rawCollaterals = ILongPool(pool).getTotalRawCollaterals();\n    uint256 collaterals = _scaleDown(rawCollaterals, scalingFactor);\n    bytes32 data = poolInfo[pool].collateralData;\n    data = data.insertUint(collaterals, COLLATERAL_BALANCE_OFFSET, COLLATERAL_DATA_BITS);\n    poolInfo[pool].collateralData = data.insertUint(\n      rawCollaterals,\n      RAW_COLLATERAL_BALANCE_OFFSET,\n      RAW_COLLATERAL_DATA_BITS\n    );\n  }\n  */\n\n  /*************************\n   * Public View Functions *\n   *************************/\n\n  /// @notice Return the pool information.\n  /// @param pool The address of pool to query.\n  /// @return collateralCapacity The maximum allowed amount of collateral tokens.\n  /// @return collateralBalance The amount of collateral tokens deposited.\n  /// @return rawCollateral The amount of raw collateral tokens deposited.\n  /// @return debtCapacity The maximum allowed amount of debt tokens.\n  /// @return debtBalance The amount of debt tokens borrowed.\n  function getPoolInfo(\n    address pool\n  )\n    external\n    view\n    returns (\n      uint256 collateralCapacity,\n      uint256 collateralBalance,\n      uint256 rawCollateral,\n      uint256 debtCapacity,\n      uint256 debtBalance\n    )\n  {\n    bytes32 data = poolInfo[pool].collateralData;\n    collateralCapacity = data.decodeUint(COLLATERAL_CAPACITY_OFFSET, COLLATERAL_DATA_BITS);\n    collateralBalance = data.decodeUint(COLLATERAL_BALANCE_OFFSET, COLLATERAL_DATA_BITS);\n    rawCollateral = data.decodeUint(RAW_COLLATERAL_BALANCE_OFFSET, RAW_COLLATERAL_DATA_BITS);\n    data = poolInfo[pool].debtData;\n    debtCapacity = data.decodeUint(DEBT_CAPACITY_OFFSET, DEBT_DATA_BITS);\n    debtBalance = data.decodeUint(DEBT_BALANCE_OFFSET, DEBT_DATA_BITS);\n  }\n\n  /// @inheritdoc IPoolManager\n  function getTokenScalingFactor(address token) external view returns (uint256) {\n    return _getTokenScalingFactor(token);\n  }\n\n  /****************************\n   * Public Mutated Functions *\n   ****************************/\n\n  /// @inheritdoc IPoolManager\n  function operate(address pool, uint256 positionId, int256 newColl, int256 newDebt) external returns (uint256) {\n    return operate(pool, positionId, newColl, newDebt, false);\n  }\n\n  /// @inheritdoc ILongPoolManager\n  function operate(\n    address pool,\n    uint256 positionId,\n    int256 newColl,\n    int256 newDebt,\n    bool useStable\n  ) public onlyRegisteredPool(pool) nonReentrant whenNotPaused onlyTopLevelCall lock returns (uint256) {\n    OperationMemoryVar memory vars;\n\n    if (useStable) {\n      if (!IPoolConfiguration(configuration).isStableRepayAllowed()) revert ErrorStableRepayNotAllowed();\n      if (newColl > 0 || newDebt >= 0 || positionId == 0) revert ErrorInvalidOperation();\n      vars.stablePrice = IFxUSDBasePool(fxBASE).getStableTokenPriceWithScale();\n    }\n\n    address collateralToken = ILongPool(pool).collateralToken();\n    uint256 scalingFactor = _getTokenScalingFactor(collateralToken);\n\n    (\n      vars.poolSupplyFeeRatio,\n      vars.poolWithdrawFeeRatio,\n      vars.poolBorrowFeeRatio,\n      vars.poolRepayFeeRatio\n    ) = IPoolConfiguration(configuration).getPoolFeeRatio(pool, _msgSender());\n\n    // in case of supply, we deduct the fee here first and transfer the collateral to pool.\n    if (newColl > 0) {\n      newColl = int256(_handleSupply(pool, collateralToken, uint256(newColl), vars.poolSupplyFeeRatio));\n    }\n\n    int256 newRawColl = newColl;\n    int256 newRawDebt = newDebt;\n    if (newRawColl != type(int256).min) {\n      newRawColl = _scaleUp(newRawColl, scalingFactor);\n    }\n    if (useStable && newRawDebt != type(int256).min) {\n      newRawDebt = _scaleUp(newRawDebt, vars.stablePrice);\n    }\n\n    // @dev the `protocolFees` is deprecated, it is always zero now.\n    (positionId, newRawColl, newRawDebt, ) = ILongPool(pool).operate(positionId, newRawColl, newRawDebt, _msgSender());\n\n    newColl = _scaleDown(newRawColl, scalingFactor);\n    _changePoolDebts(pool, newRawDebt);\n    if (newRawColl > 0) {\n      _changePoolCollateral(pool, newColl, newRawColl);\n    } else if (newRawColl < 0) {\n      _handleWithdraw(pool, collateralToken, uint256(-newColl), uint256(-newRawColl), vars.poolWithdrawFeeRatio);\n    }\n\n    if (newRawDebt > 0) {\n      _handleBorrow(uint256(newRawDebt), vars.poolBorrowFeeRatio);\n    } else if (newRawDebt < 0) {\n      _handleRepay(uint256(-newRawDebt), vars.poolRepayFeeRatio, vars.stablePrice);\n    }\n\n    emit Operate(pool, positionId, newColl, newRawDebt, 0);\n\n    return positionId;\n  }\n\n  /// @inheritdoc IPoolManager\n  function redeem(\n    address pool,\n    uint256 debts,\n    uint256 minColls\n  ) external onlyRegisteredPool(pool) nonReentrant whenNotPaused lock returns (uint256 actualDebts, uint256 colls) {\n    if (debts > IERC20(fxUSD).balanceOf(_msgSender())) {\n      revert ErrorRedeemExceedBalance();\n    }\n    if (debts < MIN_REDEEM_DEBTS) {\n      revert ErrorRedeemDebtsTooSmall();\n    }\n    if (!IPoolConfiguration(configuration).isRedeemAllowed()) {\n      revert ErrorRedeemNotAllowed();\n    }\n\n    uint256 rawColls;\n    (actualDebts, rawColls) = ILongPool(pool).redeem(debts);\n    debts = actualDebts;\n\n    address collateralToken = ILongPool(pool).collateralToken();\n    uint256 scalingFactor = _getTokenScalingFactor(collateralToken);\n    colls = _scaleDown(rawColls, scalingFactor);\n\n    _changePoolCollateral(pool, -int256(colls), -int256(rawColls));\n    _changePoolDebts(pool, -int256(debts));\n\n    // @dev use unchecked to reduce code size and gas\n    uint256 protocolFees;\n    unchecked {\n      protocolFees = (colls * getRedeemFeeRatio()) / FEE_PRECISION;\n      _accumulatePoolMiscFee(pool, protocolFees);\n      colls -= protocolFees;\n    }\n    if (colls < minColls) revert ErrorInsufficientRedeemedCollateral();\n\n    _transferCollateralOut(pool, collateralToken, colls, _msgSender());\n    IFxUSDRegeneracy(fxUSD).burn(_msgSender(), debts);\n\n    emit Redeem(pool, colls, debts, protocolFees);\n  }\n\n  /// @inheritdoc ILongPoolManager\n  function rebalance(\n    address pool,\n    address receiver,\n    int16 tick,\n    uint256 maxFxUSD,\n    uint256 maxStable\n  )\n    external\n    onlyRegisteredPool(pool)\n    nonReentrant\n    whenNotPaused\n    onlyFxUSDSave\n    returns (uint256 colls, uint256 fxUSDUsed, uint256 stableUsed)\n  {\n    LiquidateOrRebalanceMemoryVar memory op = _beforeRebalanceOrLiquidate(pool);\n    // @dev use unchecked to reduce code size and gas\n    unchecked {\n      uint256 maxRawDebts = maxFxUSD + _scaleUp(maxStable, op.stablePrice);\n      if (maxRawDebts < MIN_REBALANCE_DEBTS) {\n        revert ErrorRebalanceDebtsTooSmall();\n      }\n      ILongPool.RebalanceResult memory result = ILongPool(pool).rebalance(tick, maxRawDebts);\n      op.rawColls = result.rawColls + result.bonusRawColls;\n      op.bonusRawColls = result.bonusRawColls;\n      op.rawDebts = result.rawDebts;\n    }\n    (colls, fxUSDUsed, stableUsed) = _afterRebalanceOrLiquidate(pool, maxFxUSD, op, receiver);\n\n    emit RebalanceTick(pool, tick, colls, fxUSDUsed, stableUsed);\n  }\n\n  /// @inheritdoc ILongPoolManager\n  function rebalance(\n    address pool,\n    address receiver,\n    uint256 maxFxUSD,\n    uint256 maxStable\n  )\n    external\n    onlyRegisteredPool(pool)\n    nonReentrant\n    whenNotPaused\n    onlyFxUSDSave\n    lock\n    returns (uint256 colls, uint256 fxUSDUsed, uint256 stableUsed)\n  {\n    LiquidateOrRebalanceMemoryVar memory op = _beforeRebalanceOrLiquidate(pool);\n    // @dev use unchecked to reduce code size and gas\n    unchecked {\n      uint256 maxRawDebts = maxFxUSD + _scaleUp(maxStable, op.stablePrice);\n      if (maxRawDebts < MIN_REBALANCE_DEBTS) {\n        revert ErrorRebalanceDebtsTooSmall();\n      }\n      ILongPool.RebalanceResult memory result = ILongPool(pool).rebalance(maxRawDebts);\n      op.rawColls = result.rawColls + result.bonusRawColls;\n      op.bonusRawColls = result.bonusRawColls;\n      op.rawDebts = result.rawDebts;\n    }\n    (colls, fxUSDUsed, stableUsed) = _afterRebalanceOrLiquidate(pool, maxFxUSD, op, receiver);\n\n    emit Rebalance(pool, colls, fxUSDUsed, stableUsed);\n  }\n\n  /// @inheritdoc ILongPoolManager\n  function liquidate(\n    address pool,\n    address receiver,\n    uint256 maxFxUSD,\n    uint256 maxStable\n  )\n    external\n    onlyRegisteredPool(pool)\n    nonReentrant\n    whenNotPaused\n    onlyFxUSDSave\n    lock\n    returns (uint256 colls, uint256 fxUSDUsed, uint256 stableUsed)\n  {\n    LiquidateOrRebalanceMemoryVar memory op = _beforeRebalanceOrLiquidate(pool);\n    uint256 maxRawDebts = maxFxUSD + _scaleUp(maxStable, op.stablePrice);\n    if (maxRawDebts < MIN_LIQUIDATE_DEBTS) {\n      revert ErrorLiquidateDebtsTooSmall();\n    }\n    {\n      ILongPool.LiquidateResult memory result;\n      uint256 reservedRawColls = IReservePool(reservePool).getBalance(op.collateralToken);\n      reservedRawColls = _scaleUp(reservedRawColls, op.scalingFactor);\n\n      // @dev use unchecked to reduce code size and gas\n      unchecked {\n        result = ILongPool(pool).liquidate(maxRawDebts, reservedRawColls);\n        op.rawColls = result.rawColls + result.bonusRawColls;\n        op.bonusRawColls = result.bonusRawColls;\n        op.rawDebts = result.rawDebts;\n      }\n\n      // take bonus or shortfall from reserve pool\n      uint256 bonusFromReserve = result.bonusFromReserve;\n      if (bonusFromReserve > 0) {\n        bonusFromReserve = _scaleDown(result.bonusFromReserve, op.scalingFactor);\n        IReservePool(reservePool).requestBonus(ILongPool(pool).collateralToken(), address(this), bonusFromReserve);\n\n        // increase pool reserve first\n        _changePoolCollateral(pool, int256(bonusFromReserve), int256(result.bonusFromReserve));\n      }\n    }\n\n    (colls, fxUSDUsed, stableUsed) = _afterRebalanceOrLiquidate(pool, maxFxUSD, op, receiver);\n\n    emit Liquidate(pool, colls, fxUSDUsed, stableUsed);\n  }\n\n  /// @inheritdoc IPoolManager\n  function harvest(\n    address pool\n  )\n    external\n    onlyRegisteredPool(pool)\n    onlyRole(HARVESTER_ROLE)\n    nonReentrant\n    returns (uint256 amountRewards, uint256 amountFunding)\n  {\n    address collateralToken = ILongPool(pool).collateralToken();\n    uint256 scalingFactor = _getTokenScalingFactor(collateralToken);\n\n    uint256 collateralRecorded;\n    uint256 rawCollateralRecorded;\n    {\n      bytes32 data = poolInfo[pool].collateralData;\n      collateralRecorded = data.decodeUint(COLLATERAL_BALANCE_OFFSET, COLLATERAL_DATA_BITS);\n      rawCollateralRecorded = data.decodeUint(RAW_COLLATERAL_BALANCE_OFFSET, RAW_COLLATERAL_DATA_BITS);\n    }\n    uint256 performanceFee;\n    uint256 harvestBounty;\n    // compute funding\n    uint256 rawCollateral = ILongPool(pool).getTotalRawCollaterals();\n    if (rawCollateralRecorded > rawCollateral) {\n      unchecked {\n        amountFunding = _scaleDown(rawCollateralRecorded - rawCollateral, scalingFactor);\n        _changePoolCollateral(pool, -int256(amountFunding), -int256(rawCollateralRecorded - rawCollateral));\n\n        performanceFee = (getFundingExpenseRatio() * amountFunding) / FEE_PRECISION;\n        harvestBounty = (getHarvesterRatio() * amountFunding) / FEE_PRECISION;\n        amountFunding -= harvestBounty + performanceFee;\n      }\n      _transferCollateralOut(\n        pool,\n        collateralToken,\n        amountFunding,\n        IPoolConfiguration(configuration).registry(POOL_FUNDING_TREASURY_KEY)\n      );\n\n      // recorded data changed, update local cache\n      {\n        bytes32 data = poolInfo[pool].collateralData;\n        collateralRecorded = data.decodeUint(COLLATERAL_BALANCE_OFFSET, COLLATERAL_DATA_BITS);\n        rawCollateralRecorded = data.decodeUint(RAW_COLLATERAL_BALANCE_OFFSET, RAW_COLLATERAL_DATA_BITS);\n      }\n    }\n    // compute rewards\n    rawCollateral = _scaleUp(collateralRecorded, scalingFactor);\n    if (rawCollateral > rawCollateralRecorded) {\n      unchecked {\n        amountRewards = _scaleDown(rawCollateral - rawCollateralRecorded, scalingFactor);\n        _changePoolCollateral(pool, -int256(amountRewards), 0);\n\n        {\n          uint256 performanceFeeRewards = (getRewardsExpenseRatio() * amountRewards) / FEE_PRECISION;\n          uint256 harvestBountyRewards = (getHarvesterRatio() * amountRewards) / FEE_PRECISION;\n          amountRewards -= harvestBountyRewards + performanceFeeRewards;\n          performanceFee += performanceFeeRewards;\n          harvestBounty += harvestBountyRewards;\n        }\n\n        _transferCollateralOut(\n          pool,\n          collateralToken,\n          amountRewards,\n          IPoolConfiguration(configuration).registry(POOL_REWARDS_TREASURY_KEY)\n        );\n      }\n    }\n\n    // transfer performance fee to treasury\n    if (performanceFee > 0) {\n      _transferCollateralOut(pool, collateralToken, performanceFee, treasury);\n    }\n    // transfer various fees to revenue pool\n    _takeAccumulatedPoolFee(pool);\n    // transfer harvest bounty\n    if (harvestBounty > 0) {\n      _transferCollateralOut(pool, collateralToken, harvestBounty, _msgSender());\n    }\n    emit Harvest(_msgSender(), pool, amountRewards, amountFunding, performanceFee, harvestBounty);\n  }\n\n  /// @inheritdoc ILongPoolManager\n  function borrow(\n    address longPool,\n    address shortPool,\n    uint256 amount\n  ) external onlyCounterparty onlyRegisteredPool(longPool) nonReentrant {\n    address creditNote = IShortPool(shortPool).creditNote();\n    address collateralToken = ILongPool(longPool).collateralToken();\n    uint256 scalingFactor = _getTokenScalingFactor(collateralToken);\n    {\n      uint256 rawCollateral = ILongPool(longPool).getTotalRawCollaterals();\n      uint256 collateral = _scaleDown(rawCollateral, scalingFactor);\n      uint256 borrowed = IERC20(creditNote).totalSupply();\n      if ((collateral * shortBorrowCapacityRatio[longPool]) / PRECISION < borrowed + amount) {\n        revert ErrorBorrowExceedCapacity();\n      }\n    }\n\n    _transferOut(collateralToken, amount, counterparty);\n    ICreditNote(creditNote).mint(address(this), amount);\n  }\n\n  /// @inheritdoc ILongPoolManager\n  function repay(\n    address longPool,\n    address shortPool,\n    uint256 amount\n  ) external onlyCounterparty onlyRegisteredPool(longPool) nonReentrant {\n    address collateralToken = ILongPool(longPool).collateralToken();\n    _transferFrom(collateralToken, counterparty, address(this), amount);\n    ICreditNote(IShortPool(shortPool).creditNote()).burn(address(this), amount);\n  }\n\n  /// @inheritdoc ILongPoolManager\n  function repayByCreditNote(\n    address longPool,\n    address shortPool,\n    uint256 amount\n  ) external onlyCounterparty onlyRegisteredPool(longPool) nonReentrant {\n    ICreditNote(IShortPool(shortPool).creditNote()).burn(counterparty, amount);\n  }\n\n  /// @inheritdoc ILongPoolManager\n  function redeemForSettle(\n    address pool,\n    uint256 debts\n  ) external onlyCounterparty onlyRegisteredPool(pool) nonReentrant returns (uint256 colls) {\n    address collateralToken = ILongPool(pool).collateralToken();\n    uint256 scalingFactor = _getTokenScalingFactor(collateralToken);\n\n    // allow tick not moved to make sure all fxusd is redeemed\n    (, uint256 rawColls) = ILongPool(pool).redeem(debts, true);\n    colls = _scaleDown(rawColls, scalingFactor);\n\n    _changePoolCollateral(pool, -int256(colls), -int256(rawColls));\n\n    // burn fxUSD, the caller is the short pool manager\n    IFxUSDRegeneracy(fxUSD).burn(_msgSender(), debts);\n    _changePoolDebts(pool, -int256(debts));\n\n    emit RedeemForSettle(pool, colls, debts);\n  }\n\n  /// @inheritdoc ILongPoolManager\n  function settleShortPool(\n    address longPool,\n    address shortPool,\n    uint256 shortfall\n  ) external onlyCounterparty onlyRegisteredPool(longPool) nonReentrant {\n    address collateralToken = ILongPool(longPool).collateralToken();\n    uint256 scalingFactor = _getTokenScalingFactor(collateralToken);\n    uint256 rawShortfall = _scaleUp(shortfall, scalingFactor);\n\n    // reduce collateral in long pool\n    ILongPool(longPool).reduceCollateral(rawShortfall);\n    _changePoolCollateral(longPool, -int256(shortfall), -int256(rawShortfall));\n\n    // burn all credit note tokens in pool manager.\n    // for tokens outside of pool manager, the short pool is killed, the tokens are useless.\n    address creditNote = IShortPool(shortPool).creditNote();\n    uint256 creditNoteAmount = IERC20(creditNote).balanceOf(address(this));\n    if (creditNoteAmount > 0) {\n      ICreditNote(creditNote).burn(address(this), creditNoteAmount);\n    }\n  }\n\n  /// @inheritdoc IPoolManager\n  /// @dev This is a risky operation, only allowed by whitelisted caller.\n  function reduceDebt(\n    address pool,\n    uint256 amount\n  ) external onlyRegisteredPool(pool) onlyRole(DEBT_REDUCER_ROLE) nonReentrant {\n    IFxUSDRegeneracy(fxUSD).burn(_msgSender(), amount);\n    ILongPool(pool).reduceDebt(amount);\n\n    _changePoolDebts(pool, -int256(amount));\n\n    emit ReduceDebt(pool, amount);\n  }\n\n  /************************\n   * Restricted Functions *\n   ************************/\n\n  /// @notice Pause or unpause the system.\n  /// @param status The pause status to update.\n  function setPause(bool status) external onlyRole(EMERGENCY_ROLE) {\n    if (status) _pause();\n    else _unpause();\n  }\n\n  /// @notice Register a new pool with reward splitter.\n  /// @param pool The address of pool.\n  /// @param collateralCapacity The capacity for collateral token.\n  /// @param debtCapacity The capacity for debt token.\n  function registerPool(\n    address pool,\n    uint96 collateralCapacity,\n    uint96 debtCapacity\n  ) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    // @dev remove this line to reduce codesize, caller should make sure the pool is correct.\n    // if (fxUSD != ILongPool(pool).fxUSD()) revert ErrorInvalidPool();\n\n    if (pools.add(pool)) {\n      emit RegisterPool(pool);\n\n      _updatePoolCapacity(pool, collateralCapacity, debtCapacity);\n    }\n  }\n\n  /// @notice Update rate provider for the given token.\n  /// @param token The address of the token.\n  /// @param provider The address of corresponding rate provider.\n  function updateRateProvider(address token, address provider) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    uint256 scale = 10 ** (18 - IERC20Metadata(token).decimals());\n    tokenRates[token] = TokenRate(uint96(scale), provider);\n\n    emit UpdateTokenRate(token, scale, provider);\n  }\n\n  /// @notice Update the pool capacity.\n  /// @param pool The address of fx pool.\n  /// @param collateralCapacity The capacity for collateral token.\n  /// @param debtCapacity The capacity for debt token.\n  function updatePoolCapacity(\n    address pool,\n    uint96 collateralCapacity,\n    uint96 debtCapacity\n  ) external onlyRole(DEFAULT_ADMIN_ROLE) onlyRegisteredPool(pool) {\n    _updatePoolCapacity(pool, collateralCapacity, debtCapacity);\n  }\n\n  /// @notice Update threshold for permissionless liquidation.\n  /// @param newThreshold The value of new threshold.\n  function updateThreshold(uint256 newThreshold) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    _updateThreshold(newThreshold);\n  }\n\n  /// @notice Update the short borrow capacity ratio for the given long pool.\n  /// @param longPool The address of the long pool.\n  /// @param newRatio The new short borrow capacity ratio.\n  function updateShortBorrowCapacityRatio(address longPool, uint256 newRatio) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    uint256 oldRatio = shortBorrowCapacityRatio[longPool];\n    shortBorrowCapacityRatio[longPool] = newRatio;\n\n    emit UpdateShortBorrowCapacityRatio(longPool, oldRatio, newRatio);\n  }\n\n  /**********************\n   * Internal Functions *\n   **********************/\n\n  /// @inheritdoc ProtocolFees\n  function _takeAccumulatedPoolFee(address pool) internal virtual override {\n    address collateralToken = ILongPool(pool).collateralToken();\n    uint256 fees = accumulatedPoolOpenFees[pool];\n    if (fees > 0) {\n      _transferCollateralOut(pool, collateralToken, fees, openRevenuePool);\n      accumulatedPoolOpenFees[pool] = 0;\n    }\n    fees = accumulatedPoolCloseFees[pool];\n    if (fees > 0) {\n      _transferCollateralOut(pool, collateralToken, fees, closeRevenuePool);\n      accumulatedPoolCloseFees[pool] = 0;\n    }\n    fees = accumulatedPoolMiscFees[pool];\n    if (fees > 0) {\n      _transferCollateralOut(pool, collateralToken, fees, miscRevenuePool);\n      accumulatedPoolMiscFees[pool] = 0;\n    }\n  }\n\n  /// @dev Internal function to update the pool capacity.\n  /// @param pool The address of fx pool.\n  /// @param collateralCapacity The capacity for collateral token.\n  /// @param debtCapacity The capacity for debt token.\n  function _updatePoolCapacity(address pool, uint96 collateralCapacity, uint96 debtCapacity) internal {\n    poolInfo[pool].collateralData = poolInfo[pool].collateralData.insertUint(\n      collateralCapacity,\n      COLLATERAL_CAPACITY_OFFSET,\n      COLLATERAL_DATA_BITS\n    );\n    poolInfo[pool].debtData = poolInfo[pool].debtData.insertUint(debtCapacity, DEBT_CAPACITY_OFFSET, DEBT_DATA_BITS);\n\n    emit UpdatePoolCapacity(pool, collateralCapacity, debtCapacity);\n  }\n\n  /// @dev Internal function to update threshold for permissionless liquidation.\n  /// @param newThreshold The value of new threshold.\n  function _updateThreshold(uint256 newThreshold) internal {\n    uint256 oldThreshold = permissionedLiquidationThreshold;\n    permissionedLiquidationThreshold = newThreshold;\n\n    emit UpdatePermissionedLiquidationThreshold(oldThreshold, newThreshold);\n  }\n\n  /// @dev Internal function to scaler up for `uint256`.\n  function _scaleUp(uint256 value, uint256 scale) internal pure returns (uint256) {\n    return (value * scale) / PRECISION;\n  }\n\n  /// @dev Internal function to scaler up for `int256`.\n  function _scaleUp(int256 value, uint256 scale) internal pure returns (int256) {\n    return (value * int256(scale)) / PRECISION_I256;\n  }\n\n  /// @dev Internal function to scaler down for `uint256`, rounding down.\n  function _scaleDown(uint256 value, uint256 scale) internal pure returns (uint256) {\n    return (value * PRECISION) / scale;\n  }\n\n  /// @dev Internal function to scaler down for `uint256`, rounding up.\n  function _scaleDownRoundingUp(uint256 value, uint256 scale) internal pure returns (uint256) {\n    return (value * PRECISION + scale - 1) / scale;\n  }\n\n  /// @dev Internal function to scaler down for `int256`.\n  function _scaleDown(int256 value, uint256 scale) internal pure returns (int256) {\n    return (value * PRECISION_I256) / int256(scale);\n  }\n\n  /// @dev Internal function to handle supply.\n  /// @param pool The address of pool.\n  /// @param collateralToken The address of collateral token.\n  /// @param newColl The amount of collateral token supplied.\n  /// @param poolFeeRatio The pool supply fee ratio, multiplied by 10^9.\n  /// @return newColl The amount of collateral token supplied after fees.\n  function _handleSupply(\n    address pool,\n    address collateralToken,\n    uint256 newColl,\n    uint256 poolFeeRatio\n  ) internal returns (uint256) {\n    // handle supply fee for protocol and referral, it is safe to use unchecked here\n    unchecked {\n      uint256 poolFee = (newColl * poolFeeRatio) / FEE_PRECISION;\n      _accumulatePoolOpenFee(pool, poolFee);\n      _transferFrom(collateralToken, _msgSender(), address(this), newColl);\n      return newColl - poolFee;\n    }\n  }\n\n  /// @dev Internal function to handle withdraw.\n  /// @param pool The address of pool.\n  /// @param collateralToken The address of collateral token.\n  /// @param newColl The amount of collateral token withdrawn.\n  /// @param newRawColl The amount of raw collateral token withdrawn.\n  /// @param poolFeeRatio The pool withdraw fee ratio, multiplied by 10^9.\n  function _handleWithdraw(\n    address pool,\n    address collateralToken,\n    uint256 newColl,\n    uint256 newRawColl,\n    uint256 poolFeeRatio\n  ) internal {\n    _changePoolCollateral(pool, -int256(newColl), -int256(newRawColl));\n\n    // handle withdraw fee for protocol and referral, it is safe to use unchecked here\n    unchecked {\n      uint256 poolFee = (newColl * poolFeeRatio) / FEE_PRECISION;\n      if (poolFee > 0) {\n        _accumulatePoolCloseFee(pool, poolFee);\n      }\n      _transferCollateralOut(pool, collateralToken, newColl - poolFee, _msgSender());\n    }\n  }\n\n  /// @dev Internal function to handle borrow.\n  /// @param newDebt The amount of fxUSD borrowed.\n  /// @param poolFeeRatio The pool borrow fee ratio, multiplied by 10^9.\n  function _handleBorrow(uint256 newDebt, uint256 poolFeeRatio) internal {\n    // handle borrow fee for protocol and referral, it is safe to use unchecked here\n    unchecked {\n      uint256 poolFee = (newDebt * poolFeeRatio) / FEE_PRECISION;\n      if (poolFee > 0) {\n        IFxUSDRegeneracy(fxUSD).mint(openRevenuePool, poolFee);\n      }\n      IFxUSDRegeneracy(fxUSD).mint(_msgSender(), newDebt - poolFee);\n    }\n  }\n\n  /// @dev Internal function to handle repay.\n  /// @param newRawDebt The amount of fxUSD repaid.\n  /// @param poolFeeRatio The pool repay fee ratio, multiplied by 10^9.\n  function _handleRepay(uint256 newRawDebt, uint256 poolFeeRatio, uint256 stablePrice) internal {\n    uint256 newDebt = newRawDebt;\n    if (stablePrice != 0) {\n      newDebt = _scaleDown(newRawDebt, stablePrice);\n    }\n    // handle repay fee for protocol and referral, it is safe to use unchecked here\n    unchecked {\n      uint256 poolFee = (newDebt * poolFeeRatio) / FEE_PRECISION;\n      if (stablePrice == 0) {\n        if (poolFee > 0) {\n          IFxUSDRegeneracy(fxUSD).mint(closeRevenuePool, poolFee);\n        }\n        IFxUSDRegeneracy(fxUSD).burn(_msgSender(), newDebt + poolFee);\n      } else {\n        address stableToken = IFxUSDBasePool(fxBASE).stableToken();\n        _transferFrom(stableToken, _msgSender(), closeRevenuePool, poolFee);\n        _transferFrom(stableToken, _msgSender(), fxUSD, newDebt);\n        IFxUSDRegeneracy(fxUSD).onRebalanceWithStable(newDebt, newRawDebt);\n      }\n    }\n  }\n\n  /// @dev Internal function to prepare variables before rebalance or liquidate.\n  /// @param pool The address of pool to liquidate or rebalance.\n  function _beforeRebalanceOrLiquidate(address pool) internal view returns (LiquidateOrRebalanceMemoryVar memory op) {\n    op.stablePrice = IFxUSDBasePool(fxBASE).getStableTokenPriceWithScale();\n    op.collateralToken = ILongPool(pool).collateralToken();\n    op.scalingFactor = _getTokenScalingFactor(op.collateralToken);\n  }\n\n  /// @dev Internal function to do actions after rebalance or liquidate.\n  /// @param pool The address of pool to liquidate or rebalance.\n  /// @param maxFxUSD The maximum amount of fxUSD can be used.\n  /// @param op The memory helper variable.\n  /// @param receiver The address collateral token receiver.\n  /// @return colls The actual amount of collateral token rebalanced or liquidated.\n  /// @return fxUSDUsed The amount of fxUSD used.\n  /// @return stableUsed The amount of stable token (a.k.a USDC) used.\n  function _afterRebalanceOrLiquidate(\n    address pool,\n    uint256 maxFxUSD,\n    LiquidateOrRebalanceMemoryVar memory op,\n    address receiver\n  ) internal returns (uint256 colls, uint256 fxUSDUsed, uint256 stableUsed) {\n    colls = _scaleDown(op.rawColls, op.scalingFactor);\n    _changePoolCollateral(pool, -int256(colls), -int256(op.rawColls));\n    _changePoolDebts(pool, -int256(op.rawDebts));\n\n    // burn fxUSD or transfer USDC\n    fxUSDUsed = op.rawDebts;\n    if (fxUSDUsed > maxFxUSD) {\n      // rounding up here\n      stableUsed = _scaleDownRoundingUp(fxUSDUsed - maxFxUSD, op.stablePrice);\n      fxUSDUsed = maxFxUSD;\n    }\n    if (fxUSDUsed > 0) {\n      IFxUSDRegeneracy(fxUSD).burn(_msgSender(), fxUSDUsed);\n    }\n    if (stableUsed > 0) {\n      if (!IPoolConfiguration(configuration).isStableRepayAllowed()) revert ErrorStableRepayNotAllowed();\n      _transferFrom(IFxUSDBasePool(fxBASE).stableToken(), _msgSender(), fxUSD, stableUsed);\n      IFxUSDRegeneracy(fxUSD).onRebalanceWithStable(stableUsed, op.rawDebts - maxFxUSD);\n    }\n\n    // transfer collateral\n    uint256 protocolRevenue = (_scaleDown(op.bonusRawColls, op.scalingFactor) * getLiquidationExpenseRatio()) /\n      FEE_PRECISION;\n    _accumulatePoolMiscFee(pool, protocolRevenue);\n    unchecked {\n      colls -= protocolRevenue;\n    }\n    _transferCollateralOut(pool, op.collateralToken, colls, receiver);\n  }\n\n  /// @dev Internal function to update collateral balance.\n  function _changePoolCollateral(address pool, int256 delta, int256 rawDelta) internal {\n    bytes32 data = poolInfo[pool].collateralData;\n    uint256 capacity = data.decodeUint(COLLATERAL_CAPACITY_OFFSET, COLLATERAL_DATA_BITS);\n    uint256 balance = uint256(int256(data.decodeUint(COLLATERAL_BALANCE_OFFSET, COLLATERAL_DATA_BITS)) + delta);\n    if (balance > capacity) revert ErrorCollateralExceedCapacity();\n    data = data.insertUint(balance, COLLATERAL_BALANCE_OFFSET, COLLATERAL_DATA_BITS);\n    balance = uint256(int256(data.decodeUint(RAW_COLLATERAL_BALANCE_OFFSET, RAW_COLLATERAL_DATA_BITS)) + rawDelta);\n    poolInfo[pool].collateralData = data.insertUint(balance, RAW_COLLATERAL_BALANCE_OFFSET, RAW_COLLATERAL_DATA_BITS);\n  }\n\n  /// @dev Internal function to update debt balance.\n  function _changePoolDebts(address pool, int256 delta) internal {\n    bytes32 data = poolInfo[pool].debtData;\n    uint256 capacity = data.decodeUint(DEBT_CAPACITY_OFFSET, DEBT_DATA_BITS);\n    uint256 balance = uint256(int256(data.decodeUint(DEBT_BALANCE_OFFSET, DEBT_DATA_BITS)) + delta);\n    if (balance > capacity) revert ErrorDebtExceedCapacity();\n    poolInfo[pool].debtData = data.insertUint(balance, DEBT_BALANCE_OFFSET, DEBT_DATA_BITS);\n  }\n\n  /// @dev Internal function to get token scaling factor.\n  function _getTokenScalingFactor(address token) internal view returns (uint256 value) {\n    address rateProvider = tokenRates[token].rateProvider;\n    value = tokenRates[token].scalar;\n    unchecked {\n      if (rateProvider != address(0)) {\n        value *= IRateProvider(rateProvider).getRate();\n      } else {\n        value *= PRECISION;\n      }\n    }\n  }\n\n  /// @dev Internal function to get pool collateral info.\n  /// @param pool The address of pool.\n  /// @return collateralCapacity The capacity for collateral token.\n  /// @return collateralBalance The balance for collateral token.\n  /// @return rawCollateral The raw collateral balance for collateral token.\n  function _getPoolCollateralInfo(\n    address pool\n  ) internal view returns (uint256 collateralCapacity, uint256 collateralBalance, uint256 rawCollateral) {\n    bytes32 data = poolInfo[pool].collateralData;\n    collateralCapacity = data.decodeUint(COLLATERAL_CAPACITY_OFFSET, COLLATERAL_DATA_BITS);\n    collateralBalance = data.decodeUint(COLLATERAL_BALANCE_OFFSET, COLLATERAL_DATA_BITS);\n    rawCollateral = data.decodeUint(RAW_COLLATERAL_BALANCE_OFFSET, RAW_COLLATERAL_DATA_BITS);\n  }\n\n  /// @dev Internal function to transfer collateral out.\n  /// @param pool The address of pool.\n  /// @param collateralToken The address of collateral token.\n  /// @param scaledAmount The scaled amount of collateral token.\n  /// @param receiver The address of receiver.\n  function _transferCollateralOut(\n    address pool,\n    address collateralToken,\n    uint256 scaledAmount,\n    address receiver\n  ) internal {\n    address shortPool = ILongPool(pool).counterparty();\n    // check if current collateral is enough, if not use debt token to cover\n    if (shortPool != address(0)) {\n      uint256 balance = _balanceOf(collateralToken);\n      if (scaledAmount <= balance) {\n        _transferOut(collateralToken, scaledAmount, receiver);\n      } else {\n        address creditNote = IShortPool(shortPool).creditNote();\n        uint256 shortfall = scaledAmount - balance;\n        IERC20(creditNote).safeTransfer(receiver, shortfall);\n        _transferOut(collateralToken, balance, receiver);\n      }\n    } else {\n      _transferOut(collateralToken, scaledAmount, receiver);\n    }\n  }\n\n  /// @dev Internal function to transfer token from `msg.sender` to receiver.\n  /// @param token The address of token.\n  /// @param sender The address of sender.\n  /// @param receiver The address of receiver.\n  /// @param amount The amount of token.\n  function _transferFrom(address token, address sender, address receiver, uint256 amount) internal {\n    if (amount > 0) {\n      IERC20(token).safeTransferFrom(sender, receiver, amount);\n    }\n  }\n}\n","deployed_bytecode":"0x608060405234801561000f575f80fd5b506004361061040c575f3560e01c80636e49db1c11610221578063ba4bf7d01161012a578063d2001124116100b4578063eedfb05f11610084578063eedfb05f14610acb578063f03577fa14610ade578063f415afd714610af1578063f899980a14610b04578063f9260a8d14610b0c575f80fd5b8063d200112414610a7f578063d547741f14610a92578063d7d7442f14610aa5578063d890cba914610ab8575f80fd5b8063c1c8f15b116100fa578063c1c8f15b14610a0c578063c3df654614610a1f578063c52d087b14610a46578063cbf0b0c014610a59578063d1903fed14610a6c575f80fd5b8063ba4bf7d0146109b4578063bedb86fb146109d3578063bf6f5b00146109e6578063c1342574146109f9575f80fd5b806393e59dc1116101ab578063a4b32de81161017b578063a4b32de814610957578063a69f49351461097e578063aa05d03d14610986578063acdd515a14610999578063b754d58d146109a1575f80fd5b806393e59dc1146108fa5780639bd3bd38146109215780639d8c291014610929578063a217fddf14610950575f80fd5b806385184db7116101f157806385184db71461084157806386403125146108545780638e57338d146108b557806391d14854146108c857806393014f46146108db575f80fd5b80636e49db1c146107f557806372838c91146108085780637f51bb1f1461081b578063807d3f1d1461082e575f80fd5b80632b83cccd116103235780634ac6f0e0116102ad5780635cb3ccaa1161027d5780635cb3ccaa1461076557806361d027b31461076d57806363a560ec146107805780636c70bee9146107a75780636dbe4bb9146107ce575f80fd5b80634ac6f0e0146106b25780635224372c146106da57806352a9039c146106ed5780635c975abb1461074e575f80fd5b806334c63d3e116102f357806334c63d3e1461065d57806336568abe146106705780633eb9c694146106835780633f0292c21461069657806349bc779b1461069f575f80fd5b80632b83cccd146105f65780632bb6bc15146106095780632dfc2001146106375780632f2ff15d1461064a575f80fd5b80631ace9a7c116103a457806322e7d89e1161037457806322e7d89e146105965780632354d83f146105a9578063248a9ca3146105b1578063269ef793146105c4578063285ab4c3146105d7575f80fd5b80631ace9a7c146105365780631da649cf146105495780631da717be1461055c57806320df43591461056f575f80fd5b80630b0eee30116103df5780630b0eee30146104d35780630c932dc8146104e85780630e5c011e146104fb578063153f7cd014610523575f80fd5b806301ffc9a7146104105780630266f0441461043857806303018c111461046357806306bfa93814610498575b5f80fd5b61042361041e36600461556c565b610b2b565b60405190151581526020015b60405180910390f35b60035461044b906001600160a01b031681565b6040516001600160a01b03909116815260200161042f565b61048a7f1be5d1ebf823e636f9019a4a28b5fb56a6c9c490fea63cb140cde243b9045b5381565b60405190815260200161042f565b6104ab6104a63660046155a7565b610b61565b604080519586526020860194909452928401919091526060830152608082015260a00161042f565b6104e66104e13660046155c2565b610bf2565b005b6104e66104f63660046155a7565b610d4f565b61050e6105093660046155a7565b610d66565b6040805192835260208301919091520161042f565b6104e66105313660046155a7565b6111c9565b60055461044b906001600160a01b031681565b6104e66105573660046155ec565b6111dc565b6104e661056a3660046155ec565b6113ae565b61048a7fbf233dd2aafeb4d50879c4aa5c81e96d92f6e6945c906a58f9f2d1c1631b4b2681565b6104e66105a4366004615642565b611652565b61048a611689565b61048a6105bf366004615682565b61169e565b6104e66105d23660046155ec565b6116be565b61048a6105e53660046155a7565b60046020525f908152604090205481565b61050e610604366004615699565b61181a565b61061c6106173660046156cb565b611cc9565b6040805193845260208401929092529082015260600161042f565b61048a6106453660046155c2565b611f2c565b6104e6610658366004615728565b612182565b6104e661066b36600461576c565b61219e565b6104e661067e366004615728565b6121f6565b6104e661069136600461576c565b61222e565b61048a609b5481565b6104e66106ad3660046157a5565b612273565b61044b6106c03660046155a7565b60996020525f90815260409020546001600160a01b031681565b6104e66106e83660046155ec565b61238a565b6107276106fb3660046155a7565b60646020525f90815260409020546001600160a01b03811690600160a01b90046001600160601b031682565b604080516001600160a01b0390931683526001600160601b0390911660208301520161042f565b5f80516020615e888339815191525460ff16610423565b61048a61269c565b60015461044b906001600160a01b031681565b61048a7f3fc733b4d20d27a28452ddf0e9351aced28242fe03389a653cdb783955316b9b81565b61044b7f00000000000000000000000016b334f2644cc00b85db1a1eff0c2c395e00c28d81565b61044b7f000000000000000000000000085780639cc2cacd35e474e71f4d000e2405d8f681565b61061c61080336600461581b565b6126ac565b6104e661081636600461585e565b612984565b6104e66108293660046155a7565b61299d565b6104e661083c3660046155c2565b6129b0565b6104e661084f366004615877565b612b34565b61088e6108623660046155a7565b609a6020525f90815260409020546001600160601b03811690600160601b90046001600160a01b031682565b604080516001600160601b0390931683526001600160a01b0390911660208301520161042f565b6104e66108c33660046158e8565b612c44565b6104236108d6366004615728565b612c79565b61048a6108e93660046155a7565b60086020525f908152604090205481565b61044b7f000000000000000000000000000000000000000000000000000000000000000081565b61048a612caf565b61044b7f00000000000000000000000065c9a641afceb9c0e6034e558a319488fa0fa3be81565b61048a5f81565b61048a7fb1fadd3142ab2ad7f1337ea4d97112bcc8337fc11ce5b20cb04ad038adf9981981565b61048a612cbf565b6104e66109943660046155c2565b612cce565b61048a612d2e565b60025461044b906001600160a01b031681565b61048a6109c23660046155a7565b609c6020525f908152604090205481565b6104e66109e13660046159a9565b612d3d565b6104e66109f436600461585e565b612d7d565b61061c610a0736600461581b565b612d96565b61048a610a1a3660046159c4565b613238565b61044b7f000000000000000000000000acdc0ab51178d0ae8f70c1ead7d3cf5421fdd66d81565b60075461044b906001600160a01b031681565b6104e6610a673660046155a7565b61324f565b61048a610a7a3660046155a7565b613335565b6104e6610a8d3660046155a7565b61333f565b6104e6610aa0366004615728565b613352565b6104e6610ab3366004615682565b61336e565b6104e6610ac63660046159fc565b613381565b6104e6610ad936600461585e565b613429565b6104e6610aec3660046155a7565b613442565b61048a610aff366004615a29565b613455565b61048a613abe565b61048a610b1a3660046155a7565b60066020525f908152604090205481565b5f6001600160e01b03198216637965db0b60e01b1480610b5b57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6001600160a01b0381165f908152609860205260408120548190819081908190610b8d81836055613aca565b9550610b9b81605580613aca565b9450610baa8160aa6056613aca565b6001600160a01b0388165f90815260986020526040812060010154919550909150610bd89082906060613aca565b9250610be681606080613aca565b91505091939590929450565b7fb1fadd3142ab2ad7f1337ea4d97112bcc8337fc11ce5b20cb04ad038adf99819610c1c81613ad8565b6001600160a01b038381165f908152606460209081526040808320815180830183529054948516808252600160a01b9095046001600160601b03168184015281516318160ddd60e01b815291519094926318160ddd92600480820193918290030181865afa158015610c90573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cb49190615a7b565b60208301519091506001600160601b0316610ccf8583615aa6565b1115610cd9575f80fd5b8151610cf0906001600160a01b0387169086613ae5565b815160405163b6b55f2560e01b8152600481018690526001600160a01b039091169063b6b55f25906024015f604051808303815f87803b158015610d32575f80fd5b505af1158015610d44573d5f803e3d5ffd5b505050505050505050565b5f610d5981613ad8565b610d6282613b3d565b5050565b5f8082610d74609682613b97565b610d915760405163aaaf1ba760e01b815260040160405180910390fd5b7f3fc733b4d20d27a28452ddf0e9351aced28242fe03389a653cdb783955316b9b610dbb81613ad8565b610dc3613bbb565b5f856001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e00573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e249190615ab9565b90505f610e3082613c05565b6001600160a01b0388165f90815260986020526040812054919250908190610e5a81605580613aca565b9250610e698160aa6056613aca565b9150505f805f8b6001600160a01b031663ee65a03c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610eab573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ecf9190615a7b565b90508084111561102c57610ee581850387613cb5565b9950610ef88c8b5f038387035f03613cd3565b633b9aca008a610f06611689565b0281610f1457610f14615ad4565b049250633b9aca008a610f25612cbf565b0281610f3357610f33615ad4565b0491508282018a039950610ff58c888c7f00000000000000000000000016b334f2644cc00b85db1a1eff0c2c395e00c28d6001600160a01b0316637ef502987ffc3e964b6f9d1c4d43e30c57b170a183d35f574c0854a499e0c90f8fa253d5bd6040518263ffffffff1660e01b8152600401610fb191815260200190565b602060405180830381865afa158015610fcc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ff09190615ab9565b613d8f565b6001600160a01b038c165f9081526098602052604090205461101981605580613aca565b95506110288160aa6056613aca565b9450505b6110368587613ec7565b9050838111156111235761104c84820387613cb5565b9a5061105b8c8c5f035f613cd3565b5f633b9aca008c61106a612d2e565b028161107857611078615ad4565b0490505f633b9aca008d61108a612cbf565b028161109857611098615ad4565b604051630fdea05360e31b81527ff7670fa3906d826444885d9b61a4246afaf9f48a2f7a2ec4cd843e23dcf7d2da6004820152919004838101909e039d9590920194939093019250611123908d9089908e906001600160a01b037f00000000000000000000000016b334f2644cc00b85db1a1eff0c2c395e00c28d1690637ef5029890602401610fb1565b821561114457600154611144908d90899086906001600160a01b0316613d8f565b61114d8c613edb565b811561115f5761115f8c888433613d8f565b604080518c8152602081018c90528082018590526060810184905290516001600160a01b038e169133917fb97aa24214e8edbddacca4eccaa3910b760a7aa10a284e8b782d12f1137a75619181900360800190a3505050505050506111c2614039565b5050915091565b5f6111d381613ad8565b610d628261405f565b7f000000000000000000000000acdc0ab51178d0ae8f70c1ead7d3cf5421fdd66d6001600160a01b0316331461122557604051637f02477f60e11b815260040160405180910390fd5b82611231609682613b97565b61124e5760405163aaaf1ba760e01b815260040160405180910390fd5b611256613bbb565b5f846001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611293573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112b79190615ab9565b90506112e5817f000000000000000000000000acdc0ab51178d0ae8f70c1ead7d3cf5421fdd66d30866140b9565b836001600160a01b031663ecf1a3a66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611321573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113459190615ab9565b6001600160a01b0316639dc29fac30856040518363ffffffff1660e01b8152600401611372929190615ae8565b5f604051808303815f87803b158015611389575f80fd5b505af115801561139b573d5f803e3d5ffd5b50505050506113a8614039565b50505050565b7f000000000000000000000000acdc0ab51178d0ae8f70c1ead7d3cf5421fdd66d6001600160a01b031633146113f757604051637f02477f60e11b815260040160405180910390fd5b82611403609682613b97565b6114205760405163aaaf1ba760e01b815260040160405180910390fd5b611428613bbb565b5f846001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611465573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114899190615ab9565b90505f61149582613c05565b90505f6114a28583613ec7565b60405163e273fa8760e01b8152600481018290529091506001600160a01b0388169063e273fa87906024015f604051808303815f87803b1580156114e4575f80fd5b505af11580156114f6573d5f803e3d5ffd5b50505050611516878661150890615b01565b61151184615b01565b613cd3565b5f866001600160a01b031663ecf1a3a66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611553573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115779190615ab9565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038316906370a0823190602401602060405180830381865afa1580156115be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115e29190615a7b565b9050801561139b57604051632770a7eb60e21b81526001600160a01b03831690639dc29fac906116189030908590600401615ae8565b5f604051808303815f87803b15801561162f575f80fd5b505af1158015611641573d5f803e3d5ffd5b5050505050505050506113a8614039565b5f61165c81613ad8565b61166b8463ffffffff166140d4565b61167a8363ffffffff16614130565b6113a88263ffffffff16614185565b5f8054611699906078601e613aca565b905090565b5f9081525f80516020615e68833981519152602052604090206001015490565b7f000000000000000000000000acdc0ab51178d0ae8f70c1ead7d3cf5421fdd66d6001600160a01b0316331461170757604051637f02477f60e11b815260040160405180910390fd5b82611713609682613b97565b6117305760405163aaaf1ba760e01b815260040160405180910390fd5b611738613bbb565b826001600160a01b031663ecf1a3a66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611774573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117989190615ab9565b6001600160a01b0316639dc29fac7f000000000000000000000000acdc0ab51178d0ae8f70c1ead7d3cf5421fdd66d846040518363ffffffff1660e01b81526004016117e5929190615ae8565b5f604051808303815f87803b1580156117fc575f80fd5b505af115801561180e573d5f803e3d5ffd5b505050506113a8614039565b5f8084611828609682613b97565b6118455760405163aaaf1ba760e01b815260040160405180910390fd5b61184d613bbb565b6118556141da565b604051630bff4bf360e21b81526001600160a01b037f00000000000000000000000016b334f2644cc00b85db1a1eff0c2c395e00c28d1690632ffd2fcc906118ae9030906001600160e01b03195f351690600401615b1b565b5f604051808303815f87803b1580156118c5575f80fd5b505af11580156118d7573d5f803e3d5ffd5b505050507f000000000000000000000000085780639cc2cacd35e474e71f4d000e2405d8f66001600160a01b03166370a082316119113390565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611953573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119779190615a7b565b851115611997576040516307889a5d60e21b815260040160405180910390fd5b68056bc75e2d631000008510156119c1576040516326d643e360e11b815260040160405180910390fd5b7f00000000000000000000000016b334f2644cc00b85db1a1eff0c2c395e00c28d6001600160a01b031663c00c2ceb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a1d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a419190615b3e565b611a5e576040516321e6770560e11b815260040160405180910390fd5b60405163db006a7560e01b8152600481018690525f906001600160a01b0388169063db006a759060240160408051808303815f875af1158015611aa3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ac79190615b59565b80925081955050508395505f876001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b0f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b339190615ab9565b90505f611b3f82613c05565b9050611b4b8382613cb5565b9450611b6389611b5a87615b01565b61151186615b01565b611b7589611b708a615b01565b61420c565b5f633b9aca00611b8361269c565b870281611b9257611b92615ad4565b049050611bbb8a826001600160a01b039091165f90815260086020526040902080549091019055565b808603955087861015611be157604051630f29910b60e31b815260040160405180910390fd5b611bed8a848833613d8f565b604051632770a7eb60e21b81527f000000000000000000000000085780639cc2cacd35e474e71f4d000e2405d8f66001600160a01b031690639dc29fac90611c3b9033908d90600401615ae8565b5f604051808303815f87803b158015611c52575f80fd5b505af1158015611c64573d5f803e3d5ffd5b505060408051898152602081018d90529081018490526001600160a01b038d1692507fbd5034ffbd47e4e72a94baa2cdb74c6fad73cb3bcdc13036b72ec8306f5a7646915060600160405180910390a250505050611cc0614039565b50935093915050565b5f808087611cd8609682613b97565b611cf55760405163aaaf1ba760e01b815260040160405180910390fd5b611cfd613bbb565b611d056141da565b337f00000000000000000000000065c9a641afceb9c0e6034e558a319488fa0fa3be6001600160a01b031614611dd657609b547f00000000000000000000000065c9a641afceb9c0e6034e558a319488fa0fa3be6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d94573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611db89190615a7b565b10611dd657604051639544786b60e01b815260040160405180910390fd5b5f611de08a6142a3565b90505f611df087835f0151613ec7565b88019050670de0b6b3a7640000811015611e1d5760405163880cbfe760e01b815260040160405180910390fd5b604051630723d57160e01b815260018a900b6004820152602481018290525f906001600160a01b038d1690630723d571906044016060604051808303815f875af1158015611e6d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e919190615b7b565b60408101805182510160608601525160808501526020015160a084015250611ebd90508a88838c6143ea565b60408051848152602081018490529081018290529297509095509350600189900b906001600160a01b038c16907ff8cdb1f9af03fbf36ddb1d43fce878a63592deba4f09a82777616f3019aa6c4d9060600160405180910390a350611f20614039565b50955095509592505050565b5f7f000000000000000000000000acdc0ab51178d0ae8f70c1ead7d3cf5421fdd66d6001600160a01b03163314611f7657604051637f02477f60e11b815260040160405180910390fd5b82611f82609682613b97565b611f9f5760405163aaaf1ba760e01b815260040160405180910390fd5b611fa7613bbb565b5f846001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fe4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120089190615ab9565b90505f61201482613c05565b604051630d65a06b60e41b815260048101879052600160248201529091505f906001600160a01b0388169063d65a06b09060440160408051808303815f875af1158015612063573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120879190615b59565b9150506120948183613cb5565b94506120a38761150887615b01565b604051632770a7eb60e21b81527f000000000000000000000000085780639cc2cacd35e474e71f4d000e2405d8f66001600160a01b031690639dc29fac906120f19033908a90600401615ae8565b5f604051808303815f87803b158015612108575f80fd5b505af115801561211a573d5f803e3d5ffd5b5050505061212c8787611b7090615b01565b60408051868152602081018890526001600160a01b038916917f8a71ee13bf13e8b561796365ba04cdca906b2944b6ba975995fb5ba8c2955d57910160405180910390a250505061217b614039565b5092915050565b61218b8261169e565b61219481613ad8565b6113a88383614721565b5f6121a881613ad8565b6121b36096856147c2565b156113a8576040516001600160a01b038516907fdfc596fabc6581c887262c97695176a79e3c8fc6ab7aaf14700820f3436b8fb9905f90a26113a88484846147d6565b6001600160a01b038116331461221f5760405163334bd91960e11b815260040160405180910390fd5b61222982826148ad565b505050565b5f61223881613ad8565b83612244609682613b97565b6122615760405163aaaf1ba760e01b815260040160405180910390fd5b61226c8585856147d6565b5050505050565b5f61227c614926565b805490915060ff600160401b820416159067ffffffffffffffff165f811580156122a35750825b90505f8267ffffffffffffffff1660011480156122bf5750303b155b9050811580156122cd575080155b156122eb5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561231557845460ff60401b1916600160401b1785555b61231f5f8d614721565b5061232e8b8b8b8b8b8b61494e565b6123366149b8565b831561237c57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050505050565b7f000000000000000000000000acdc0ab51178d0ae8f70c1ead7d3cf5421fdd66d6001600160a01b031633146123d357604051637f02477f60e11b815260040160405180910390fd5b826123df609682613b97565b6123fc5760405163aaaf1ba760e01b815260040160405180910390fd5b612404613bbb565b5f836001600160a01b031663ecf1a3a66040518163ffffffff1660e01b8152600401602060405180830381865afa158015612441573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124659190615ab9565b90505f856001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156124a4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124c89190615ab9565b90505f6124d482613c05565b90505f876001600160a01b031663ee65a03c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612513573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125379190615a7b565b90505f6125448284613cb5565b90505f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612583573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125a79190615a7b565b90506125b38882615aa6565b6001600160a01b038b165f908152609c6020526040902054670de0b6b3a7640000906125df9085615bd4565b6125e99190615beb565b1015612608576040516319d5157560e31b815260040160405180910390fd5b50505061263682867f000000000000000000000000acdc0ab51178d0ae8f70c1ead7d3cf5421fdd66d6149c0565b6040516340c10f1960e01b81526001600160a01b038416906340c10f19906126649030908990600401615ae8565b5f604051808303815f87803b15801561267b575f80fd5b505af115801561268d573d5f803e3d5ffd5b505050505050506113a8614039565b5f805461169990605a601e613aca565b5f8080866126bb609682613b97565b6126d85760405163aaaf1ba760e01b815260040160405180910390fd5b6126e0613bbb565b6126e86141da565b337f00000000000000000000000065c9a641afceb9c0e6034e558a319488fa0fa3be6001600160a01b0316146127b957609b547f00000000000000000000000065c9a641afceb9c0e6034e558a319488fa0fa3be6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612777573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061279b9190615a7b565b106127b957604051639544786b60e01b815260040160405180910390fd5b604051630bff4bf360e21b81526001600160a01b037f00000000000000000000000016b334f2644cc00b85db1a1eff0c2c395e00c28d1690632ffd2fcc906128129030906001600160e01b03195f351690600401615b1b565b5f604051808303815f87803b158015612829575f80fd5b505af115801561283b573d5f803e3d5ffd5b505050505f612849896142a3565b90505f61285987835f0151613ec7565b88019050670de0b6b3a76400008110156128865760405163880cbfe760e01b815260040160405180910390fd5b604051631e93260360e31b8152600481018290525f906001600160a01b038c169063f4993018906024016060604051808303815f875af11580156128cc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128f09190615b7b565b60408101805182510160608601525160808501526020015160a08401525061291c90508988838b6143ea565b604080518481526020810184905290810182905292975090955093506001600160a01b038a16907f2ee87fe08e822e20d39eb53e4cfe022c750e0b72e3dfafa2413b41b61f3dacc59060600160405180910390a250612979614039565b509450945094915050565b5f61298e81613ad8565b610d628263ffffffff16614b17565b5f6129a781613ad8565b610d6282614b6c565b816129bc609682613b97565b6129d95760405163aaaf1ba760e01b815260040160405180910390fd5b7f1be5d1ebf823e636f9019a4a28b5fb56a6c9c490fea63cb140cde243b9045b53612a0381613ad8565b612a0b613bbb565b604051632770a7eb60e21b81527f000000000000000000000000085780639cc2cacd35e474e71f4d000e2405d8f66001600160a01b031690639dc29fac90612a599033908790600401615ae8565b5f604051808303815f87803b158015612a70575f80fd5b505af1158015612a82573d5f803e3d5ffd5b505060405163193cefdd60e31b8152600481018690526001600160a01b038716925063c9e77ee891506024015f604051808303815f87803b158015612ac5575f80fd5b505af1158015612ad7573d5f803e3d5ffd5b50505050612ae98484611b7090615b01565b836001600160a01b03167f243d60a280579accabafa82109d7f67f7ce230d575b0ff7a301e8dabf3a3f50584604051612b2491815260200190565b60405180910390a26113a8614039565b5f612b3e81613ad8565b5f836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b7b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b9f9190615bfe565b612baa906012615c1e565b612bb590600a615d1a565b6040805180820182526001600160601b0383811682526001600160a01b0387811660208085018281528b84165f818152609a845288902096519151909416600160601b02941693909317909355835185815291820192909252929350917f5eae3446f897bd3bbec9c0c4bfa76e39caf18a7b1a0ed8e89de3aea8a297acae91015b60405180910390a250505050565b5f5b8151811015610d6257612c71828281518110612c6457612c64615d28565b6020026020010151613edb565b600101612c46565b5f9182525f80516020615e68833981519152602090815260408084206001600160a01b0393909316845291905290205460ff1690565b5f8054611699906096601e613aca565b5f805461169990601e80613aca565b5f612cd881613ad8565b6001600160a01b0383165f818152609c6020908152604091829020805490869055825181815291820186905292917fb5905b07f0c450b4bfc9df549639d6d41a561c63f983efb2d22b6710a147d9c09101612c36565b5f80546116999082601e613aca565b7fbf233dd2aafeb4d50879c4aa5c81e96d92f6e6945c906a58f9f2d1c1631b4b26612d6781613ad8565b8115612d7557610d62614bc6565b610d62614c28565b5f612d8781613ad8565b610d628263ffffffff16614c6d565b5f808086612da5609682613b97565b612dc25760405163aaaf1ba760e01b815260040160405180910390fd5b612dca613bbb565b612dd26141da565b337f00000000000000000000000065c9a641afceb9c0e6034e558a319488fa0fa3be6001600160a01b031614612ea357609b547f00000000000000000000000065c9a641afceb9c0e6034e558a319488fa0fa3be6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e61573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e859190615a7b565b10612ea357604051639544786b60e01b815260040160405180910390fd5b604051630bff4bf360e21b81526001600160a01b037f00000000000000000000000016b334f2644cc00b85db1a1eff0c2c395e00c28d1690632ffd2fcc90612efc9030906001600160e01b03195f351690600401615b1b565b5f604051808303815f87803b158015612f13575f80fd5b505af1158015612f25573d5f803e3d5ffd5b505050505f612f33896142a3565b90505f612f4387835f0151613ec7565b612f4d9089615aa6565b9050670de0b6b3a7640000811015612f78576040516307a1b46360e01b815260040160405180910390fd5b612f9f60405180608001604052805f81526020015f81526020015f81526020015f81525090565b600354604084810151905163f8b2cb4f60e01b81526001600160a01b0391821660048201525f92919091169063f8b2cb4f90602401602060405180830381865afa158015612fef573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130139190615a7b565b9050613023818560200151613ec7565b60405163d296d1f160e01b815260048101859052602481018290529091506001600160a01b038d169063d296d1f1906044016080604051808303815f875af1158015613071573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130959190615d3c565b60408101805182510160608088019190915290516080870152602082015160a087015281015190925080156131cb576130d683606001518660200151613cb5565b905060035f9054906101000a90046001600160a01b03166001600160a01b031663565659ea8e6001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa158015613137573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061315b9190615ab9565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604481018490526064015f604051808303815f87803b1580156131a6575f80fd5b505af11580156131b8573d5f803e3d5ffd5b505050506131cb8d828560600151613cd3565b5050506131da8a89848c6143ea565b604080518481526020810184905290810182905292985090965094506001600160a01b038b16907f158ba9ab7bbbd08eeffa4753bad41f4d450e24831d293427308badf3eadd8c769060600160405180910390a25050612979614039565b5f613246858585855f613455565b95945050505050565b5f61325981613ad8565b6001600160a01b038281165f90815260646020908152604091829020825180840190935254928316808352600160a01b9093046001600160601b031690820152901561222957805f01516001600160a01b03166341c0e1b56040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156132da575f80fd5b505af11580156132ec573d5f803e3d5ffd5b50505f80845260208085018281526001600160a01b03888116845260649092526040909220855192516001600160601b0316600160a01b02929091169190911790555050505050565b5f610b5b82613c05565b5f61334981613ad8565b610d6282614cc1565b61335b8261169e565b61336481613ad8565b6113a883836148ad565b5f61337881613ad8565b610d6282614d1b565b5f61338b81613ad8565b6001600160a01b038481165f90815260646020908152604091829020825180840190935254928316808352600160a01b9093046001600160601b03169082015290156133da576133da8561324f565b50506040805180820182526001600160a01b0393841681526001600160601b0392831660208083019182529585165f90815260649096529190942093519051909116600160a01b029116179055565b5f61343381613ad8565b610d628263ffffffff16614d59565b5f61344c81613ad8565b610d6282614dae565b5f85613462609682613b97565b61347f5760405163aaaf1ba760e01b815260040160405180910390fd5b613487613bbb565b61348f6141da565b333b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316158015906134d257505f8111806134d25750333214155b1561357a57604051631846d2f560e31b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c23697a890602401602060405180830381865afa158015613539573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061355d9190615b3e565b61357a57604051632c10e80160e21b815260040160405180910390fd5b604051630bff4bf360e21b81526001600160a01b037f00000000000000000000000016b334f2644cc00b85db1a1eff0c2c395e00c28d1690632ffd2fcc906135d39030906001600160e01b03195f351690600401615b1b565b5f604051808303815f87803b1580156135ea575f80fd5b505af11580156135fc573d5f803e3d5ffd5b505050506136556040518061014001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81525090565b84156137b0577f00000000000000000000000016b334f2644cc00b85db1a1eff0c2c395e00c28d6001600160a01b0316639db4a5536040518163ffffffff1660e01b8152600401602060405180830381865afa1580156136b7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136db9190615b3e565b6136f8576040516378bcd3ab60e11b815260040160405180910390fd5b5f87138061370657505f8612155b8061370f575087155b1561372d57604051630549b09160e31b815260040160405180910390fd5b7f00000000000000000000000065c9a641afceb9c0e6034e558a319488fa0fa3be6001600160a01b0316633fd7ebe96040518163ffffffff1660e01b8152600401602060405180830381865afa158015613789573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906137ad9190615a7b565b81525b5f896001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138119190615ab9565b90505f61381d82613c05565b90506001600160a01b037f00000000000000000000000016b334f2644cc00b85db1a1eff0c2c395e00c28d16631a4a400f8c336040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401608060405180830381865afa158015613899573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138bd9190615d9f565b60808701526060860152604085015260208401525f8913156138ec576138e98b838b8660200151614e08565b98505b8888600160ff1b8214613906576139038284614e47565b91505b8880156139175750600160ff1b8114155b1561392c5761392981865f0151614e47565b90505b6001600160a01b038d1663032d22768d8484336040516001600160e01b031960e087901b1681526004810194909452602484019290925260448301526001600160a01b031660648201526084016080604051808303815f875af1158015613995573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906139b99190615d9f565b50919d50925090506139cb8284614e65565b9a506139d78d8261420c565b5f8213156139ef576139ea8d8c84613cd3565b613a18565b5f821215613a1857613a188d85613a058e615b01565b613a0e86615b01565b8960400151614e79565b5f811315613a3357613a2e818660600151614eca565b613a53565b5f811215613a5357613a53613a4782615b01565b60808701518751614fde565b604080518c8152602081018390525f918101919091528c906001600160a01b038f16907f9a243f0f02273a4b80be965697988a178f95cd11863de2122e69f811445dff449060600160405180910390a38b9750505050505050613ab4614039565b5095945050505050565b5f805461169990603c601e5b6001901b5f190191901c1690565b613ae28133615228565b50565b61222983846001600160a01b031663a9059cbb8585604051602401613b0b929190615ae8565b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505061525c565b613b46816152c8565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fe5110bb0e516861a91fc6865f2b0c0540cceff8cec2bfaaa5b032979e13c7e41905f90a35050565b6001600160a01b0381165f90815260018301602052604081205415155b9392505050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00805460011901613bff57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b6001600160a01b038082165f908152609a60205260409020546001600160601b03811691600160601b909104168015613ca157806001600160a01b031663679aefce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613c74573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613c989190615a7b565b82029150613caf565b670de0b6b3a7640000820291505b50919050565b5f81613cc9670de0b6b3a764000085615bd4565b613bb49190615beb565b6001600160a01b0383165f9081526098602052604081205490613cf882826055613aca565b90505f84613d0884605580613aca565b613d129190615dd2565b905081811115613d355760405163f646f2f960e01b815260040160405180910390fd5b613d4283826055806152ef565b925083613d528460aa6056613aca565b613d5c9190615dd2565b9050613d6c838260aa60566152ef565b6001600160a01b039096165f908152609860205260409020959095555050505050565b5f846001600160a01b031663c3df65466040518163ffffffff1660e01b8152600401602060405180830381865afa158015613dcc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613df09190615ab9565b90506001600160a01b03811615613ebc575f613e0b85615303565b9050808411613e2457613e1f8585856149c0565b613eb6565b5f826001600160a01b031663ecf1a3a66040518163ffffffff1660e01b8152600401602060405180830381865afa158015613e61573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613e859190615ab9565b90505f613e928387615df9565b9050613ea86001600160a01b0383168683613ae5565b613eb38784876149c0565b50505b5061226c565b61226c8484846149c0565b5f670de0b6b3a7640000613cc98385615bd4565b5f816001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa158015613f18573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613f3c9190615ab9565b6001600160a01b0383165f908152600460205260409020549091508015613f9157600254613f78908490849084906001600160a01b0316613d8f565b6001600160a01b0383165f908152600460205260408120555b506001600160a01b0382165f908152600660205260409020548015613fe457600554613fcb908490849084906001600160a01b0316613d8f565b6001600160a01b0383165f908152600660205260408120555b506001600160a01b0382165f9081526008602052604090205480156122295760075461401e908490849084906001600160a01b0316613d8f565b50506001600160a01b03165f90815260086020526040812055565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b614068816152c8565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f3ed91ef70e6e7c6a805523d1a95ddc27851b8f620524b5def16053d07bc33c32905f90a35050565b80156113a8576113a86001600160a01b038516848484615408565b6140e281631dcd6500615441565b5f6140ef825f601e615462565b60408051828152602081018590529192507f77cf0faf60882cf7bf063a7308f5b2f7acc4c4cf6118126dc6f45a3fc19a05d191015b60405180910390a15050565b61413e81631dcd6500615441565b5f61414c826078601e615462565b60408051828152602081018590529192507f38a939f96f90bf373822856f3ca5959e9f2fa4d92dfd22cc236d692ac15c80ff9101614124565b61419381631dcd6500615441565b5f6141a1826096601e615462565b60408051828152602081018590529192507fc47c244bb9022fbfd61c1961e43c3f6100aba94a7196cca3e6743b6ec04f7d099101614124565b5f80516020615e888339815191525460ff161561420a5760405163d93c066560e01b815260040160405180910390fd5b565b6001600160a01b0382165f908152609860205260408120600101549061423482826060613aca565b90505f8361424484606080613aca565b61424e9190615dd2565b90508181111561427157604051631b2f832360e21b815260040160405180910390fd5b61427e83826060806152ef565b6001600160a01b039095165f9081526098602052604090206001019490945550505050565b6142df6040518060c001604052805f81526020015f81526020015f6001600160a01b031681526020015f81526020015f81526020015f81525090565b7f00000000000000000000000065c9a641afceb9c0e6034e558a319488fa0fa3be6001600160a01b0316633fd7ebe96040518163ffffffff1660e01b8152600401602060405180830381865afa15801561433b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061435f9190615a7b565b815f018181525050816001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156143a3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906143c79190615ab9565b6001600160a01b0316604082018190526143e090613c05565b6020820152919050565b5f805f6143ff85606001518660200151613cb5565b925061441c8761440e85615b01565b876060015161151190615b01565b61442e878660a00151611b7090615b01565b8460a001519150858211156144575761445161444a8784615df9565b8651615488565b90508591505b81156144d957604051632770a7eb60e21b81527f000000000000000000000000085780639cc2cacd35e474e71f4d000e2405d8f66001600160a01b031690639dc29fac906144ab9033908690600401615ae8565b5f604051808303815f87803b1580156144c2575f80fd5b505af11580156144d4573d5f803e3d5ffd5b505050505b80156146b9577f00000000000000000000000016b334f2644cc00b85db1a1eff0c2c395e00c28d6001600160a01b0316639db4a5536040518163ffffffff1660e01b8152600401602060405180830381865afa15801561453b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061455f9190615b3e565b61457c576040516378bcd3ab60e11b815260040160405180910390fd5b6146277f00000000000000000000000065c9a641afceb9c0e6034e558a319488fa0fa3be6001600160a01b031663a9d75b2b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156145db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906145ff9190615ab9565b337f000000000000000000000000085780639cc2cacd35e474e71f4d000e2405d8f6846140b9565b7f000000000000000000000000085780639cc2cacd35e474e71f4d000e2405d8f66001600160a01b0316631ae94cde82888860a001516146679190615df9565b6040516001600160e01b031960e085901b168152600481019290925260248201526044015f604051808303815f87803b1580156146a2575f80fd5b505af11580156146b4573d5f803e3d5ffd5b505050505b5f633b9aca006146c7612caf565b6146d988608001518960200151613cb5565b6146e39190615bd4565b6146ed9190615beb565b6001600160a01b0389165f908152600860205260409020805482019055905080840393506129798887604001518688613d8f565b5f5f80516020615e6883398151915261473a8484612c79565b6147b9575f848152602082815260408083206001600160a01b03871684529091529020805460ff1916600117905561476f3390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a46001915050610b5b565b5f915050610b5b565b5f613bb4836001600160a01b0384166154b3565b6001600160a01b0383165f90815260986020526040812054614804916001600160601b0385169060556152ef565b6001600160a01b0384165f90815260986020526040812091825560019091015461483a916001600160601b0384169060606152ef565b6001600160a01b0384165f81815260986020526040908190206001019290925590517fe02c6e99b21daa3ddf5404c5d54ac9c919fe91ab12e1e72665dc1fd8bc865467906148a090859085906001600160601b0392831681529116602082015260400190565b60405180910390a2505050565b5f5f80516020615e688339815191526148c68484612c79565b156147b9575f848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a46001915050610b5b565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610b5b565b6149566154ff565b61495f86614130565b614968866140d4565b61497186614185565b61497a85614c6d565b61498384614b17565b61498c83614b6c565b61499582614dae565b61499e82613b3d565b6149a782614cc1565b6149b08161405f565b505050505050565b61420a6154ff565b6040516370a0823160e01b81523060048201525f906001600160a01b038516906370a0823190602401602060405180830381865afa158015614a04573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614a289190615a7b565b9050828110614a4a57614a456001600160a01b0385168385613ae5565b6113a8565b8015614a6457614a646001600160a01b0385168383613ae5565b6001600160a01b038481165f90815260646020908152604091829020825180840190935254928316808352600160a01b9093046001600160601b03169082015282850391614ab0575f80fd5b8051604051627b8a6760e11b8152600481018490526001600160a01b0386811660248301529091169062f714ce906044015b5f604051808303815f87803b158015614af9575f80fd5b505af1158015614b0b573d5f803e3d5ffd5b50505050505050505050565b614b25816305f5e100615441565b5f614b3382603c601e615462565b60408051828152602081018590529192507f6435b9a85963bf02d1ea1c96162e6e48e3cf1112e4b029810eba42e10532e5a99101614124565b614b75816152c8565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd101a15f9e9364a1c0a7c4cc8eb4cd9220094e83353915b0c74e09f72ec73edb905f90a35050565b614bce6141da565b5f80516020615e88833981519152805460ff191660011781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258335b6040516001600160a01b03909116815260200160405180910390a150565b614c30615524565b5f80516020615e88833981519152805460ff191681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33614c0a565b614c7b81630bebc200615441565b5f614c8882601e80615462565b60408051828152602081018590529192507f2c3b971a5011a057ee9b96ea2aa1504d93d268e5c9cfdee7581d31435b24435e9101614124565b614cca816152c8565b600780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fbcfa1f4a44edd726cc4f3c7dca57d46a5a8e8adb14b1eaae01bc3576059ddd42905f90a35050565b609b80549082905560408051828152602081018490527f87b7851a3d0ea68ea4815a7d26786f79a1395130f36977b4cae075de129f3cbd9101614124565b614d67816305f5e100615441565b5f614d7582605a601e615462565b60408051828152602081018590529192507fbf5383b9e422a4efef091bed41e294217b4a7c7adfbed0dc4d48588bac69afa89101614124565b614db7816152c8565b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f731b9ea4fb17ff346b10938712cc430bfa7ba2198f0d2d66a9594804ddf56bc2905f90a35050565b6001600160a01b0384165f9081526004602052604081208054633b9aca0084860204908101909155614e3c853330876140b9565b909203949350505050565b5f670de0b6b3a7640000614e5b8385615e0c565b613bb49190615e3b565b5f81614e5b670de0b6b3a764000085615e0c565b614e8f85614e8685615b01565b61151185615b01565b633b9aca00818402048015614ebc576001600160a01b0386165f9081526006602052604090208054820190555b6149b0868683870333613d8f565b633b9aca00818302048015614f5c576002546040516340c10f1960e01b81526001600160a01b037f000000000000000000000000085780639cc2cacd35e474e71f4d000e2405d8f68116926340c10f1992614f2e9291909116908590600401615ae8565b5f604051808303815f87803b158015614f45575f80fd5b505af1158015614f57573d5f803e3d5ffd5b505050505b6040516340c10f1960e01b81527f000000000000000000000000085780639cc2cacd35e474e71f4d000e2405d8f66001600160a01b0316906340c10f1990614fac90339085880390600401615ae8565b5f604051808303815f87803b158015614fc3575f80fd5b505af1158015614fd5573d5f803e3d5ffd5b50505050505050565b828115614ff257614fef8483613cb5565b90505b633b9aca00838202045f83900361510e57801561508c576005546040516340c10f1960e01b81526001600160a01b037f000000000000000000000000085780639cc2cacd35e474e71f4d000e2405d8f68116926340c10f199261505e9291909116908590600401615ae8565b5f604051808303815f87803b158015615075575f80fd5b505af1158015615087573d5f803e3d5ffd5b505050505b604051632770a7eb60e21b81527f000000000000000000000000085780639cc2cacd35e474e71f4d000e2405d8f66001600160a01b031690639dc29fac906150dc90339086860190600401615ae8565b5f604051808303815f87803b1580156150f3575f80fd5b505af1158015615105573d5f803e3d5ffd5b5050505061226c565b5f7f00000000000000000000000065c9a641afceb9c0e6034e558a319488fa0fa3be6001600160a01b031663a9d75b2b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561516b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061518f9190615ab9565b90506151a881336005546001600160a01b0316856140b9565b6151d481337f000000000000000000000000085780639cc2cacd35e474e71f4d000e2405d8f6866140b9565b604051630d74a66f60e11b815260048101849052602481018790527f000000000000000000000000085780639cc2cacd35e474e71f4d000e2405d8f66001600160a01b031690631ae94cde90604401614ae2565b6152328282612c79565b610d6257808260405163e2517d3f60e01b8152600401615253929190615ae8565b60405180910390fd5b5f8060205f8451602086015f885af18061527b576040513d5f823e3d81fd5b50505f513d9150811561529257806001141561529f565b6001600160a01b0384163b155b156113a857604051635274afe760e01b81526001600160a01b0385166004820152602401615253565b6001600160a01b038116613ae25760405163a7f9319d60e01b815260040160405180910390fd5b6001901b5f1901811b1992909216911b1790565b6040516370a0823160e01b81523060048201525f9081906001600160a01b038416906370a0823190602401602060405180830381865afa158015615349573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061536d9190615a7b565b6001600160a01b038085165f908152606460205260409020549192501680615396575092915050565b806001600160a01b031663ba5d30786040518163ffffffff1660e01b8152600401602060405180830381865afa1580156153d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906153f69190615a7b565b6154009083615aa6565b949350505050565b6040516001600160a01b0384811660248301528381166044830152606482018390526113a89186918216906323b872dd90608401613b0b565b80821115610d6257604051634df52d2560e11b815260040160405180910390fd5b5f8054615470818585613aca565b915061547e818686866152ef565b5f55509392505050565b5f8160018161549f670de0b6b3a764000087615bd4565b6154a99190615aa6565b613cc99190615df9565b5f8181526001830160205260408120546154f857508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610b5b565b505f610b5b565b615507615553565b61420a57604051631afcd79f60e31b815260040160405180910390fd5b5f80516020615e888339815191525460ff1661420a57604051638dfc202b60e01b815260040160405180910390fd5b5f61555c614926565b54600160401b900460ff16919050565b5f6020828403121561557c575f80fd5b81356001600160e01b031981168114613bb4575f80fd5b6001600160a01b0381168114613ae2575f80fd5b5f602082840312156155b7575f80fd5b8135613bb481615593565b5f80604083850312156155d3575f80fd5b82356155de81615593565b946020939093013593505050565b5f805f606084860312156155fe575f80fd5b833561560981615593565b9250602084013561561981615593565b929592945050506040919091013590565b803563ffffffff8116811461563d575f80fd5b919050565b5f805f60608486031215615654575f80fd5b61565d8461562a565b925061566b6020850161562a565b91506156796040850161562a565b90509250925092565b5f60208284031215615692575f80fd5b5035919050565b5f805f606084860312156156ab575f80fd5b83356156b681615593565b95602085013595506040909401359392505050565b5f805f805f60a086880312156156df575f80fd5b85356156ea81615593565b945060208601356156fa81615593565b93506040860135600181900b8114615710575f80fd5b94979396509394606081013594506080013592915050565b5f8060408385031215615739575f80fd5b82359150602083013561574b81615593565b809150509250929050565b80356001600160601b038116811461563d575f80fd5b5f805f6060848603121561577e575f80fd5b833561578981615593565b925061579760208501615756565b915061567960408501615756565b5f805f805f805f60e0888a0312156157bb575f80fd5b87356157c681615593565b965060208801359550604088013594506060880135935060808801356157eb81615593565b925060a08801356157fb81615593565b915060c088013561580b81615593565b8091505092959891949750929550565b5f805f806080858703121561582e575f80fd5b843561583981615593565b9350602085013561584981615593565b93969395505050506040820135916060013590565b5f6020828403121561586e575f80fd5b613bb48261562a565b5f8060408385031215615888575f80fd5b823561589381615593565b9150602083013561574b81615593565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156158e0576158e06158a3565b604052919050565b5f602082840312156158f8575f80fd5b813567ffffffffffffffff81111561590e575f80fd5b8201601f8101841361591e575f80fd5b803567ffffffffffffffff811115615938576159386158a3565b8060051b615948602082016158b7565b91825260208184018101929081019087841115615963575f80fd5b6020850194505b83851015615991578435925061597f83615593565b8282526020948501949091019061596a565b979650505050505050565b8015158114613ae2575f80fd5b5f602082840312156159b9575f80fd5b8135613bb48161599c565b5f805f80608085870312156159d7575f80fd5b84356159e281615593565b966020860135965060408601359560600135945092505050565b5f805f60608486031215615a0e575f80fd5b8335615a1981615593565b9250602084013561579781615593565b5f805f805f60a08688031215615a3d575f80fd5b8535615a4881615593565b94506020860135935060408601359250606086013591506080860135615a6d8161599c565b809150509295509295909350565b5f60208284031215615a8b575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610b5b57610b5b615a92565b5f60208284031215615ac9575f80fd5b8151613bb481615593565b634e487b7160e01b5f52601260045260245ffd5b6001600160a01b03929092168252602082015260400190565b5f600160ff1b8201615b1557615b15615a92565b505f0390565b6001600160a01b039290921682526001600160e01b031916602082015260400190565b5f60208284031215615b4e575f80fd5b8151613bb48161599c565b5f8060408385031215615b6a575f80fd5b505080516020909101519092909150565b5f6060828403128015615b8c575f80fd5b506040516060810167ffffffffffffffff81118282101715615bb057615bb06158a3565b60409081528351825260208085015190830152928301519281019290925250919050565b8082028115828204841417610b5b57610b5b615a92565b5f82615bf957615bf9615ad4565b500490565b5f60208284031215615c0e575f80fd5b815160ff81168114613bb4575f80fd5b60ff8281168282160390811115610b5b57610b5b615a92565b6001815b6001841115615c7257808504811115615c5657615c56615a92565b6001841615615c6457908102905b60019390931c928002615c3b565b935093915050565b5f82615c8857506001610b5b565b81615c9457505f610b5b565b8160018114615caa5760028114615cb457615cd0565b6001915050610b5b565b60ff841115615cc557615cc5615a92565b50506001821b610b5b565b5060208310610133831016604e8410600b8410161715615cf3575081810a610b5b565b615cff5f198484615c37565b805f1904821115615d1257615d12615a92565b029392505050565b5f613bb460ff841683615c7a565b634e487b7160e01b5f52603260045260245ffd5b5f6080828403128015615d4d575f80fd5b506040516080810167ffffffffffffffff81118282101715615d7157615d716158a3565b6040908152835182526020808501519083015283810151908201526060928301519281019290925250919050565b5f805f8060808587031215615db2575f80fd5b505082516020840151604085015160609095015191969095509092509050565b8082018281125f831280158216821582161715615df157615df1615a92565b505092915050565b81810381811115610b5b57610b5b615a92565b8082025f8212600160ff1b84141615615e2757615e27615a92565b8181058314821517610b5b57610b5b615a92565b5f82615e4957615e49615ad4565b600160ff1b82145f1984141615615e6257615e62615a92565b50059056fe02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800cd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300a264697066735822122067254a36349e2b3c461ad1aee00c5bf63cc0bca40743d2e7440ad1089cd06e0364736f6c634300081a0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":true,"runs":200},"remappings":["npm/@openzeppelin/contracts-upgradeable@5.4.0/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.4.0/","project/:@openzeppelin/contracts-upgradeable/=npm/@openzeppelin/contracts-upgradeable@5.4.0/","project/:@openzeppelin/contracts/=npm/@openzeppelin/contracts@5.4.0/"]},"optimization_runs":200,"sourcify_repo_url":"https://repo.sourcify.dev/contracts/full_match/1/0xa70DDDb8ddD06B1C26061d998E041748b18eCf85/","decoded_constructor_args":[["0x085780639CC2cACd35E474e71f4d000e2405d8f6",{"internalType":"address","name":"_fxUSD","type":"address"}],["0x65C9A641afCEB9C0E6034e558A319488FA0FA3be",{"internalType":"address","name":"_fxBASE","type":"address"}],["0xaCDc0AB51178d0Ae8F70c1EAd7d3cF5421FDd66D",{"internalType":"address","name":"_counterparty","type":"address"}],["0x16b334f2644cc00b85DB1A1efF0C2C395e00C28d",{"internalType":"address","name":"_configuration","type":"address"}],["0x0000000000000000000000000000000000000000",{"internalType":"address","name":"_whitelist","type":"address"}]],"compiler_version":"0.8.26+commit.8a97fa7a","is_verified_via_verifier_alliance":false,"verified_at":"2025-12-01T15:23:45.118924Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x610120604052348015610010575f80fd5b5060405161611b38038061611b83398101604081905261002f91610073565b6001600160a01b0394851660805292841660e05290831660a052821660c05216610100526100d4565b80516001600160a01b038116811461006e575f80fd5b919050565b5f805f805f60a08688031215610087575f80fd5b61009086610058565b945061009e60208701610058565b93506100ac60408701610058565b92506100ba60608701610058565b91506100c860808701610058565b90509295509295909350565b60805160a05160c05160e05161010051615edd61023e5f395f81816108ff0152818161349301526134ec01525f818161092e01528181611d0801528181611d3a015281816126eb0152818161271d01528181612dd501528181612e070152818161372f015281816142e101528181614581015261511101525f81816107ac01528181610f45015281816110f40152818161186c015281816119c3015281816127d001528181612eba015281816135910152818161365d0152818161382901526144e101525f8181610a24015281816111de015281816112bf015281816113b0015281816116c0015281816117a801528181611f2f0152818161238c015261261201525f81816107d3015281816118dd01528181611bfc015281816120b201528181612a1a0152818161446c015281816146020152818161462901528181614ef301528181614f6b015281816150230152818161509b015281816151af01526151f10152615edd5ff3fe608060405234801561000f575f80fd5b506004361061040c575f3560e01c80636e49db1c11610221578063ba4bf7d01161012a578063d2001124116100b4578063eedfb05f11610084578063eedfb05f14610acb578063f03577fa14610ade578063f415afd714610af1578063f899980a14610b04578063f9260a8d14610b0c575f80fd5b8063d200112414610a7f578063d547741f14610a92578063d7d7442f14610aa5578063d890cba914610ab8575f80fd5b8063c1c8f15b116100fa578063c1c8f15b14610a0c578063c3df654614610a1f578063c52d087b14610a46578063cbf0b0c014610a59578063d1903fed14610a6c575f80fd5b8063ba4bf7d0146109b4578063bedb86fb146109d3578063bf6f5b00146109e6578063c1342574146109f9575f80fd5b806393e59dc1116101ab578063a4b32de81161017b578063a4b32de814610957578063a69f49351461097e578063aa05d03d14610986578063acdd515a14610999578063b754d58d146109a1575f80fd5b806393e59dc1146108fa5780639bd3bd38146109215780639d8c291014610929578063a217fddf14610950575f80fd5b806385184db7116101f157806385184db71461084157806386403125146108545780638e57338d146108b557806391d14854146108c857806393014f46146108db575f80fd5b80636e49db1c146107f557806372838c91146108085780637f51bb1f1461081b578063807d3f1d1461082e575f80fd5b80632b83cccd116103235780634ac6f0e0116102ad5780635cb3ccaa1161027d5780635cb3ccaa1461076557806361d027b31461076d57806363a560ec146107805780636c70bee9146107a75780636dbe4bb9146107ce575f80fd5b80634ac6f0e0146106b25780635224372c146106da57806352a9039c146106ed5780635c975abb1461074e575f80fd5b806334c63d3e116102f357806334c63d3e1461065d57806336568abe146106705780633eb9c694146106835780633f0292c21461069657806349bc779b1461069f575f80fd5b80632b83cccd146105f65780632bb6bc15146106095780632dfc2001146106375780632f2ff15d1461064a575f80fd5b80631ace9a7c116103a457806322e7d89e1161037457806322e7d89e146105965780632354d83f146105a9578063248a9ca3146105b1578063269ef793146105c4578063285ab4c3146105d7575f80fd5b80631ace9a7c146105365780631da649cf146105495780631da717be1461055c57806320df43591461056f575f80fd5b80630b0eee30116103df5780630b0eee30146104d35780630c932dc8146104e85780630e5c011e146104fb578063153f7cd014610523575f80fd5b806301ffc9a7146104105780630266f0441461043857806303018c111461046357806306bfa93814610498575b5f80fd5b61042361041e36600461556c565b610b2b565b60405190151581526020015b60405180910390f35b60035461044b906001600160a01b031681565b6040516001600160a01b03909116815260200161042f565b61048a7f1be5d1ebf823e636f9019a4a28b5fb56a6c9c490fea63cb140cde243b9045b5381565b60405190815260200161042f565b6104ab6104a63660046155a7565b610b61565b604080519586526020860194909452928401919091526060830152608082015260a00161042f565b6104e66104e13660046155c2565b610bf2565b005b6104e66104f63660046155a7565b610d4f565b61050e6105093660046155a7565b610d66565b6040805192835260208301919091520161042f565b6104e66105313660046155a7565b6111c9565b60055461044b906001600160a01b031681565b6104e66105573660046155ec565b6111dc565b6104e661056a3660046155ec565b6113ae565b61048a7fbf233dd2aafeb4d50879c4aa5c81e96d92f6e6945c906a58f9f2d1c1631b4b2681565b6104e66105a4366004615642565b611652565b61048a611689565b61048a6105bf366004615682565b61169e565b6104e66105d23660046155ec565b6116be565b61048a6105e53660046155a7565b60046020525f908152604090205481565b61050e610604366004615699565b61181a565b61061c6106173660046156cb565b611cc9565b6040805193845260208401929092529082015260600161042f565b61048a6106453660046155c2565b611f2c565b6104e6610658366004615728565b612182565b6104e661066b36600461576c565b61219e565b6104e661067e366004615728565b6121f6565b6104e661069136600461576c565b61222e565b61048a609b5481565b6104e66106ad3660046157a5565b612273565b61044b6106c03660046155a7565b60996020525f90815260409020546001600160a01b031681565b6104e66106e83660046155ec565b61238a565b6107276106fb3660046155a7565b60646020525f90815260409020546001600160a01b03811690600160a01b90046001600160601b031682565b604080516001600160a01b0390931683526001600160601b0390911660208301520161042f565b5f80516020615e888339815191525460ff16610423565b61048a61269c565b60015461044b906001600160a01b031681565b61048a7f3fc733b4d20d27a28452ddf0e9351aced28242fe03389a653cdb783955316b9b81565b61044b7f000000000000000000000000000000000000000000000000000000000000000081565b61044b7f000000000000000000000000000000000000000000000000000000000000000081565b61061c61080336600461581b565b6126ac565b6104e661081636600461585e565b612984565b6104e66108293660046155a7565b61299d565b6104e661083c3660046155c2565b6129b0565b6104e661084f366004615877565b612b34565b61088e6108623660046155a7565b609a6020525f90815260409020546001600160601b03811690600160601b90046001600160a01b031682565b604080516001600160601b0390931683526001600160a01b0390911660208301520161042f565b6104e66108c33660046158e8565b612c44565b6104236108d6366004615728565b612c79565b61048a6108e93660046155a7565b60086020525f908152604090205481565b61044b7f000000000000000000000000000000000000000000000000000000000000000081565b61048a612caf565b61044b7f000000000000000000000000000000000000000000000000000000000000000081565b61048a5f81565b61048a7fb1fadd3142ab2ad7f1337ea4d97112bcc8337fc11ce5b20cb04ad038adf9981981565b61048a612cbf565b6104e66109943660046155c2565b612cce565b61048a612d2e565b60025461044b906001600160a01b031681565b61048a6109c23660046155a7565b609c6020525f908152604090205481565b6104e66109e13660046159a9565b612d3d565b6104e66109f436600461585e565b612d7d565b61061c610a0736600461581b565b612d96565b61048a610a1a3660046159c4565b613238565b61044b7f000000000000000000000000000000000000000000000000000000000000000081565b60075461044b906001600160a01b031681565b6104e6610a673660046155a7565b61324f565b61048a610a7a3660046155a7565b613335565b6104e6610a8d3660046155a7565b61333f565b6104e6610aa0366004615728565b613352565b6104e6610ab3366004615682565b61336e565b6104e6610ac63660046159fc565b613381565b6104e6610ad936600461585e565b613429565b6104e6610aec3660046155a7565b613442565b61048a610aff366004615a29565b613455565b61048a613abe565b61048a610b1a3660046155a7565b60066020525f908152604090205481565b5f6001600160e01b03198216637965db0b60e01b1480610b5b57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6001600160a01b0381165f908152609860205260408120548190819081908190610b8d81836055613aca565b9550610b9b81605580613aca565b9450610baa8160aa6056613aca565b6001600160a01b0388165f90815260986020526040812060010154919550909150610bd89082906060613aca565b9250610be681606080613aca565b91505091939590929450565b7fb1fadd3142ab2ad7f1337ea4d97112bcc8337fc11ce5b20cb04ad038adf99819610c1c81613ad8565b6001600160a01b038381165f908152606460209081526040808320815180830183529054948516808252600160a01b9095046001600160601b03168184015281516318160ddd60e01b815291519094926318160ddd92600480820193918290030181865afa158015610c90573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cb49190615a7b565b60208301519091506001600160601b0316610ccf8583615aa6565b1115610cd9575f80fd5b8151610cf0906001600160a01b0387169086613ae5565b815160405163b6b55f2560e01b8152600481018690526001600160a01b039091169063b6b55f25906024015f604051808303815f87803b158015610d32575f80fd5b505af1158015610d44573d5f803e3d5ffd5b505050505050505050565b5f610d5981613ad8565b610d6282613b3d565b5050565b5f8082610d74609682613b97565b610d915760405163aaaf1ba760e01b815260040160405180910390fd5b7f3fc733b4d20d27a28452ddf0e9351aced28242fe03389a653cdb783955316b9b610dbb81613ad8565b610dc3613bbb565b5f856001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e00573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e249190615ab9565b90505f610e3082613c05565b6001600160a01b0388165f90815260986020526040812054919250908190610e5a81605580613aca565b9250610e698160aa6056613aca565b9150505f805f8b6001600160a01b031663ee65a03c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610eab573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ecf9190615a7b565b90508084111561102c57610ee581850387613cb5565b9950610ef88c8b5f038387035f03613cd3565b633b9aca008a610f06611689565b0281610f1457610f14615ad4565b049250633b9aca008a610f25612cbf565b0281610f3357610f33615ad4565b0491508282018a039950610ff58c888c7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637ef502987ffc3e964b6f9d1c4d43e30c57b170a183d35f574c0854a499e0c90f8fa253d5bd6040518263ffffffff1660e01b8152600401610fb191815260200190565b602060405180830381865afa158015610fcc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ff09190615ab9565b613d8f565b6001600160a01b038c165f9081526098602052604090205461101981605580613aca565b95506110288160aa6056613aca565b9450505b6110368587613ec7565b9050838111156111235761104c84820387613cb5565b9a5061105b8c8c5f035f613cd3565b5f633b9aca008c61106a612d2e565b028161107857611078615ad4565b0490505f633b9aca008d61108a612cbf565b028161109857611098615ad4565b604051630fdea05360e31b81527ff7670fa3906d826444885d9b61a4246afaf9f48a2f7a2ec4cd843e23dcf7d2da6004820152919004838101909e039d9590920194939093019250611123908d9089908e906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637ef5029890602401610fb1565b821561114457600154611144908d90899086906001600160a01b0316613d8f565b61114d8c613edb565b811561115f5761115f8c888433613d8f565b604080518c8152602081018c90528082018590526060810184905290516001600160a01b038e169133917fb97aa24214e8edbddacca4eccaa3910b760a7aa10a284e8b782d12f1137a75619181900360800190a3505050505050506111c2614039565b5050915091565b5f6111d381613ad8565b610d628261405f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316331461122557604051637f02477f60e11b815260040160405180910390fd5b82611231609682613b97565b61124e5760405163aaaf1ba760e01b815260040160405180910390fd5b611256613bbb565b5f846001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611293573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112b79190615ab9565b90506112e5817f000000000000000000000000000000000000000000000000000000000000000030866140b9565b836001600160a01b031663ecf1a3a66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611321573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113459190615ab9565b6001600160a01b0316639dc29fac30856040518363ffffffff1660e01b8152600401611372929190615ae8565b5f604051808303815f87803b158015611389575f80fd5b505af115801561139b573d5f803e3d5ffd5b50505050506113a8614039565b50505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633146113f757604051637f02477f60e11b815260040160405180910390fd5b82611403609682613b97565b6114205760405163aaaf1ba760e01b815260040160405180910390fd5b611428613bbb565b5f846001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611465573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114899190615ab9565b90505f61149582613c05565b90505f6114a28583613ec7565b60405163e273fa8760e01b8152600481018290529091506001600160a01b0388169063e273fa87906024015f604051808303815f87803b1580156114e4575f80fd5b505af11580156114f6573d5f803e3d5ffd5b50505050611516878661150890615b01565b61151184615b01565b613cd3565b5f866001600160a01b031663ecf1a3a66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611553573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115779190615ab9565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038316906370a0823190602401602060405180830381865afa1580156115be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115e29190615a7b565b9050801561139b57604051632770a7eb60e21b81526001600160a01b03831690639dc29fac906116189030908590600401615ae8565b5f604051808303815f87803b15801561162f575f80fd5b505af1158015611641573d5f803e3d5ffd5b5050505050505050506113a8614039565b5f61165c81613ad8565b61166b8463ffffffff166140d4565b61167a8363ffffffff16614130565b6113a88263ffffffff16614185565b5f8054611699906078601e613aca565b905090565b5f9081525f80516020615e68833981519152602052604090206001015490565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316331461170757604051637f02477f60e11b815260040160405180910390fd5b82611713609682613b97565b6117305760405163aaaf1ba760e01b815260040160405180910390fd5b611738613bbb565b826001600160a01b031663ecf1a3a66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611774573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117989190615ab9565b6001600160a01b0316639dc29fac7f0000000000000000000000000000000000000000000000000000000000000000846040518363ffffffff1660e01b81526004016117e5929190615ae8565b5f604051808303815f87803b1580156117fc575f80fd5b505af115801561180e573d5f803e3d5ffd5b505050506113a8614039565b5f8084611828609682613b97565b6118455760405163aaaf1ba760e01b815260040160405180910390fd5b61184d613bbb565b6118556141da565b604051630bff4bf360e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632ffd2fcc906118ae9030906001600160e01b03195f351690600401615b1b565b5f604051808303815f87803b1580156118c5575f80fd5b505af11580156118d7573d5f803e3d5ffd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a082316119113390565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611953573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119779190615a7b565b851115611997576040516307889a5d60e21b815260040160405180910390fd5b68056bc75e2d631000008510156119c1576040516326d643e360e11b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c00c2ceb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a1d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a419190615b3e565b611a5e576040516321e6770560e11b815260040160405180910390fd5b60405163db006a7560e01b8152600481018690525f906001600160a01b0388169063db006a759060240160408051808303815f875af1158015611aa3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ac79190615b59565b80925081955050508395505f876001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b0f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b339190615ab9565b90505f611b3f82613c05565b9050611b4b8382613cb5565b9450611b6389611b5a87615b01565b61151186615b01565b611b7589611b708a615b01565b61420c565b5f633b9aca00611b8361269c565b870281611b9257611b92615ad4565b049050611bbb8a826001600160a01b039091165f90815260086020526040902080549091019055565b808603955087861015611be157604051630f29910b60e31b815260040160405180910390fd5b611bed8a848833613d8f565b604051632770a7eb60e21b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690639dc29fac90611c3b9033908d90600401615ae8565b5f604051808303815f87803b158015611c52575f80fd5b505af1158015611c64573d5f803e3d5ffd5b505060408051898152602081018d90529081018490526001600160a01b038d1692507fbd5034ffbd47e4e72a94baa2cdb74c6fad73cb3bcdc13036b72ec8306f5a7646915060600160405180910390a250505050611cc0614039565b50935093915050565b5f808087611cd8609682613b97565b611cf55760405163aaaf1ba760e01b815260040160405180910390fd5b611cfd613bbb565b611d056141da565b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614611dd657609b547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d94573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611db89190615a7b565b10611dd657604051639544786b60e01b815260040160405180910390fd5b5f611de08a6142a3565b90505f611df087835f0151613ec7565b88019050670de0b6b3a7640000811015611e1d5760405163880cbfe760e01b815260040160405180910390fd5b604051630723d57160e01b815260018a900b6004820152602481018290525f906001600160a01b038d1690630723d571906044016060604051808303815f875af1158015611e6d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e919190615b7b565b60408101805182510160608601525160808501526020015160a084015250611ebd90508a88838c6143ea565b60408051848152602081018490529081018290529297509095509350600189900b906001600160a01b038c16907ff8cdb1f9af03fbf36ddb1d43fce878a63592deba4f09a82777616f3019aa6c4d9060600160405180910390a350611f20614039565b50955095509592505050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314611f7657604051637f02477f60e11b815260040160405180910390fd5b82611f82609682613b97565b611f9f5760405163aaaf1ba760e01b815260040160405180910390fd5b611fa7613bbb565b5f846001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fe4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120089190615ab9565b90505f61201482613c05565b604051630d65a06b60e41b815260048101879052600160248201529091505f906001600160a01b0388169063d65a06b09060440160408051808303815f875af1158015612063573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120879190615b59565b9150506120948183613cb5565b94506120a38761150887615b01565b604051632770a7eb60e21b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690639dc29fac906120f19033908a90600401615ae8565b5f604051808303815f87803b158015612108575f80fd5b505af115801561211a573d5f803e3d5ffd5b5050505061212c8787611b7090615b01565b60408051868152602081018890526001600160a01b038916917f8a71ee13bf13e8b561796365ba04cdca906b2944b6ba975995fb5ba8c2955d57910160405180910390a250505061217b614039565b5092915050565b61218b8261169e565b61219481613ad8565b6113a88383614721565b5f6121a881613ad8565b6121b36096856147c2565b156113a8576040516001600160a01b038516907fdfc596fabc6581c887262c97695176a79e3c8fc6ab7aaf14700820f3436b8fb9905f90a26113a88484846147d6565b6001600160a01b038116331461221f5760405163334bd91960e11b815260040160405180910390fd5b61222982826148ad565b505050565b5f61223881613ad8565b83612244609682613b97565b6122615760405163aaaf1ba760e01b815260040160405180910390fd5b61226c8585856147d6565b5050505050565b5f61227c614926565b805490915060ff600160401b820416159067ffffffffffffffff165f811580156122a35750825b90505f8267ffffffffffffffff1660011480156122bf5750303b155b9050811580156122cd575080155b156122eb5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561231557845460ff60401b1916600160401b1785555b61231f5f8d614721565b5061232e8b8b8b8b8b8b61494e565b6123366149b8565b831561237c57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633146123d357604051637f02477f60e11b815260040160405180910390fd5b826123df609682613b97565b6123fc5760405163aaaf1ba760e01b815260040160405180910390fd5b612404613bbb565b5f836001600160a01b031663ecf1a3a66040518163ffffffff1660e01b8152600401602060405180830381865afa158015612441573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124659190615ab9565b90505f856001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156124a4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124c89190615ab9565b90505f6124d482613c05565b90505f876001600160a01b031663ee65a03c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612513573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125379190615a7b565b90505f6125448284613cb5565b90505f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612583573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125a79190615a7b565b90506125b38882615aa6565b6001600160a01b038b165f908152609c6020526040902054670de0b6b3a7640000906125df9085615bd4565b6125e99190615beb565b1015612608576040516319d5157560e31b815260040160405180910390fd5b50505061263682867f00000000000000000000000000000000000000000000000000000000000000006149c0565b6040516340c10f1960e01b81526001600160a01b038416906340c10f19906126649030908990600401615ae8565b5f604051808303815f87803b15801561267b575f80fd5b505af115801561268d573d5f803e3d5ffd5b505050505050506113a8614039565b5f805461169990605a601e613aca565b5f8080866126bb609682613b97565b6126d85760405163aaaf1ba760e01b815260040160405180910390fd5b6126e0613bbb565b6126e86141da565b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146127b957609b547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612777573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061279b9190615a7b565b106127b957604051639544786b60e01b815260040160405180910390fd5b604051630bff4bf360e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632ffd2fcc906128129030906001600160e01b03195f351690600401615b1b565b5f604051808303815f87803b158015612829575f80fd5b505af115801561283b573d5f803e3d5ffd5b505050505f612849896142a3565b90505f61285987835f0151613ec7565b88019050670de0b6b3a76400008110156128865760405163880cbfe760e01b815260040160405180910390fd5b604051631e93260360e31b8152600481018290525f906001600160a01b038c169063f4993018906024016060604051808303815f875af11580156128cc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128f09190615b7b565b60408101805182510160608601525160808501526020015160a08401525061291c90508988838b6143ea565b604080518481526020810184905290810182905292975090955093506001600160a01b038a16907f2ee87fe08e822e20d39eb53e4cfe022c750e0b72e3dfafa2413b41b61f3dacc59060600160405180910390a250612979614039565b509450945094915050565b5f61298e81613ad8565b610d628263ffffffff16614b17565b5f6129a781613ad8565b610d6282614b6c565b816129bc609682613b97565b6129d95760405163aaaf1ba760e01b815260040160405180910390fd5b7f1be5d1ebf823e636f9019a4a28b5fb56a6c9c490fea63cb140cde243b9045b53612a0381613ad8565b612a0b613bbb565b604051632770a7eb60e21b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690639dc29fac90612a599033908790600401615ae8565b5f604051808303815f87803b158015612a70575f80fd5b505af1158015612a82573d5f803e3d5ffd5b505060405163193cefdd60e31b8152600481018690526001600160a01b038716925063c9e77ee891506024015f604051808303815f87803b158015612ac5575f80fd5b505af1158015612ad7573d5f803e3d5ffd5b50505050612ae98484611b7090615b01565b836001600160a01b03167f243d60a280579accabafa82109d7f67f7ce230d575b0ff7a301e8dabf3a3f50584604051612b2491815260200190565b60405180910390a26113a8614039565b5f612b3e81613ad8565b5f836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b7b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b9f9190615bfe565b612baa906012615c1e565b612bb590600a615d1a565b6040805180820182526001600160601b0383811682526001600160a01b0387811660208085018281528b84165f818152609a845288902096519151909416600160601b02941693909317909355835185815291820192909252929350917f5eae3446f897bd3bbec9c0c4bfa76e39caf18a7b1a0ed8e89de3aea8a297acae91015b60405180910390a250505050565b5f5b8151811015610d6257612c71828281518110612c6457612c64615d28565b6020026020010151613edb565b600101612c46565b5f9182525f80516020615e68833981519152602090815260408084206001600160a01b0393909316845291905290205460ff1690565b5f8054611699906096601e613aca565b5f805461169990601e80613aca565b5f612cd881613ad8565b6001600160a01b0383165f818152609c6020908152604091829020805490869055825181815291820186905292917fb5905b07f0c450b4bfc9df549639d6d41a561c63f983efb2d22b6710a147d9c09101612c36565b5f80546116999082601e613aca565b7fbf233dd2aafeb4d50879c4aa5c81e96d92f6e6945c906a58f9f2d1c1631b4b26612d6781613ad8565b8115612d7557610d62614bc6565b610d62614c28565b5f612d8781613ad8565b610d628263ffffffff16614c6d565b5f808086612da5609682613b97565b612dc25760405163aaaf1ba760e01b815260040160405180910390fd5b612dca613bbb565b612dd26141da565b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614612ea357609b547f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e61573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e859190615a7b565b10612ea357604051639544786b60e01b815260040160405180910390fd5b604051630bff4bf360e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632ffd2fcc90612efc9030906001600160e01b03195f351690600401615b1b565b5f604051808303815f87803b158015612f13575f80fd5b505af1158015612f25573d5f803e3d5ffd5b505050505f612f33896142a3565b90505f612f4387835f0151613ec7565b612f4d9089615aa6565b9050670de0b6b3a7640000811015612f78576040516307a1b46360e01b815260040160405180910390fd5b612f9f60405180608001604052805f81526020015f81526020015f81526020015f81525090565b600354604084810151905163f8b2cb4f60e01b81526001600160a01b0391821660048201525f92919091169063f8b2cb4f90602401602060405180830381865afa158015612fef573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130139190615a7b565b9050613023818560200151613ec7565b60405163d296d1f160e01b815260048101859052602481018290529091506001600160a01b038d169063d296d1f1906044016080604051808303815f875af1158015613071573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130959190615d3c565b60408101805182510160608088019190915290516080870152602082015160a087015281015190925080156131cb576130d683606001518660200151613cb5565b905060035f9054906101000a90046001600160a01b03166001600160a01b031663565659ea8e6001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa158015613137573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061315b9190615ab9565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604481018490526064015f604051808303815f87803b1580156131a6575f80fd5b505af11580156131b8573d5f803e3d5ffd5b505050506131cb8d828560600151613cd3565b5050506131da8a89848c6143ea565b604080518481526020810184905290810182905292985090965094506001600160a01b038b16907f158ba9ab7bbbd08eeffa4753bad41f4d450e24831d293427308badf3eadd8c769060600160405180910390a25050612979614039565b5f613246858585855f613455565b95945050505050565b5f61325981613ad8565b6001600160a01b038281165f90815260646020908152604091829020825180840190935254928316808352600160a01b9093046001600160601b031690820152901561222957805f01516001600160a01b03166341c0e1b56040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156132da575f80fd5b505af11580156132ec573d5f803e3d5ffd5b50505f80845260208085018281526001600160a01b03888116845260649092526040909220855192516001600160601b0316600160a01b02929091169190911790555050505050565b5f610b5b82613c05565b5f61334981613ad8565b610d6282614cc1565b61335b8261169e565b61336481613ad8565b6113a883836148ad565b5f61337881613ad8565b610d6282614d1b565b5f61338b81613ad8565b6001600160a01b038481165f90815260646020908152604091829020825180840190935254928316808352600160a01b9093046001600160601b03169082015290156133da576133da8561324f565b50506040805180820182526001600160a01b0393841681526001600160601b0392831660208083019182529585165f90815260649096529190942093519051909116600160a01b029116179055565b5f61343381613ad8565b610d628263ffffffff16614d59565b5f61344c81613ad8565b610d6282614dae565b5f85613462609682613b97565b61347f5760405163aaaf1ba760e01b815260040160405180910390fd5b613487613bbb565b61348f6141da565b333b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316158015906134d257505f8111806134d25750333214155b1561357a57604051631846d2f560e31b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c23697a890602401602060405180830381865afa158015613539573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061355d9190615b3e565b61357a57604051632c10e80160e21b815260040160405180910390fd5b604051630bff4bf360e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632ffd2fcc906135d39030906001600160e01b03195f351690600401615b1b565b5f604051808303815f87803b1580156135ea575f80fd5b505af11580156135fc573d5f803e3d5ffd5b505050506136556040518061014001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81525090565b84156137b0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639db4a5536040518163ffffffff1660e01b8152600401602060405180830381865afa1580156136b7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136db9190615b3e565b6136f8576040516378bcd3ab60e11b815260040160405180910390fd5b5f87138061370657505f8612155b8061370f575087155b1561372d57604051630549b09160e31b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633fd7ebe96040518163ffffffff1660e01b8152600401602060405180830381865afa158015613789573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906137ad9190615a7b565b81525b5f896001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138119190615ab9565b90505f61381d82613c05565b90506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016631a4a400f8c336040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401608060405180830381865afa158015613899573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138bd9190615d9f565b60808701526060860152604085015260208401525f8913156138ec576138e98b838b8660200151614e08565b98505b8888600160ff1b8214613906576139038284614e47565b91505b8880156139175750600160ff1b8114155b1561392c5761392981865f0151614e47565b90505b6001600160a01b038d1663032d22768d8484336040516001600160e01b031960e087901b1681526004810194909452602484019290925260448301526001600160a01b031660648201526084016080604051808303815f875af1158015613995573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906139b99190615d9f565b50919d50925090506139cb8284614e65565b9a506139d78d8261420c565b5f8213156139ef576139ea8d8c84613cd3565b613a18565b5f821215613a1857613a188d85613a058e615b01565b613a0e86615b01565b8960400151614e79565b5f811315613a3357613a2e818660600151614eca565b613a53565b5f811215613a5357613a53613a4782615b01565b60808701518751614fde565b604080518c8152602081018390525f918101919091528c906001600160a01b038f16907f9a243f0f02273a4b80be965697988a178f95cd11863de2122e69f811445dff449060600160405180910390a38b9750505050505050613ab4614039565b5095945050505050565b5f805461169990603c601e5b6001901b5f190191901c1690565b613ae28133615228565b50565b61222983846001600160a01b031663a9059cbb8585604051602401613b0b929190615ae8565b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505061525c565b613b46816152c8565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fe5110bb0e516861a91fc6865f2b0c0540cceff8cec2bfaaa5b032979e13c7e41905f90a35050565b6001600160a01b0381165f90815260018301602052604081205415155b9392505050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00805460011901613bff57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b6001600160a01b038082165f908152609a60205260409020546001600160601b03811691600160601b909104168015613ca157806001600160a01b031663679aefce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613c74573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613c989190615a7b565b82029150613caf565b670de0b6b3a7640000820291505b50919050565b5f81613cc9670de0b6b3a764000085615bd4565b613bb49190615beb565b6001600160a01b0383165f9081526098602052604081205490613cf882826055613aca565b90505f84613d0884605580613aca565b613d129190615dd2565b905081811115613d355760405163f646f2f960e01b815260040160405180910390fd5b613d4283826055806152ef565b925083613d528460aa6056613aca565b613d5c9190615dd2565b9050613d6c838260aa60566152ef565b6001600160a01b039096165f908152609860205260409020959095555050505050565b5f846001600160a01b031663c3df65466040518163ffffffff1660e01b8152600401602060405180830381865afa158015613dcc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613df09190615ab9565b90506001600160a01b03811615613ebc575f613e0b85615303565b9050808411613e2457613e1f8585856149c0565b613eb6565b5f826001600160a01b031663ecf1a3a66040518163ffffffff1660e01b8152600401602060405180830381865afa158015613e61573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613e859190615ab9565b90505f613e928387615df9565b9050613ea86001600160a01b0383168683613ae5565b613eb38784876149c0565b50505b5061226c565b61226c8484846149c0565b5f670de0b6b3a7640000613cc98385615bd4565b5f816001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa158015613f18573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613f3c9190615ab9565b6001600160a01b0383165f908152600460205260409020549091508015613f9157600254613f78908490849084906001600160a01b0316613d8f565b6001600160a01b0383165f908152600460205260408120555b506001600160a01b0382165f908152600660205260409020548015613fe457600554613fcb908490849084906001600160a01b0316613d8f565b6001600160a01b0383165f908152600660205260408120555b506001600160a01b0382165f9081526008602052604090205480156122295760075461401e908490849084906001600160a01b0316613d8f565b50506001600160a01b03165f90815260086020526040812055565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b614068816152c8565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f3ed91ef70e6e7c6a805523d1a95ddc27851b8f620524b5def16053d07bc33c32905f90a35050565b80156113a8576113a86001600160a01b038516848484615408565b6140e281631dcd6500615441565b5f6140ef825f601e615462565b60408051828152602081018590529192507f77cf0faf60882cf7bf063a7308f5b2f7acc4c4cf6118126dc6f45a3fc19a05d191015b60405180910390a15050565b61413e81631dcd6500615441565b5f61414c826078601e615462565b60408051828152602081018590529192507f38a939f96f90bf373822856f3ca5959e9f2fa4d92dfd22cc236d692ac15c80ff9101614124565b61419381631dcd6500615441565b5f6141a1826096601e615462565b60408051828152602081018590529192507fc47c244bb9022fbfd61c1961e43c3f6100aba94a7196cca3e6743b6ec04f7d099101614124565b5f80516020615e888339815191525460ff161561420a5760405163d93c066560e01b815260040160405180910390fd5b565b6001600160a01b0382165f908152609860205260408120600101549061423482826060613aca565b90505f8361424484606080613aca565b61424e9190615dd2565b90508181111561427157604051631b2f832360e21b815260040160405180910390fd5b61427e83826060806152ef565b6001600160a01b039095165f9081526098602052604090206001019490945550505050565b6142df6040518060c001604052805f81526020015f81526020015f6001600160a01b031681526020015f81526020015f81526020015f81525090565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633fd7ebe96040518163ffffffff1660e01b8152600401602060405180830381865afa15801561433b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061435f9190615a7b565b815f018181525050816001600160a01b031663b2016bd46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156143a3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906143c79190615ab9565b6001600160a01b0316604082018190526143e090613c05565b6020820152919050565b5f805f6143ff85606001518660200151613cb5565b925061441c8761440e85615b01565b876060015161151190615b01565b61442e878660a00151611b7090615b01565b8460a001519150858211156144575761445161444a8784615df9565b8651615488565b90508591505b81156144d957604051632770a7eb60e21b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690639dc29fac906144ab9033908690600401615ae8565b5f604051808303815f87803b1580156144c2575f80fd5b505af11580156144d4573d5f803e3d5ffd5b505050505b80156146b9577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639db4a5536040518163ffffffff1660e01b8152600401602060405180830381865afa15801561453b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061455f9190615b3e565b61457c576040516378bcd3ab60e11b815260040160405180910390fd5b6146277f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9d75b2b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156145db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906145ff9190615ab9565b337f0000000000000000000000000000000000000000000000000000000000000000846140b9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631ae94cde82888860a001516146679190615df9565b6040516001600160e01b031960e085901b168152600481019290925260248201526044015f604051808303815f87803b1580156146a2575f80fd5b505af11580156146b4573d5f803e3d5ffd5b505050505b5f633b9aca006146c7612caf565b6146d988608001518960200151613cb5565b6146e39190615bd4565b6146ed9190615beb565b6001600160a01b0389165f908152600860205260409020805482019055905080840393506129798887604001518688613d8f565b5f5f80516020615e6883398151915261473a8484612c79565b6147b9575f848152602082815260408083206001600160a01b03871684529091529020805460ff1916600117905561476f3390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a46001915050610b5b565b5f915050610b5b565b5f613bb4836001600160a01b0384166154b3565b6001600160a01b0383165f90815260986020526040812054614804916001600160601b0385169060556152ef565b6001600160a01b0384165f90815260986020526040812091825560019091015461483a916001600160601b0384169060606152ef565b6001600160a01b0384165f81815260986020526040908190206001019290925590517fe02c6e99b21daa3ddf5404c5d54ac9c919fe91ab12e1e72665dc1fd8bc865467906148a090859085906001600160601b0392831681529116602082015260400190565b60405180910390a2505050565b5f5f80516020615e688339815191526148c68484612c79565b156147b9575f848152602082815260408083206001600160a01b0387168085529252808320805460ff1916905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a46001915050610b5b565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610b5b565b6149566154ff565b61495f86614130565b614968866140d4565b61497186614185565b61497a85614c6d565b61498384614b17565b61498c83614b6c565b61499582614dae565b61499e82613b3d565b6149a782614cc1565b6149b08161405f565b505050505050565b61420a6154ff565b6040516370a0823160e01b81523060048201525f906001600160a01b038516906370a0823190602401602060405180830381865afa158015614a04573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614a289190615a7b565b9050828110614a4a57614a456001600160a01b0385168385613ae5565b6113a8565b8015614a6457614a646001600160a01b0385168383613ae5565b6001600160a01b038481165f90815260646020908152604091829020825180840190935254928316808352600160a01b9093046001600160601b03169082015282850391614ab0575f80fd5b8051604051627b8a6760e11b8152600481018490526001600160a01b0386811660248301529091169062f714ce906044015b5f604051808303815f87803b158015614af9575f80fd5b505af1158015614b0b573d5f803e3d5ffd5b50505050505050505050565b614b25816305f5e100615441565b5f614b3382603c601e615462565b60408051828152602081018590529192507f6435b9a85963bf02d1ea1c96162e6e48e3cf1112e4b029810eba42e10532e5a99101614124565b614b75816152c8565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd101a15f9e9364a1c0a7c4cc8eb4cd9220094e83353915b0c74e09f72ec73edb905f90a35050565b614bce6141da565b5f80516020615e88833981519152805460ff191660011781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258335b6040516001600160a01b03909116815260200160405180910390a150565b614c30615524565b5f80516020615e88833981519152805460ff191681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33614c0a565b614c7b81630bebc200615441565b5f614c8882601e80615462565b60408051828152602081018590529192507f2c3b971a5011a057ee9b96ea2aa1504d93d268e5c9cfdee7581d31435b24435e9101614124565b614cca816152c8565b600780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fbcfa1f4a44edd726cc4f3c7dca57d46a5a8e8adb14b1eaae01bc3576059ddd42905f90a35050565b609b80549082905560408051828152602081018490527f87b7851a3d0ea68ea4815a7d26786f79a1395130f36977b4cae075de129f3cbd9101614124565b614d67816305f5e100615441565b5f614d7582605a601e615462565b60408051828152602081018590529192507fbf5383b9e422a4efef091bed41e294217b4a7c7adfbed0dc4d48588bac69afa89101614124565b614db7816152c8565b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f731b9ea4fb17ff346b10938712cc430bfa7ba2198f0d2d66a9594804ddf56bc2905f90a35050565b6001600160a01b0384165f9081526004602052604081208054633b9aca0084860204908101909155614e3c853330876140b9565b909203949350505050565b5f670de0b6b3a7640000614e5b8385615e0c565b613bb49190615e3b565b5f81614e5b670de0b6b3a764000085615e0c565b614e8f85614e8685615b01565b61151185615b01565b633b9aca00818402048015614ebc576001600160a01b0386165f9081526006602052604090208054820190555b6149b0868683870333613d8f565b633b9aca00818302048015614f5c576002546040516340c10f1960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116926340c10f1992614f2e9291909116908590600401615ae8565b5f604051808303815f87803b158015614f45575f80fd5b505af1158015614f57573d5f803e3d5ffd5b505050505b6040516340c10f1960e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f1990614fac90339085880390600401615ae8565b5f604051808303815f87803b158015614fc3575f80fd5b505af1158015614fd5573d5f803e3d5ffd5b50505050505050565b828115614ff257614fef8483613cb5565b90505b633b9aca00838202045f83900361510e57801561508c576005546040516340c10f1960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116926340c10f199261505e9291909116908590600401615ae8565b5f604051808303815f87803b158015615075575f80fd5b505af1158015615087573d5f803e3d5ffd5b505050505b604051632770a7eb60e21b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690639dc29fac906150dc90339086860190600401615ae8565b5f604051808303815f87803b1580156150f3575f80fd5b505af1158015615105573d5f803e3d5ffd5b5050505061226c565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9d75b2b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561516b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061518f9190615ab9565b90506151a881336005546001600160a01b0316856140b9565b6151d481337f0000000000000000000000000000000000000000000000000000000000000000866140b9565b604051630d74a66f60e11b815260048101849052602481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631ae94cde90604401614ae2565b6152328282612c79565b610d6257808260405163e2517d3f60e01b8152600401615253929190615ae8565b60405180910390fd5b5f8060205f8451602086015f885af18061527b576040513d5f823e3d81fd5b50505f513d9150811561529257806001141561529f565b6001600160a01b0384163b155b156113a857604051635274afe760e01b81526001600160a01b0385166004820152602401615253565b6001600160a01b038116613ae25760405163a7f9319d60e01b815260040160405180910390fd5b6001901b5f1901811b1992909216911b1790565b6040516370a0823160e01b81523060048201525f9081906001600160a01b038416906370a0823190602401602060405180830381865afa158015615349573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061536d9190615a7b565b6001600160a01b038085165f908152606460205260409020549192501680615396575092915050565b806001600160a01b031663ba5d30786040518163ffffffff1660e01b8152600401602060405180830381865afa1580156153d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906153f69190615a7b565b6154009083615aa6565b949350505050565b6040516001600160a01b0384811660248301528381166044830152606482018390526113a89186918216906323b872dd90608401613b0b565b80821115610d6257604051634df52d2560e11b815260040160405180910390fd5b5f8054615470818585613aca565b915061547e818686866152ef565b5f55509392505050565b5f8160018161549f670de0b6b3a764000087615bd4565b6154a99190615aa6565b613cc99190615df9565b5f8181526001830160205260408120546154f857508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610b5b565b505f610b5b565b615507615553565b61420a57604051631afcd79f60e31b815260040160405180910390fd5b5f80516020615e888339815191525460ff1661420a57604051638dfc202b60e01b815260040160405180910390fd5b5f61555c614926565b54600160401b900460ff16919050565b5f6020828403121561557c575f80fd5b81356001600160e01b031981168114613bb4575f80fd5b6001600160a01b0381168114613ae2575f80fd5b5f602082840312156155b7575f80fd5b8135613bb481615593565b5f80604083850312156155d3575f80fd5b82356155de81615593565b946020939093013593505050565b5f805f606084860312156155fe575f80fd5b833561560981615593565b9250602084013561561981615593565b929592945050506040919091013590565b803563ffffffff8116811461563d575f80fd5b919050565b5f805f60608486031215615654575f80fd5b61565d8461562a565b925061566b6020850161562a565b91506156796040850161562a565b90509250925092565b5f60208284031215615692575f80fd5b5035919050565b5f805f606084860312156156ab575f80fd5b83356156b681615593565b95602085013595506040909401359392505050565b5f805f805f60a086880312156156df575f80fd5b85356156ea81615593565b945060208601356156fa81615593565b93506040860135600181900b8114615710575f80fd5b94979396509394606081013594506080013592915050565b5f8060408385031215615739575f80fd5b82359150602083013561574b81615593565b809150509250929050565b80356001600160601b038116811461563d575f80fd5b5f805f6060848603121561577e575f80fd5b833561578981615593565b925061579760208501615756565b915061567960408501615756565b5f805f805f805f60e0888a0312156157bb575f80fd5b87356157c681615593565b965060208801359550604088013594506060880135935060808801356157eb81615593565b925060a08801356157fb81615593565b915060c088013561580b81615593565b8091505092959891949750929550565b5f805f806080858703121561582e575f80fd5b843561583981615593565b9350602085013561584981615593565b93969395505050506040820135916060013590565b5f6020828403121561586e575f80fd5b613bb48261562a565b5f8060408385031215615888575f80fd5b823561589381615593565b9150602083013561574b81615593565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156158e0576158e06158a3565b604052919050565b5f602082840312156158f8575f80fd5b813567ffffffffffffffff81111561590e575f80fd5b8201601f8101841361591e575f80fd5b803567ffffffffffffffff811115615938576159386158a3565b8060051b615948602082016158b7565b91825260208184018101929081019087841115615963575f80fd5b6020850194505b83851015615991578435925061597f83615593565b8282526020948501949091019061596a565b979650505050505050565b8015158114613ae2575f80fd5b5f602082840312156159b9575f80fd5b8135613bb48161599c565b5f805f80608085870312156159d7575f80fd5b84356159e281615593565b966020860135965060408601359560600135945092505050565b5f805f60608486031215615a0e575f80fd5b8335615a1981615593565b9250602084013561579781615593565b5f805f805f60a08688031215615a3d575f80fd5b8535615a4881615593565b94506020860135935060408601359250606086013591506080860135615a6d8161599c565b809150509295509295909350565b5f60208284031215615a8b575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610b5b57610b5b615a92565b5f60208284031215615ac9575f80fd5b8151613bb481615593565b634e487b7160e01b5f52601260045260245ffd5b6001600160a01b03929092168252602082015260400190565b5f600160ff1b8201615b1557615b15615a92565b505f0390565b6001600160a01b039290921682526001600160e01b031916602082015260400190565b5f60208284031215615b4e575f80fd5b8151613bb48161599c565b5f8060408385031215615b6a575f80fd5b505080516020909101519092909150565b5f6060828403128015615b8c575f80fd5b506040516060810167ffffffffffffffff81118282101715615bb057615bb06158a3565b60409081528351825260208085015190830152928301519281019290925250919050565b8082028115828204841417610b5b57610b5b615a92565b5f82615bf957615bf9615ad4565b500490565b5f60208284031215615c0e575f80fd5b815160ff81168114613bb4575f80fd5b60ff8281168282160390811115610b5b57610b5b615a92565b6001815b6001841115615c7257808504811115615c5657615c56615a92565b6001841615615c6457908102905b60019390931c928002615c3b565b935093915050565b5f82615c8857506001610b5b565b81615c9457505f610b5b565b8160018114615caa5760028114615cb457615cd0565b6001915050610b5b565b60ff841115615cc557615cc5615a92565b50506001821b610b5b565b5060208310610133831016604e8410600b8410161715615cf3575081810a610b5b565b615cff5f198484615c37565b805f1904821115615d1257615d12615a92565b029392505050565b5f613bb460ff841683615c7a565b634e487b7160e01b5f52603260045260245ffd5b5f6080828403128015615d4d575f80fd5b506040516080810167ffffffffffffffff81118282101715615d7157615d716158a3565b6040908152835182526020808501519083015283810151908201526060928301519281019290925250919050565b5f805f8060808587031215615db2575f80fd5b505082516020840151604085015160609095015191969095509092509050565b8082018281125f831280158216821582161715615df157615df1615a92565b505092915050565b81810381811115610b5b57610b5b615a92565b8082025f8212600160ff1b84141615615e2757615e27615a92565b8181058314821517610b5b57610b5b615a92565b5f82615e4957615e49615ad4565b600160ff1b82145f1984141615615e6257615e62615a92565b50059056fe02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800cd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300a264697066735822122067254a36349e2b3c461ad1aee00c5bf63cc0bca40743d2e7440ad1089cd06e0364736f6c634300081a0033000000000000000000000000085780639cc2cacd35e474e71f4d000e2405d8f600000000000000000000000065c9a641afceb9c0e6034e558a319488fa0fa3be000000000000000000000000acdc0ab51178d0ae8f70c1ead7d3cf5421fdd66d00000000000000000000000016b334f2644cc00b85db1a1eff0c2c395e00c28d0000000000000000000000000000000000000000000000000000000000000000","name":"PoolManager","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"cancun","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":true,"additional_sources":[{"file_path":"npm/@openzeppelin/contracts-upgradeable@5.4.0/utils/ContextUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"},{"file_path":"npm/@openzeppelin/contracts-upgradeable@5.4.0/access/AccessControlUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.20;\n\nimport {IAccessControl} from \"@openzeppelin/contracts/access/IAccessControl.sol\";\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport {ERC165Upgradeable} from \"../utils/introspection/ERC165Upgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n *     require(hasRole(MY_ROLE, msg.sender));\n *     ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControl, ERC165Upgradeable {\n    struct RoleData {\n        mapping(address account => bool) hasRole;\n        bytes32 adminRole;\n    }\n\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n\n    /// @custom:storage-location erc7201:openzeppelin.storage.AccessControl\n    struct AccessControlStorage {\n        mapping(bytes32 role => RoleData) _roles;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.AccessControl\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant AccessControlStorageLocation = 0x02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800;\n\n    function _getAccessControlStorage() private pure returns (AccessControlStorage storage $) {\n        assembly {\n            $.slot := AccessControlStorageLocation\n        }\n    }\n\n    /**\n     * @dev Modifier that checks that an account has a specific role. Reverts\n     * with an {AccessControlUnauthorizedAccount} error including the required role.\n     */\n    modifier onlyRole(bytes32 role) {\n        _checkRole(role);\n        _;\n    }\n\n    function __AccessControl_init() internal onlyInitializing {\n    }\n\n    function __AccessControl_init_unchained() internal onlyInitializing {\n    }\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n        AccessControlStorage storage $ = _getAccessControlStorage();\n        return $._roles[role].hasRole[account];\n    }\n\n    /**\n     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n     */\n    function _checkRole(bytes32 role) internal view virtual {\n        _checkRole(role, _msgSender());\n    }\n\n    /**\n     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n     * is missing `role`.\n     */\n    function _checkRole(bytes32 role, address account) internal view virtual {\n        if (!hasRole(role, account)) {\n            revert AccessControlUnauthorizedAccount(account, role);\n        }\n    }\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n        AccessControlStorage storage $ = _getAccessControlStorage();\n        return $._roles[role].adminRole;\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been revoked `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `callerConfirmation`.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n        if (callerConfirmation != _msgSender()) {\n            revert AccessControlBadConfirmation();\n        }\n\n        _revokeRole(role, callerConfirmation);\n    }\n\n    /**\n     * @dev Sets `adminRole` as ``role``'s admin role.\n     *\n     * Emits a {RoleAdminChanged} event.\n     */\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n        AccessControlStorage storage $ = _getAccessControlStorage();\n        bytes32 previousAdminRole = getRoleAdmin(role);\n        $._roles[role].adminRole = adminRole;\n        emit RoleAdminChanged(role, previousAdminRole, adminRole);\n    }\n\n    /**\n     * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n        AccessControlStorage storage $ = _getAccessControlStorage();\n        if (!hasRole(role, account)) {\n            $._roles[role].hasRole[account] = true;\n            emit RoleGranted(role, account, _msgSender());\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n        AccessControlStorage storage $ = _getAccessControlStorage();\n        if (hasRole(role, account)) {\n            $._roles[role].hasRole[account] = false;\n            emit RoleRevoked(role, account, _msgSender());\n            return true;\n        } else {\n            return false;\n        }\n    }\n}\n"},{"file_path":"project/contracts/interfaces/IProtocolFees.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IProtocolFees {\n  /**********\n   * Events *\n   **********/\n\n  /// @notice Emitted when the reserve pool contract is updated.\n  /// @param oldReservePool The address of previous reserve pool.\n  /// @param newReservePool The address of current reserve pool.\n  event UpdateReservePool(address indexed oldReservePool, address indexed newReservePool);\n\n  /// @notice Emitted when the treasury contract is updated.\n  /// @param oldTreasury The address of previous treasury contract.\n  /// @param newTreasury The address of current treasury contract.\n  event UpdateTreasury(address indexed oldTreasury, address indexed newTreasury);\n\n  /// @notice Emitted when the open revenue pool contract is updated.\n  /// @param oldPool The address of previous revenue pool contract.\n  /// @param newPool The address of current revenue pool contract.\n  event UpdateOpenRevenuePool(address indexed oldPool, address indexed newPool);\n\n  /// @notice Emitted when the close revenue pool contract is updated.\n  /// @param oldPool The address of previous revenue pool contract.\n  /// @param newPool The address of current revenue pool contract.\n  event UpdateCloseRevenuePool(address indexed oldPool, address indexed newPool);\n\n  /// @notice Emitted when the misc revenue pool contract is updated.\n  /// @param oldPool The address of previous revenue pool contract.\n  /// @param newPool The address of current revenue pool contract.\n  event UpdateMiscRevenuePool(address indexed oldPool, address indexed newPool);\n\n  /// @notice Emitted when the ratio for treasury is updated.\n  /// @param oldRatio The value of the previous ratio, multiplied by 1e9.\n  /// @param newRatio The value of the current ratio, multiplied by 1e9.\n  event UpdateRewardsExpenseRatio(uint256 oldRatio, uint256 newRatio);\n\n  /// @notice Emitted when the ratio for treasury is updated.\n  /// @param oldRatio The value of the previous ratio, multiplied by 1e9.\n  /// @param newRatio The value of the current ratio, multiplied by 1e9.\n  event UpdateFundingExpenseRatio(uint256 oldRatio, uint256 newRatio);\n\n  /// @notice Emitted when the ratio for treasury is updated.\n  /// @param oldRatio The value of the previous ratio, multiplied by 1e9.\n  /// @param newRatio The value of the current ratio, multiplied by 1e9.\n  event UpdateLiquidationExpenseRatio(uint256 oldRatio, uint256 newRatio);\n\n  /// @notice Emitted when the ratio for harvester is updated.\n  /// @param oldRatio The value of the previous ratio, multiplied by 1e9.\n  /// @param newRatio The value of the current ratio, multiplied by 1e9.\n  event UpdateHarvesterRatio(uint256 oldRatio, uint256 newRatio);\n\n  /// @notice Emitted when the flash loan fee ratio is updated.\n  /// @param oldRatio The value of the previous ratio, multiplied by 1e9.\n  /// @param newRatio The value of the current ratio, multiplied by 1e9.\n  event UpdateFlashLoanFeeRatio(uint256 oldRatio, uint256 newRatio);\n\n  /// @notice Emitted when the redeem fee ratio is updated.\n  /// @param oldRatio The value of the previous ratio, multiplied by 1e9.\n  /// @param newRatio The value of the current ratio, multiplied by 1e9.\n  event UpdateRedeemFeeRatio(uint256 oldRatio, uint256 newRatio);\n\n  /*************************\n   * Public View Functions *\n   *************************/\n\n  /// @notice Return the fee ratio distributed as protocol revenue in funding costs, multiplied by 1e9.\n  function getFundingExpenseRatio() external view returns (uint256);\n\n  /// @notice Return the fee ratio distributed as protocol revenue in general rewards, multiplied by 1e9.\n  function getRewardsExpenseRatio() external view returns (uint256);\n\n  /// @notice Return the fee ratio distributed as protocol revenue in liquidation/rebalance, multiplied by 1e9.\n  function getLiquidationExpenseRatio() external view returns (uint256);\n\n  /* @dev removed to reduce codesize, since it is not used.\n  /// @notice Return the fee ratio distributed to fxBASE in funding costs, multiplied by 1e9.\n  function getFundingFxSaveRatio() external view returns (uint256);\n  */\n\n  /* @dev removed to reduce codesize, since it is not used.\n  /// @notice Return the fee ratio distributed to fxBASE in general rewards, multiplied by 1e9.\n  function getRewardsFxSaveRatio() external view returns (uint256);\n  */\n\n  /// @notice Return the fee ratio distributed ad harvester bounty, multiplied by 1e9.\n  function getHarvesterRatio() external view returns (uint256);\n\n  /// @notice Return the flash loan fee ratio, multiplied by 1e9.\n  function getFlashLoanFeeRatio() external view returns (uint256);\n\n  /// @notice Return the redeem fee ratio, multiplied by 1e9.\n  function getRedeemFeeRatio() external view returns (uint256);\n\n  /// @notice Return the address of reserve pool.\n  function reservePool() external view returns (address);\n\n  /// @notice Return the address of protocol treasury.\n  function treasury() external view returns (address);\n\n  /// @notice Return the address of protocol revenue pool.\n  function openRevenuePool() external view returns (address);\n\n  /// @notice Return the address of protocol revenue pool.\n  function closeRevenuePool() external view returns (address);\n\n  /// @notice Return the address of protocol revenue pool.\n  function miscRevenuePool() external view returns (address);\n\n  /// @notice Return the amount of protocol open fees accumulated by the given pool.\n  function accumulatedPoolOpenFees(address pool) external view returns (uint256);\n\n  /// @notice Return the amount of protocol close fees accumulated by the given pool.\n  function accumulatedPoolCloseFees(address pool) external view returns (uint256);\n\n  /// @notice Return the amount of protocol misc fees accumulated by the given pool.\n  function accumulatedPoolMiscFees(address pool) external view returns (uint256);\n\n  /****************************\n   * Public Mutated Functions *\n   ****************************/\n\n  /// @notice Withdraw accumulated pool fee for the given pool lists.\n  /// @param pools The list of pool addresses to withdraw.\n  function withdrawAccumulatedPoolFee(address[] memory pools) external;\n}\n"},{"file_path":"project/contracts/interfaces/IPool.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IPool {\n  /**********\n   * Events *\n   **********/\n\n  /// @notice Emitted when price oracle is updated.\n  /// @param oldOracle The previous address of price oracle.\n  /// @param newOracle The current address of price oracle.\n  event UpdatePriceOracle(address oldOracle, address newOracle);\n\n  /// @notice Emitted when borrow status is updated.\n  /// @param status The updated borrow status.\n  event UpdateBorrowStatus(bool status);\n\n  /// @notice Emitted when redeem status is updated.\n  /// @param status The updated redeem status.\n  event UpdateRedeemStatus(bool status);\n\n  /// @notice Emitted when debt ratio range is updated.\n  /// @param minDebtRatio The current value of minimum debt ratio, multiplied by 1e18.\n  /// @param maxDebtRatio The current value of maximum debt ratio, multiplied by 1e18.\n  event UpdateDebtRatioRange(uint256 minDebtRatio, uint256 maxDebtRatio);\n\n  /// @notice Emitted when max redeem ratio per tick is updated.\n  /// @param ratio The current value of max redeem ratio per tick, multiplied by 1e9.\n  event UpdateMaxRedeemRatioPerTick(uint256 ratio);\n\n  /// @notice Emitted when the rebalance ratio is updated.\n  /// @param debtRatio The current value of rebalance debt ratio, multiplied by 1e18.\n  /// @param bonusRatio The current value of rebalance bonus ratio, multiplied by 1e9.\n  event UpdateRebalanceRatios(uint256 debtRatio, uint256 bonusRatio);\n\n  /// @notice Emitted when the liquidate ratio is updated.\n  /// @param debtRatio The current value of liquidate debt ratio, multiplied by 1e18.\n  /// @param bonusRatio The current value of liquidate bonus ratio, multiplied by 1e9.\n  event UpdateLiquidateRatios(uint256 debtRatio, uint256 bonusRatio);\n\n  /// @notice Emitted when position is updated.\n  /// @param position The index of this position.\n  /// @param tick The index of tick, this position belongs to.\n  /// @param collShares The amount of collateral shares in this position.\n  /// @param debtShares The amount of debt shares in this position.\n  /// @param price The price used for this operation.\n  event PositionSnapshot(uint256 position, int16 tick, uint256 collShares, uint256 debtShares, uint256 price);\n\n  /// @notice Emitted when tick moved due to rebalance, liquidate or redeem.\n  /// @param oldTick The index of the previous tick.\n  /// @param newTick The index of the current tick.\n  /// @param collShares The amount of collateral shares added to new tick.\n  /// @param debtShares The amount of debt shares added to new tick.\n  /// @param price The price used for this operation.\n  event TickMovement(int16 oldTick, int16 newTick, uint256 collShares, uint256 debtShares, uint256 price);\n\n  /// @notice Emitted when debt index increase.\n  event DebtIndexSnapshot(uint256 index);\n\n  /// @notice Emitted when collateral index increase.\n  event CollateralIndexSnapshot(uint256 index);\n\n  /// @notice Emitted when counterparty is updated.\n  /// @param oldCounterparty The previous address of counterparty.\n  /// @param newCounterparty The new address of counterparty.\n  event UpdateCounterparty(address oldCounterparty, address newCounterparty);\n\n  /***********\n   * Structs *\n   ***********/\n\n  /// @dev The result for liquidation.\n  /// @param rawColls The amount of collateral tokens liquidated.\n  /// @param rawDebts The amount of debt tokens liquidated.\n  /// @param bonusRawColls The amount of bonus collateral tokens given.\n  /// @param bonusFromReserve The amount of bonus collateral tokens coming from reserve pool.\n  struct LiquidateResult {\n    uint256 rawColls;\n    uint256 rawDebts;\n    uint256 bonusRawColls;\n    uint256 bonusFromReserve;\n  }\n\n  /// @dev The result for rebalance.\n  /// @param rawColls The amount of collateral tokens rebalanced.\n  /// @param rawDebts The amount of debt tokens rebalanced.\n  /// @param bonusRawColls The amount of bonus collateral tokens given.\n  struct RebalanceResult {\n    uint256 rawColls;\n    uint256 rawDebts;\n    uint256 bonusRawColls;\n  }\n\n  /*************************\n   * Public View Functions *\n   *************************/\n\n  /// @notice The address of counterparty.\n  function counterparty() external view returns (address);\n\n  /// @notice The address of fxUSD.\n  function fxUSD() external view returns (address);\n\n  /// @notice The address of `PoolManager` contract.\n  function poolManager() external view returns (address);\n\n  /// @notice The address of `PoolConfiguration` contract.\n  function configuration() external view returns (address);\n\n  /// @notice The address of collateral token.\n  function collateralToken() external view returns (address);\n\n  /// @notice The address of price oracle.\n  function priceOracle() external view returns (address);\n\n  /// @notice Return whether borrow is paused.\n  function isBorrowPaused() external view returns (bool);\n\n  /// @notice Return whether redeem is paused.\n  function isRedeemPaused() external view returns (bool);\n\n  /// @notice Return the current top tick with debts.\n  function getTopTick() external view returns (int16);\n\n  /// @notice Return the next position id.\n  function getNextPositionId() external view returns (uint32);\n\n  /// @notice Return the next tick tree node id.\n  function getNextTreeNodeId() external view returns (uint48);\n\n  /// @notice Return the debt ratio range.\n  /// @param minDebtRatio The minimum required debt ratio, multiplied by 1e18.\n  /// @param maxDebtRatio The minimum allowed debt ratio, multiplied by 1e18.\n  function getDebtRatioRange() external view returns (uint256 minDebtRatio, uint256 maxDebtRatio);\n\n  /// @notice Return the maximum redeem percentage per tick, multiplied by 1e9.\n  function getMaxRedeemRatioPerTick() external view returns (uint256);\n\n  /// @notice Get `debtRatio` and `bonusRatio` for rebalance.\n  /// @return debtRatio The minimum debt ratio to start rebalance, multiplied by 1e18.\n  /// @return bonusRatio The bonus ratio during rebalance, multiplied by 1e9.\n  function getRebalanceRatios() external view returns (uint256 debtRatio, uint256 bonusRatio);\n\n  /// @notice Get `debtRatio` and `bonusRatio` for liquidate.\n  /// @return debtRatio The minimum debt ratio to start liquidate, multiplied by 1e18.\n  /// @return bonusRatio The bonus ratio during liquidate, multiplied by 1e9.\n  function getLiquidateRatios() external view returns (uint256 debtRatio, uint256 bonusRatio);\n\n  /// @notice Get debt and collateral index.\n  /// @return debtIndex The index for debt shares.\n  /// @return collIndex The index for collateral shares.\n  function getDebtAndCollateralIndex() external view returns (uint256 debtIndex, uint256 collIndex);\n\n  /// @notice Get debt and collateral shares.\n  /// @return debtShares The total number of debt shares.\n  /// @return collShares The total number of collateral shares.\n  function getDebtAndCollateralShares() external view returns (uint256 debtShares, uint256 collShares);\n\n  /// @notice Return the details of the given position.\n  /// @param tokenId The id of position to query.\n  /// @return rawColls The amount of collateral tokens supplied in this position.\n  /// @return rawDebts The amount of debt tokens borrowed in this position.\n  function getPosition(uint256 tokenId) external view returns (uint256 rawColls, uint256 rawDebts);\n\n  /// @notice Return the debt ratio of the given position.\n  /// @param tokenId The id of position to query.\n  /// @return debtRatio The debt ratio of this position.\n  function getPositionDebtRatio(uint256 tokenId) external view returns (uint256 debtRatio);\n\n  /// @notice The total amount of raw collateral tokens.\n  function getTotalRawCollaterals() external view returns (uint256);\n\n  /// @notice The total amount of raw debt tokens.\n  function getTotalRawDebts() external view returns (uint256);\n\n  /****************************\n   * Public Mutated Functions *\n   ****************************/\n\n  /// @notice Open a new position or operate on an old position.\n  /// @param positionId The id of the position. If `positionId=0`, it means we need to open a new position.\n  /// @param newRawColl The amount of collateral token to supply (positive value) or withdraw (negative value).\n  /// @param newRawColl The amount of debt token to borrow (positive value) or repay (negative value).\n  /// @param owner The address of position owner.\n  /// @return actualPositionId The id of this position.\n  /// @return actualRawColl The actual amount of collateral tokens supplied (positive value) or withdrawn (negative value).\n  /// @return actualRawDebt The actual amount of debt tokens borrowed (positive value) or repay (negative value).\n  function operate(\n    uint256 positionId,\n    int256 newRawColl,\n    int256 newRawDebt,\n    address owner\n  ) external returns (uint256 actualPositionId, int256 actualRawColl, int256 actualRawDebt, uint256 protocolFees);\n\n  /// @notice Redeem debt tokens to get collateral tokens.\n  /// @param rawDebts The amount of debt tokens to redeem.\n  /// @return actualRawDebts The actual amount of debt tokens used.\n  /// @return rawColls The amount of collateral tokens to redeemed.\n  function redeem(uint256 rawDebts) external returns (uint256 actualRawDebts, uint256 rawColls);\n\n  /// @notice Redeem debt tokens to get collateral tokens.\n  /// @param rawDebts The amount of debt tokens to redeem.\n  /// @param allowTickNotMoved Whether to allow tick not moved.\n  /// @return actualRawDebts The actual amount of debt tokens used.\n  /// @return rawColls The amount of collateral tokens to redeemed.\n  function redeem(uint256 rawDebts, bool allowTickNotMoved) external returns (uint256 actualRawDebts, uint256 rawColls);\n\n  /// @notice Rebalance all positions in the given tick.\n  /// @param tick The id of tick to rebalance.\n  /// @param maxRawDebts The maximum amount of debt tokens to rebalance.\n  /// @return result The result of rebalance.\n  function rebalance(int16 tick, uint256 maxRawDebts) external returns (RebalanceResult memory result);\n\n  /// @notice Rebalance all ticks in the decreasing order of LTV.\n  /// @param maxRawDebts The maximum amount of debt tokens to rebalance.\n  /// @return result The result of rebalance.\n  function rebalance(uint256 maxRawDebts) external returns (RebalanceResult memory result);\n\n  /// @notice Liquidate all ticks in the decreasing order of LTV.\n  /// @param maxRawDebts The maximum amount of debt tokens to liquidate.\n  /// @param reservedRawColls The amount of collateral tokens in reserve pool.\n  /// @return result The result of liquidate.\n  function liquidate(uint256 maxRawDebts, uint256 reservedRawColls) external returns (LiquidateResult memory result);\n\n  /// @notice Reduce debt.\n  /// @param rawAmount The amount of debt tokens to reduce.\n  function reduceDebt(uint256 rawAmount) external;\n}\n"},{"file_path":"project/contracts/core/FlashLoans.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.25;\n\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol\";\n\nimport { ProtocolFees } from \"./ProtocolFees.sol\";\n\n/// @custom:deprecated\ncontract FlashLoans is ProtocolFees, ReentrancyGuardUpgradeable {\n  using SafeERC20 for IERC20;\n\n  /*************\n   * Variables *\n   *************/\n\n  /// @dev Slots for future use.\n  uint256[50] private _gap;\n\n  /***************\n   * Constructor *\n   ***************/\n\n  function __FlashLoans_init() internal onlyInitializing {}\n\n  /*************************\n   * Public View Functions *\n   *************************/\n\n  /****************************\n   * Public Mutated Functions *\n   ****************************/\n}\n"},{"file_path":"project/contracts/interfaces/IFxUSDBasePool.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IFxUSDBasePool {\n  /**********\n   * Events *\n   **********/\n\n  /// @notice Emitted when the stable depeg price is updated.\n  /// @param oldPrice The value of previous depeg price, multiplied by 1e18.\n  /// @param newPrice The value of current depeg price, multiplied by 1e18.\n  event UpdateStableDepegPrice(uint256 oldPrice, uint256 newPrice);\n\n  /// @notice Emitted when the redeem cool down period is updated.\n  /// @param oldPeriod The value of previous redeem cool down period.\n  /// @param newPeriod The value of current redeem cool down period.\n  event UpdateRedeemCoolDownPeriod(uint256 oldPeriod, uint256 newPeriod);\n\n  /// @notice Emitted when the instant redeem fee ratio is updated.\n  /// @param oldRatio The value of previous instant redeem fee ratio, multiplied by 1e18.\n  /// @param newRatio The value of current instant redeem fee ratio, multiplied by 1e18.\n  event UpdateInstantRedeemFeeRatio(uint256 oldRatio, uint256 newRatio);\n\n  /// @notice Emitted when deposit tokens.\n  /// @param caller The address of caller.\n  /// @param receiver The address of pool share recipient.\n  /// @param tokenIn The address of input token.\n  /// @param amountDeposited The amount of input tokens.\n  /// @param amountSharesOut The amount of pool shares minted.\n  event Deposit(\n    address indexed caller,\n    address indexed receiver,\n    address indexed tokenIn,\n    uint256 amountDeposited,\n    uint256 amountSharesOut\n  );\n  \n  /// @notice Emitted when users request redeem.\n  /// @param caller The address of caller.\n  /// @param shares The amount of shares to redeem.\n  /// @param unlockAt The timestamp when this share can be redeemed.\n  event RequestRedeem(address indexed caller, uint256 shares, uint256 unlockAt);\n\n  /// @notice Emitted when redeem pool shares.\n  /// @param caller The address of caller.\n  /// @param receiver The address of pool share recipient.\n  /// @param amountSharesToRedeem The amount of pool shares burned.\n  /// @param amountYieldTokenOut The amount of yield tokens redeemed.\n  /// @param amountStableTokenOut The amount of stable tokens redeemed.\n  event Redeem(\n    address indexed caller,\n    address indexed receiver,\n    uint256 amountSharesToRedeem,\n    uint256 amountYieldTokenOut,\n    uint256 amountStableTokenOut\n  );\n\n  /// @notice Emitted when instant redeem pool shares.\n  /// @param caller The address of caller.\n  /// @param receiver The address of pool share recipient.\n  /// @param amountSharesToRedeem The amount of pool shares burned.\n  /// @param amountYieldTokenOut The amount of yield tokens redeemed.\n  /// @param amountStableTokenOut The amount of stable tokens redeemed.\n  event InstantRedeem(\n    address indexed caller,\n    address indexed receiver,\n    uint256 amountSharesToRedeem,\n    uint256 amountYieldTokenOut,\n    uint256 amountStableTokenOut\n  );\n\n  /// @notice Emitted when rebalance or liquidate.\n  /// @param caller The address of caller.\n  /// @param tokenIn The address of input token.\n  /// @param amountTokenIn The amount of input token used.\n  /// @param amountCollateral The amount of collateral token rebalanced.\n  /// @param amountYieldToken The amount of yield token used.\n  /// @param amountStableToken The amount of stable token used.\n  event Rebalance(\n    address indexed caller,\n    address indexed tokenIn,\n    uint256 amountTokenIn,\n    uint256 amountCollateral,\n    uint256 amountYieldToken,\n    uint256 amountStableToken\n  );\n\n  /// @notice Emitted when arbitrage in curve pool.\n  /// @param caller The address of caller.\n  /// @param tokenIn The address of input token.\n  /// @param amountIn The amount of input token used.\n  /// @param amountOut The amount of output token swapped.\n  /// @param bonusOut The amount of bonus token.\n  event Arbitrage(\n    address indexed caller,\n    address indexed tokenIn,\n    uint256 amountIn,\n    uint256 amountOut,\n    uint256 bonusOut\n  );\n\n  /*************************\n   * Public View Functions *\n   *************************/\n\n  /// @notice The address of yield token.\n  function yieldToken() external view returns (address);\n\n  /// @notice The address of stable token.\n  function stableToken() external view returns (address);\n\n  /// @notice The total amount of yield token managed in this contract\n  function totalYieldToken() external view returns (uint256);\n\n  /// @notice The total amount of stable token managed in this contract\n  function totalStableToken() external view returns (uint256);\n\n  /// @notice The net asset value, multiplied by 1e18.\n  function nav() external view returns (uint256);\n\n  /// @notice Return the stable token price, multiplied by 1e18.\n  function getStableTokenPrice() external view returns (uint256);\n\n  /// @notice Return the stable token price with scaling to 18 decimals, multiplied by 1e18.\n  function getStableTokenPriceWithScale() external view returns (uint256);\n\n  /// @notice Preview the result of deposit.\n  /// @param tokenIn The address of input token.\n  /// @param amount The amount of input tokens to deposit.\n  /// @return amountSharesOut The amount of pool shares should receive.\n  function previewDeposit(address tokenIn, uint256 amount) external view returns (uint256 amountSharesOut);\n\n  /// @notice Preview the result of redeem.\n  /// @param amountSharesToRedeem The amount of pool shares to redeem.\n  /// @return amountYieldOut The amount of yield token should receive.\n  /// @return amountStableOut The amount of stable token should receive.\n  function previewRedeem(\n    uint256 amountSharesToRedeem\n  ) external view returns (uint256 amountYieldOut, uint256 amountStableOut);\n\n  /****************************\n   * Public Mutated Functions *\n   ****************************/\n\n  /// @notice Deposit token.\n  /// @param receiver The address of pool shares recipient.\n  /// @param tokenIn The address of input token.\n  /// @param amountTokenToDeposit The amount of input tokens to deposit.\n  /// @param minSharesOut The minimum amount of pool shares should receive.\n  /// @return amountSharesOut The amount of pool shares received.\n  function deposit(\n    address receiver,\n    address tokenIn,\n    uint256 amountTokenToDeposit,\n    uint256 minSharesOut\n  ) external returns (uint256 amountSharesOut);\n\n  /// @notice Request redeem.\n  /// @param shares The amount of shares to request.\n  function requestRedeem(uint256 shares) external;\n\n  /// @notice Redeem pool shares.\n  /// @param receiver The address of token recipient.\n  /// @param shares The amount of pool shares to redeem.\n  /// @return amountYieldOut The amount of yield token should received.\n  /// @return amountStableOut The amount of stable token should received.\n  function redeem(address receiver, uint256 shares) external returns (uint256 amountYieldOut, uint256 amountStableOut);\n\n  /// @notice Redeem pool shares instantly with withdraw fee.\n  /// @param receiver The address of token recipient.\n  /// @param shares The amount of pool shares to redeem.\n  /// @return amountYieldOut The amount of yield token should received.\n  /// @return amountStableOut The amount of stable token should received.\n  function instantRedeem(address receiver, uint256 shares) external returns (uint256 amountYieldOut, uint256 amountStableOut);\n\n  /// @notice Redeem pool shares instantly without withdraw fee.\n  /// @param receiver The address of token recipient.\n  /// @param shares The amount of pool shares to redeem.\n  /// @return amountYieldOut The amount of yield token should received.\n  /// @return amountStableOut The amount of stable token should received.\n  function instantRedeemNoFee(address receiver, uint256 shares) external returns (uint256 amountYieldOut, uint256 amountStableOut);\n\n  /// @notice Rebalance all positions in the given tick.\n  /// @param pool The address of pool to rebalance.\n  /// @param tick The index of tick to rebalance.\n  /// @param tokenIn The address of token to rebalance.\n  /// @param maxAmount The maximum amount of input token to rebalance.\n  /// @param minBaseOut The minimum amount of collateral tokens should receive.\n  /// @return tokenUsed The amount of input token used to rebalance.\n  /// @return baseOut The amount of collateral tokens rebalanced.\n  function rebalance(\n    address pool,\n    int16 tick,\n    address tokenIn,\n    uint256 maxAmount,\n    uint256 minBaseOut\n  ) external returns (uint256 tokenUsed, uint256 baseOut);\n\n  /// @notice Rebalance all possible ticks.\n  /// @param pool The address of pool to rebalance.\n  /// @param tokenIn The address of token to rebalance.\n  /// @param maxAmount The maximum amount of input token to rebalance.\n  /// @param minBaseOut The minimum amount of collateral tokens should receive.\n  /// @return tokenUsed The amount of input token used to rebalance.\n  /// @return baseOut The amount of collateral tokens rebalanced.\n  function rebalance(\n    address pool,\n    address tokenIn,\n    uint256 maxAmount,\n    uint256 minBaseOut\n  ) external returns (uint256 tokenUsed, uint256 baseOut);\n\n  /// @notice Liquidate all possible ticks.\n  /// @param pool The address of pool to rebalance.\n  /// @param tokenIn The address of token to rebalance.\n  /// @param maxAmount The maximum amount of input token to rebalance.\n  /// @param minBaseOut The minimum amount of collateral tokens should receive.\n  /// @return tokenUsed The amount of input token used to rebalance.\n  /// @return baseOut The amount of collateral tokens rebalanced.\n  function liquidate(\n    address pool,\n    address tokenIn,\n    uint256 maxAmount,\n    uint256 minBaseOut\n  ) external returns (uint256 tokenUsed, uint256 baseOut);\n\n  /// @notice Arbitrage between yield token and stable token.\n  /// @param srcToken The address of source token.\n  /// @param amountIn The amount of source token to use.\n  /// @param receiver The address of bonus receiver.\n  /// @param data The hook data to `onSwap`.\n  /// @return amountOut The amount of target token swapped.\n  /// @return bonusOut The amount of bonus token.\n  function arbitrage(\n    address srcToken,\n    uint256 amountIn,\n    address receiver,\n    bytes calldata data\n  ) external returns (uint256 amountOut, uint256 bonusOut);\n}\n"},{"file_path":"npm/@openzeppelin/contracts@5.4.0/interfaces/IERC1363.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @title IERC1363\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\n *\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\n */\ninterface IERC1363 is IERC20, IERC165 {\n    /*\n     * Note: the ERC-165 identifier for this interface is 0xb0202a11.\n     * 0xb0202a11 ===\n     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\n     */\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @param data Additional data with no specified format, sent in call to `spender`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\n}\n"},{"file_path":"project/contracts/voting-escrow/interfaces/ISmartWalletChecker.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface ISmartWalletChecker {\n  function check(address) external view returns (bool);\n}"},{"file_path":"npm/@openzeppelin/contracts@5.4.0/token/ERC20/utils/SafeERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC1363} from \"../../../interfaces/IERC1363.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    /**\n     * @dev An operation with an ERC-20 token failed.\n     */\n    error SafeERC20FailedOperation(address token);\n\n    /**\n     * @dev Indicates a failed `decreaseAllowance` request.\n     */\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n    }\n\n    /**\n     * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\n     */\n    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\n        return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));\n    }\n\n    /**\n     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\n     */\n    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\n        return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     *\n     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n     * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        forceApprove(token, spender, oldAllowance + value);\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n     * value, non-reverting calls are assumed to be successful.\n     *\n     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \"client\"\n     * smart contract uses ERC-7674 to set temporary allowances, then the \"client\" smart contract should avoid using\n     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\n     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n        unchecked {\n            uint256 currentAllowance = token.allowance(address(this), spender);\n            if (currentAllowance < requestedDecrease) {\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n            }\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     *\n     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\n     * only sets the \"standard\" allowance. Any temporary allowance will remain active, in addition to the value being\n     * set here.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            safeTransfer(token, to, value);\n        } else if (!token.transferAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\n     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferFromAndCallRelaxed(\n        IERC1363 token,\n        address from,\n        address to,\n        uint256 value,\n        bytes memory data\n    ) internal {\n        if (to.code.length == 0) {\n            safeTransferFrom(token, from, to, value);\n        } else if (!token.transferFromAndCall(from, to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\n     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\n     * once without retrying, and relies on the returned value to be true.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            forceApprove(token, to, value);\n        } else if (!token.approveAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        uint256 returnSize;\n        uint256 returnValue;\n        assembly (\"memory-safe\") {\n            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\n            // bubble errors\n            if iszero(success) {\n                let ptr := mload(0x40)\n                returndatacopy(ptr, 0, returndatasize())\n                revert(ptr, returndatasize())\n            }\n            returnSize := returndatasize()\n            returnValue := mload(0)\n        }\n\n        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        bool success;\n        uint256 returnSize;\n        uint256 returnValue;\n        assembly (\"memory-safe\") {\n            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\n            returnSize := returndatasize()\n            returnValue := mload(0)\n        }\n        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);\n    }\n}\n"},{"file_path":"npm/@openzeppelin/contracts-upgradeable@5.4.0/utils/introspection/ERC165Upgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport {Initializable} from \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165Upgradeable is Initializable, IERC165 {\n    function __ERC165_init() internal onlyInitializing {\n    }\n\n    function __ERC165_init_unchained() internal onlyInitializing {\n    }\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"},{"file_path":"npm/@openzeppelin/contracts@5.4.0/utils/Arrays.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/Arrays.sol)\n// This file was procedurally generated from scripts/generate/templates/Arrays.js.\n\npragma solidity ^0.8.20;\n\nimport {Comparators} from \"./Comparators.sol\";\nimport {SlotDerivation} from \"./SlotDerivation.sol\";\nimport {StorageSlot} from \"./StorageSlot.sol\";\nimport {Math} from \"./math/Math.sol\";\n\n/**\n * @dev Collection of functions related to array types.\n */\nlibrary Arrays {\n    using SlotDerivation for bytes32;\n    using StorageSlot for bytes32;\n\n    /**\n     * @dev Sort an array of uint256 (in memory) following the provided comparator function.\n     *\n     * This function does the sorting \"in place\", meaning that it overrides the input. The object is returned for\n     * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\n     *\n     * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the\n     * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\n     * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\n     * consume more gas than is available in a block, leading to potential DoS.\n     *\n     * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\n     */\n    function sort(\n        uint256[] memory array,\n        function(uint256, uint256) pure returns (bool) comp\n    ) internal pure returns (uint256[] memory) {\n        _quickSort(_begin(array), _end(array), comp);\n        return array;\n    }\n\n    /**\n     * @dev Variant of {sort} that sorts an array of uint256 in increasing order.\n     */\n    function sort(uint256[] memory array) internal pure returns (uint256[] memory) {\n        sort(array, Comparators.lt);\n        return array;\n    }\n\n    /**\n     * @dev Sort an array of address (in memory) following the provided comparator function.\n     *\n     * This function does the sorting \"in place\", meaning that it overrides the input. The object is returned for\n     * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\n     *\n     * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the\n     * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\n     * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\n     * consume more gas than is available in a block, leading to potential DoS.\n     *\n     * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\n     */\n    function sort(\n        address[] memory array,\n        function(address, address) pure returns (bool) comp\n    ) internal pure returns (address[] memory) {\n        sort(_castToUint256Array(array), _castToUint256Comp(comp));\n        return array;\n    }\n\n    /**\n     * @dev Variant of {sort} that sorts an array of address in increasing order.\n     */\n    function sort(address[] memory array) internal pure returns (address[] memory) {\n        sort(_castToUint256Array(array), Comparators.lt);\n        return array;\n    }\n\n    /**\n     * @dev Sort an array of bytes32 (in memory) following the provided comparator function.\n     *\n     * This function does the sorting \"in place\", meaning that it overrides the input. The object is returned for\n     * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\n     *\n     * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the\n     * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\n     * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\n     * consume more gas than is available in a block, leading to potential DoS.\n     *\n     * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\n     */\n    function sort(\n        bytes32[] memory array,\n        function(bytes32, bytes32) pure returns (bool) comp\n    ) internal pure returns (bytes32[] memory) {\n        sort(_castToUint256Array(array), _castToUint256Comp(comp));\n        return array;\n    }\n\n    /**\n     * @dev Variant of {sort} that sorts an array of bytes32 in increasing order.\n     */\n    function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) {\n        sort(_castToUint256Array(array), Comparators.lt);\n        return array;\n    }\n\n    /**\n     * @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops\n     * at end (exclusive). Sorting follows the `comp` comparator.\n     *\n     * Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls.\n     *\n     * IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should\n     * be used only if the limits are within a memory array.\n     */\n    function _quickSort(uint256 begin, uint256 end, function(uint256, uint256) pure returns (bool) comp) private pure {\n        unchecked {\n            if (end - begin < 0x40) return;\n\n            // Use first element as pivot\n            uint256 pivot = _mload(begin);\n            // Position where the pivot should be at the end of the loop\n            uint256 pos = begin;\n\n            for (uint256 it = begin + 0x20; it < end; it += 0x20) {\n                if (comp(_mload(it), pivot)) {\n                    // If the value stored at the iterator's position comes before the pivot, we increment the\n                    // position of the pivot and move the value there.\n                    pos += 0x20;\n                    _swap(pos, it);\n                }\n            }\n\n            _swap(begin, pos); // Swap pivot into place\n            _quickSort(begin, pos, comp); // Sort the left side of the pivot\n            _quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot\n        }\n    }\n\n    /**\n     * @dev Pointer to the memory location of the first element of `array`.\n     */\n    function _begin(uint256[] memory array) private pure returns (uint256 ptr) {\n        assembly (\"memory-safe\") {\n            ptr := add(array, 0x20)\n        }\n    }\n\n    /**\n     * @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word\n     * that comes just after the last element of the array.\n     */\n    function _end(uint256[] memory array) private pure returns (uint256 ptr) {\n        unchecked {\n            return _begin(array) + array.length * 0x20;\n        }\n    }\n\n    /**\n     * @dev Load memory word (as a uint256) at location `ptr`.\n     */\n    function _mload(uint256 ptr) private pure returns (uint256 value) {\n        assembly {\n            value := mload(ptr)\n        }\n    }\n\n    /**\n     * @dev Swaps the elements memory location `ptr1` and `ptr2`.\n     */\n    function _swap(uint256 ptr1, uint256 ptr2) private pure {\n        assembly {\n            let value1 := mload(ptr1)\n            let value2 := mload(ptr2)\n            mstore(ptr1, value2)\n            mstore(ptr2, value1)\n        }\n    }\n\n    /// @dev Helper: low level cast address memory array to uint256 memory array\n    function _castToUint256Array(address[] memory input) private pure returns (uint256[] memory output) {\n        assembly {\n            output := input\n        }\n    }\n\n    /// @dev Helper: low level cast bytes32 memory array to uint256 memory array\n    function _castToUint256Array(bytes32[] memory input) private pure returns (uint256[] memory output) {\n        assembly {\n            output := input\n        }\n    }\n\n    /// @dev Helper: low level cast address comp function to uint256 comp function\n    function _castToUint256Comp(\n        function(address, address) pure returns (bool) input\n    ) private pure returns (function(uint256, uint256) pure returns (bool) output) {\n        assembly {\n            output := input\n        }\n    }\n\n    /// @dev Helper: low level cast bytes32 comp function to uint256 comp function\n    function _castToUint256Comp(\n        function(bytes32, bytes32) pure returns (bool) input\n    ) private pure returns (function(uint256, uint256) pure returns (bool) output) {\n        assembly {\n            output := input\n        }\n    }\n\n    /**\n     * @dev Searches a sorted `array` and returns the first index that contains\n     * a value greater or equal to `element`. If no such index exists (i.e. all\n     * values in the array are strictly less than `element`), the array length is\n     * returned. Time complexity O(log n).\n     *\n     * NOTE: The `array` is expected to be sorted in ascending order, and to\n     * contain no repeated elements.\n     *\n     * IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks\n     * support for repeated elements in the array. The {lowerBound} function should\n     * be used instead.\n     */\n    function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\n        uint256 low = 0;\n        uint256 high = array.length;\n\n        if (high == 0) {\n            return 0;\n        }\n\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n\n            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\n            // because Math.average rounds towards zero (it does integer division with truncation).\n            if (unsafeAccess(array, mid).value > element) {\n                high = mid;\n            } else {\n                low = mid + 1;\n            }\n        }\n\n        // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.\n        if (low > 0 && unsafeAccess(array, low - 1).value == element) {\n            return low - 1;\n        } else {\n            return low;\n        }\n    }\n\n    /**\n     * @dev Searches an `array` sorted in ascending order and returns the first\n     * index that contains a value greater or equal than `element`. If no such index\n     * exists (i.e. all values in the array are strictly less than `element`), the array\n     * length is returned. Time complexity O(log n).\n     *\n     * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound].\n     */\n    function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\n        uint256 low = 0;\n        uint256 high = array.length;\n\n        if (high == 0) {\n            return 0;\n        }\n\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n\n            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\n            // because Math.average rounds towards zero (it does integer division with truncation).\n            if (unsafeAccess(array, mid).value < element) {\n                // this cannot overflow because mid < high\n                unchecked {\n                    low = mid + 1;\n                }\n            } else {\n                high = mid;\n            }\n        }\n\n        return low;\n    }\n\n    /**\n     * @dev Searches an `array` sorted in ascending order and returns the first\n     * index that contains a value strictly greater than `element`. If no such index\n     * exists (i.e. all values in the array are strictly less than `element`), the array\n     * length is returned. Time complexity O(log n).\n     *\n     * See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound].\n     */\n    function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\n        uint256 low = 0;\n        uint256 high = array.length;\n\n        if (high == 0) {\n            return 0;\n        }\n\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n\n            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\n            // because Math.average rounds towards zero (it does integer division with truncation).\n            if (unsafeAccess(array, mid).value > element) {\n                high = mid;\n            } else {\n                // this cannot overflow because mid < high\n                unchecked {\n                    low = mid + 1;\n                }\n            }\n        }\n\n        return low;\n    }\n\n    /**\n     * @dev Same as {lowerBound}, but with an array in memory.\n     */\n    function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {\n        uint256 low = 0;\n        uint256 high = array.length;\n\n        if (high == 0) {\n            return 0;\n        }\n\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n\n            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\n            // because Math.average rounds towards zero (it does integer division with truncation).\n            if (unsafeMemoryAccess(array, mid) < element) {\n                // this cannot overflow because mid < high\n                unchecked {\n                    low = mid + 1;\n                }\n            } else {\n                high = mid;\n            }\n        }\n\n        return low;\n    }\n\n    /**\n     * @dev Same as {upperBound}, but with an array in memory.\n     */\n    function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {\n        uint256 low = 0;\n        uint256 high = array.length;\n\n        if (high == 0) {\n            return 0;\n        }\n\n        while (low < high) {\n            uint256 mid = Math.average(low, high);\n\n            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\n            // because Math.average rounds towards zero (it does integer division with truncation).\n            if (unsafeMemoryAccess(array, mid) > element) {\n                high = mid;\n            } else {\n                // this cannot overflow because mid < high\n                unchecked {\n                    low = mid + 1;\n                }\n            }\n        }\n\n        return low;\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {\n        bytes32 slot;\n        assembly (\"memory-safe\") {\n            slot := arr.slot\n        }\n        return slot.deriveArray().offset(pos).getAddressSlot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {\n        bytes32 slot;\n        assembly (\"memory-safe\") {\n            slot := arr.slot\n        }\n        return slot.deriveArray().offset(pos).getBytes32Slot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {\n        bytes32 slot;\n        assembly (\"memory-safe\") {\n            slot := arr.slot\n        }\n        return slot.deriveArray().offset(pos).getUint256Slot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(bytes[] storage arr, uint256 pos) internal pure returns (StorageSlot.BytesSlot storage) {\n        bytes32 slot;\n        assembly (\"memory-safe\") {\n            slot := arr.slot\n        }\n        return slot.deriveArray().offset(pos).getBytesSlot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeAccess(string[] storage arr, uint256 pos) internal pure returns (StorageSlot.StringSlot storage) {\n        bytes32 slot;\n        assembly (\"memory-safe\") {\n            slot := arr.slot\n        }\n        return slot.deriveArray().offset(pos).getStringSlot();\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {\n        assembly {\n            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\n        }\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) {\n        assembly {\n            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\n        }\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {\n        assembly {\n            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\n        }\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeMemoryAccess(bytes[] memory arr, uint256 pos) internal pure returns (bytes memory res) {\n        assembly {\n            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\n        }\n    }\n\n    /**\n     * @dev Access an array in an \"unsafe\" way. Skips solidity \"index-out-of-range\" check.\n     *\n     * WARNING: Only use if you are certain `pos` is lower than the array length.\n     */\n    function unsafeMemoryAccess(string[] memory arr, uint256 pos) internal pure returns (string memory res) {\n        assembly {\n            res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\n        }\n    }\n\n    /**\n     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\n     *\n     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\n     */\n    function unsafeSetLength(address[] storage array, uint256 len) internal {\n        assembly (\"memory-safe\") {\n            sstore(array.slot, len)\n        }\n    }\n\n    /**\n     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\n     *\n     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\n     */\n    function unsafeSetLength(bytes32[] storage array, uint256 len) internal {\n        assembly (\"memory-safe\") {\n            sstore(array.slot, len)\n        }\n    }\n\n    /**\n     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\n     *\n     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\n     */\n    function unsafeSetLength(uint256[] storage array, uint256 len) internal {\n        assembly (\"memory-safe\") {\n            sstore(array.slot, len)\n        }\n    }\n\n    /**\n     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\n     *\n     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\n     */\n    function unsafeSetLength(bytes[] storage array, uint256 len) internal {\n        assembly (\"memory-safe\") {\n            sstore(array.slot, len)\n        }\n    }\n\n    /**\n     * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\n     *\n     * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\n     */\n    function unsafeSetLength(string[] storage array, uint256 len) internal {\n        assembly (\"memory-safe\") {\n            sstore(array.slot, len)\n        }\n    }\n}\n"},{"file_path":"project/contracts/interfaces/IPoolConfiguration.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.26;\n\ninterface IPoolConfiguration {\n  /**********\n   * Events *\n   **********/\n\n  /// @notice Emitted when the oracle is updated.\n  /// @param oldOracle The old oracle address.\n  /// @param newOracle The new oracle address.\n  event UpdateOracle(address indexed oldOracle, address indexed newOracle);\n\n  /// @notice Emitted when the pool fee ratio is updated.\n  /// @param pool The address of pool.\n  /// @param recipient The address of recipient.\n  /// @param supplyRatio The supply ratio, multiplied by 1e9.\n  /// @param supplyRatioStep The supply ratio step, multiplied by 1e18.\n  /// @param withdrawFeeRatio The withdraw fee ratio, multiplied by 1e9.\n  /// @param borrowFeeRatio The borrow fee ratio, multiplied by 1e9.\n  /// @param repayFeeRatio The repay fee ratio, multiplied by 1e9.\n  event UpdatePoolFeeRatio(\n    address indexed pool,\n    address indexed recipient,\n    uint256 supplyRatio,\n    uint256 supplyRatioStep,\n    uint256 withdrawFeeRatio,\n    uint256 borrowFeeRatio,\n    uint256 repayFeeRatio\n  );\n\n  /// @notice Emitted when the long funding ratio parameter is updated.\n  /// @param scalarA The scalar A.\n  /// @param scalarB The scalar B.\n  /// @param maxFxUSDRatio The max fxUSD ratio.\n  event UpdateLongFundingRatioParameter(uint64 scalarA, uint64 scalarB, uint64 maxFxUSDRatio);\n\n  /// @notice Emitted when the short funding ratio parameter is updated.\n  /// @param scalarC The scalar C.\n  /// @param maxBorrowRatio The max borrow ratio.\n  event UpdateShortFundingRatioParameter(uint64 scalarC, uint64 maxBorrowRatio);\n\n  /// @notice Emitted when the snapshot is taken.\n  /// @param borrowIndex The borrow index.\n  /// @param lastInterestRate The last interest rate.\n  /// @param timestamp The timestamp of the snapshot.\n  event Snapshot(uint256 borrowIndex, uint256 lastInterestRate, uint256 timestamp);\n\n  /// @notice Emitted when the stable depeg price is updated.\n  /// @param oldStableDepegPrice The old stable depeg price.\n  /// @param newStableDepegPrice The new stable depeg price.\n  event UpdateStableDepegPrice(uint256 oldStableDepegPrice, uint256 newStableDepegPrice);\n\n  /// @notice Emitted when an address is registered.\n  /// @param key The key of the registered address.\n  /// @param addr The registered address.\n  event Register(bytes32 key, address addr);\n\n  /*************************\n   * Public View Functions *\n   *************************/\n\n  /// @notice Return whether borrow for fxUSD is allowed.\n  function isBorrowAllowed() external view returns (bool);\n\n  /// @notice Return whether redeem for fxUSD is allowed.\n  function isRedeemAllowed() external view returns (bool);\n\n  /// @notice Return whether funding costs is enabled.\n  function isFundingEnabled() external view returns (bool);\n\n  /// @notice Return whether repay with stable coin is allowed.\n  function isStableRepayAllowed() external view returns (bool);\n\n  /// @notice Get the pool fee ratio.\n  /// @param pool The address of pool.\n  /// @param recipient The address of recipient.\n  /// @return supplyFeeRatio The supply fee ratio, multiplied by 1e9.\n  /// @return withdrawFeeRatio The withdraw fee ratio, multiplied by 1e9.\n  /// @return borrowFeeRatio The borrow fee ratio, multiplied by 1e9.\n  /// @return repayFeeRatio The repay fee ratio, multiplied by 1e9.\n  function getPoolFeeRatio(\n    address pool,\n    address recipient\n  )\n    external\n    view\n    returns (uint256 supplyFeeRatio, uint256 withdrawFeeRatio, uint256 borrowFeeRatio, uint256 repayFeeRatio);\n\n  /// @notice Get the long pool funding ratio.\n  /// @param pool The address of pool.\n  /// @return fundingRatio The funding ratio, multiplied by 1e18.\n  function getLongPoolFundingRatio(address pool) external view returns (uint256 fundingRatio);\n\n  /// @notice Get the short pool funding ratio.\n  /// @param pool The address of pool.\n  /// @return fundingRatio The funding ratio, multiplied by 1e18.\n  function getShortPoolFundingRatio(address pool) external view returns (uint256 fundingRatio);\n\n  /// @notice Get the registered address.\n  /// @param key The key of the registered address.\n  /// @return address The registered address.\n  function registry(bytes32 key) external view returns (address);\n\n  /****************************\n   * Public Mutated Functions *\n   ****************************/\n\n  /// @notice Checkpoint the lending pool snapshot.\n  /// @param pool The address of pool.\n  function checkpoint(address pool) external;\n\n  /// @notice Lock the pool manager.\n  /// @param manager The address of pool manager.\n  /// @param selector The selector of the function to lock.\n  function lock(address manager, bytes4 selector) external;\n\n  /// @notice Unlock the pool manager.\n  /// @param manager The address of pool manager.\n  /// @param selector The selector of the function to unlock.\n  function unlock(address manager, bytes4 selector) external;\n}\n"},{"file_path":"project/contracts/interfaces/IPoolManager.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IPoolManager {\n  /**********\n   * Events *\n   **********/\n\n  /// @notice Register a new pool.\n  /// @param pool The address of fx pool.\n  event RegisterPool(address indexed pool);\n\n  /// @notice Emitted when the reward splitter contract is updated.\n  /// @param pool The address of fx pool.\n  /// @param oldSplitter The address of previous reward splitter contract.\n  /// @param newSplitter The address of current reward splitter contract.\n  event UpdateRewardSplitter(address indexed pool, address indexed oldSplitter, address indexed newSplitter);\n\n  /// @notice Emitted when token rate is updated.\n  /// @param scalar The token scalar to reach 18 decimals.\n  /// @param provider The address of token rate provider.\n  event UpdateTokenRate(address indexed token, uint256 scalar, address provider);\n\n  /// @notice Emitted when pool capacity is updated.\n  /// @param pool The address of fx pool.\n  /// @param collateralCapacity The capacity for collateral token.\n  /// @param debtCapacity The capacity for debt token.\n  event UpdatePoolCapacity(address indexed pool, uint256 collateralCapacity, uint256 debtCapacity);\n\n  /// @notice Emitted when position is updated.\n  /// @param pool The address of pool where the position belongs to.\n  /// @param position The id of the position.\n  /// @param deltaColls The amount of collateral token changes.\n  /// @param deltaDebts The amount of debt token changes.\n  /// @param protocolFees The amount of protocol fees charges.\n  event Operate(\n    address indexed pool,\n    uint256 indexed position,\n    int256 deltaColls,\n    int256 deltaDebts,\n    uint256 protocolFees\n  );\n\n  /// @notice Emitted when redeem happened.\n  /// @param pool The address of pool redeemed.\n  /// @param colls The amount of collateral tokens redeemed.\n  /// @param debts The amount of debt tokens redeemed.\n  /// @param protocolFees The amount of protocol fees charges.\n  event Redeem(address indexed pool, uint256 colls, uint256 debts, uint256 protocolFees);\n\n  /// @notice Emitted when redeem for settle happened.\n  /// @param pool The address of pool redeemed.\n  /// @param colls The amount of collateral tokens redeemed.\n  /// @param debts The amount of debt tokens redeemed.\n  event RedeemForSettle(address indexed pool, uint256 colls, uint256 debts);\n\n  /// @notice Emitted when someone harvest pending rewards.\n  /// @param caller The address of caller.\n  /// @param amountRewards The amount of total harvested rewards.\n  /// @param amountFunding The amount of total harvested funding.\n  /// @param performanceFee The amount of harvested rewards distributed to protocol revenue.\n  /// @param harvestBounty The amount of harvested rewards distributed to caller as harvest bounty.\n  event Harvest(\n    address indexed caller,\n    address indexed pool,\n    uint256 amountRewards,\n    uint256 amountFunding,\n    uint256 performanceFee,\n    uint256 harvestBounty\n  );\n\n  /// @notice Emitted when debt is reduced by someone.\n  /// @param pool The address of pool reduced.\n  /// @param amount The amount of debt token reduced.\n  event ReduceDebt(address indexed pool, uint256 amount);\n\n  /*************************\n   * Public View Functions *\n   *************************/\n\n  /// @notice The address of fxUSD.\n  function fxUSD() external view returns (address);\n\n  /// @notice The address of counterparty PoolManager.\n  function counterparty() external view returns (address);\n\n  /// @notice The address of `PoolConfiguration` contract.\n  function configuration() external view returns (address);\n\n  /// @notice The address of reward splitter.\n  function rewardSplitter(address pool) external view returns (address);\n\n  /// @notice Get the scaling factor for a token.\n  /// @param token The address of the token.\n  /// @return scalingFactor The scaling factor for the token.\n  function getTokenScalingFactor(address token) external view returns (uint256);\n\n  /****************************\n   * Public Mutated Functions *\n   ****************************/\n\n  /// @notice Open a new position or operate on an old position.\n  /// @param pool The address of pool to operate.\n  /// @param positionId The id of the position. If `positionId=0`, it means we need to open a new position.\n  /// @param newColl The amount of collateral token to supply (positive value) or withdraw (negative value).\n  /// @param newDebt The amount of debt token to borrow (positive value) or repay (negative value).\n  /// @return actualPositionId The id of this position.\n  function operate(\n    address pool,\n    uint256 positionId,\n    int256 newColl,\n    int256 newDebt\n  ) external returns (uint256 actualPositionId);\n\n  /// @notice Redeem debt tokens to get collateral tokens.\n  /// @param pool The address of pool to redeem.\n  /// @param debts The amount of debt tokens to redeem.\n  /// @param minColls The minimum amount of collateral tokens should redeem.\n  /// @return actualDebts The actual amount of debt tokens used.\n  /// @return colls The amount of collateral tokens redeemed.\n  function redeem(address pool, uint256 debts, uint256 minColls) external returns (uint256 actualDebts, uint256 colls);\n\n  /// @notice Harvest pending rewards of the given pool.\n  /// @param pool The address of pool to harvest.\n  /// @return amountRewards The amount of rewards harvested.\n  /// @return amountFunding The amount of funding harvested.\n  function harvest(address pool) external returns (uint256 amountRewards, uint256 amountFunding);\n\n  /// @notice Reduce the debt of a pool. This function is only callable by whitelisted addresses.\n  /// @param pool The address of the pool to reduce debt for.\n  /// @param amount The amount of debt token to reduce.\n  function reduceDebt(address pool, uint256 amount) external;\n}\n"},{"file_path":"npm/@openzeppelin/contracts-upgradeable@5.4.0/proxy/utils/Initializable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Storage of the initializable contract.\n     *\n     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n     * when using with upgradeable contracts.\n     *\n     * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n     */\n    struct InitializableStorage {\n        /**\n         * @dev Indicates that the contract has been initialized.\n         */\n        uint64 _initialized;\n        /**\n         * @dev Indicates that the contract is in the process of being initialized.\n         */\n        bool _initializing;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n    /**\n     * @dev The contract is already initialized.\n     */\n    error InvalidInitialization();\n\n    /**\n     * @dev The contract is not initializing.\n     */\n    error NotInitializing();\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint64 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n     * production.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        // Cache values to avoid duplicated sloads\n        bool isTopLevelCall = !$._initializing;\n        uint64 initialized = $._initialized;\n\n        // Allowed calls:\n        // - initialSetup: the contract is not in the initializing state and no previous version was\n        //                 initialized\n        // - construction: the contract is initialized at version 1 (no reinitialization) and the\n        //                 current contract is just being deployed\n        bool initialSetup = initialized == 0 && isTopLevelCall;\n        bool construction = initialized == 1 && address(this).code.length == 0;\n\n        if (!initialSetup && !construction) {\n            revert InvalidInitialization();\n        }\n        $._initialized = 1;\n        if (isTopLevelCall) {\n            $._initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            $._initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint64 version) {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing || $._initialized >= version) {\n            revert InvalidInitialization();\n        }\n        $._initialized = version;\n        $._initializing = true;\n        _;\n        $._initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        _checkInitializing();\n        _;\n    }\n\n    /**\n     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n     */\n    function _checkInitializing() internal view virtual {\n        if (!_isInitializing()) {\n            revert NotInitializing();\n        }\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing) {\n            revert InvalidInitialization();\n        }\n        if ($._initialized != type(uint64).max) {\n            $._initialized = type(uint64).max;\n            emit Initialized(type(uint64).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint64) {\n        return _getInitializableStorage()._initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _getInitializableStorage()._initializing;\n    }\n\n    /**\n     * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.\n     *\n     * NOTE: Consider following the ERC-7201 formula to derive storage locations.\n     */\n    function _initializableStorageSlot() internal pure virtual returns (bytes32) {\n        return INITIALIZABLE_STORAGE;\n    }\n\n    /**\n     * @dev Returns a pointer to the storage namespace.\n     */\n    // solhint-disable-next-line var-name-mixedcase\n    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n        bytes32 slot = _initializableStorageSlot();\n        assembly {\n            $.slot := slot\n        }\n    }\n}\n"},{"file_path":"npm/@openzeppelin/contracts@5.4.0/token/ERC20/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"},{"file_path":"npm/@openzeppelin/contracts@5.4.0/utils/Panic.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Helper library for emitting standardized panic codes.\n *\n * ```solidity\n * contract Example {\n *      using Panic for uint256;\n *\n *      // Use any of the declared internal constants\n *      function foo() { Panic.GENERIC.panic(); }\n *\n *      // Alternatively\n *      function foo() { Panic.panic(Panic.GENERIC); }\n * }\n * ```\n *\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\n *\n * _Available since v5.1._\n */\n// slither-disable-next-line unused-state\nlibrary Panic {\n    /// @dev generic / unspecified error\n    uint256 internal constant GENERIC = 0x00;\n    /// @dev used by the assert() builtin\n    uint256 internal constant ASSERT = 0x01;\n    /// @dev arithmetic underflow or overflow\n    uint256 internal constant UNDER_OVERFLOW = 0x11;\n    /// @dev division or modulo by zero\n    uint256 internal constant DIVISION_BY_ZERO = 0x12;\n    /// @dev enum conversion error\n    uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\n    /// @dev invalid encoding in storage\n    uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\n    /// @dev empty array pop\n    uint256 internal constant EMPTY_ARRAY_POP = 0x31;\n    /// @dev array out of bounds access\n    uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\n    /// @dev resource error (too large allocation or too large array)\n    uint256 internal constant RESOURCE_ERROR = 0x41;\n    /// @dev calling invalid internal function\n    uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\n\n    /// @dev Reverts with a panic code. Recommended to use with\n    /// the internal constants with predefined codes.\n    function panic(uint256 code) internal pure {\n        assembly (\"memory-safe\") {\n            mstore(0x00, 0x4e487b71)\n            mstore(0x20, code)\n            revert(0x1c, 0x24)\n        }\n    }\n}\n"},{"file_path":"npm/@openzeppelin/contracts-upgradeable@5.4.0/utils/PausableUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n    /// @custom:storage-location erc7201:openzeppelin.storage.Pausable\n    struct PausableStorage {\n        bool _paused;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Pausable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300;\n\n    function _getPausableStorage() private pure returns (PausableStorage storage $) {\n        assembly {\n            $.slot := PausableStorageLocation\n        }\n    }\n\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    /**\n     * @dev The operation failed because the contract is paused.\n     */\n    error EnforcedPause();\n\n    /**\n     * @dev The operation failed because the contract is not paused.\n     */\n    error ExpectedPause();\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    function __Pausable_init() internal onlyInitializing {\n    }\n\n    function __Pausable_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        PausableStorage storage $ = _getPausableStorage();\n        return $._paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        if (paused()) {\n            revert EnforcedPause();\n        }\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        if (!paused()) {\n            revert ExpectedPause();\n        }\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        PausableStorage storage $ = _getPausableStorage();\n        $._paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        PausableStorage storage $ = _getPausableStorage();\n        $._paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n"},{"file_path":"npm/@openzeppelin/contracts-upgradeable@5.4.0/utils/ReentrancyGuardUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,\n * consider using {ReentrancyGuardTransient} instead.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant NOT_ENTERED = 1;\n    uint256 private constant ENTERED = 2;\n\n    /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard\n    struct ReentrancyGuardStorage {\n        uint256 _status;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n    function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) {\n        assembly {\n            $.slot := ReentrancyGuardStorageLocation\n        }\n    }\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        $._status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        if ($._status == ENTERED) {\n            revert ReentrancyGuardReentrantCall();\n        }\n\n        // Any calls to nonReentrant after this point will fail\n        $._status = ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        $._status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();\n        return $._status == ENTERED;\n    }\n}\n"},{"file_path":"npm/@openzeppelin/contracts@5.4.0/interfaces/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC165} from \"../utils/introspection/IERC165.sol\";\n"},{"file_path":"project/contracts/fund/AssetManagement.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.26;\n\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { AccessControlUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\n\nimport { IStrategy } from \"./IStrategy.sol\";\n\nabstract contract AssetManagement is AccessControlUpgradeable {\n  using SafeERC20 for IERC20;\n\n  bytes32 public constant ASSET_MANAGER_ROLE = keccak256(\"ASSET_MANAGER_ROLE\");\n\n  struct Allocation {\n    address strategy;\n    uint96 capacity;\n  }\n\n  mapping(address => Allocation) public allocations;\n\n  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   */\n  uint256[49] private __gap;\n\n  function kill(address asset) public onlyRole(DEFAULT_ADMIN_ROLE) {\n    Allocation memory curAlloc = allocations[asset];\n    if (curAlloc.strategy != address(0)) {\n      IStrategy(curAlloc.strategy).kill();\n      curAlloc.strategy = address(0);\n      curAlloc.capacity = 0;\n      allocations[asset] = curAlloc;\n    }\n  }\n\n  function alloc(address asset, address strategy, uint96 capacity) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    Allocation memory oldAlloc = allocations[asset];\n    if (oldAlloc.strategy != address(0)) kill(asset);\n    allocations[asset] = Allocation({ strategy: strategy, capacity: capacity });\n  }\n\n  function manage(address asset, uint256 amount) external onlyRole(ASSET_MANAGER_ROLE) {\n    Allocation memory curAlloc = allocations[asset];\n    uint256 managed = IStrategy(curAlloc.strategy).totalSupply();\n    if (managed + amount > curAlloc.capacity) revert();\n    IERC20(asset).safeTransfer(curAlloc.strategy, amount);\n    IStrategy(curAlloc.strategy).deposit(amount);\n  }\n\n  function _transferOut(address asset, uint256 amount, address receiver) internal {\n    uint256 balance = IERC20(asset).balanceOf(address(this));\n    if (balance >= amount) {\n      IERC20(asset).safeTransfer(receiver, amount);\n    } else {\n      if (balance > 0) {\n        IERC20(asset).safeTransfer(receiver, balance);\n      }\n      unchecked {\n        uint256 diff = amount - balance;\n        Allocation memory curAlloc = allocations[asset];\n        if (curAlloc.strategy == address(0)) revert();\n        IStrategy(curAlloc.strategy).withdraw(diff, receiver);\n      }\n    }\n  }\n\n  function _balanceOf(address asset) internal view returns (uint256) {\n    uint256 balance = IERC20(asset).balanceOf(address(this));\n    address strategy = allocations[asset].strategy;\n    if (strategy == address(0)) return balance;\n    return balance + IStrategy(strategy).principal();\n  }\n}\n"},{"file_path":"project/contracts/fund/IStrategy.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IStrategy {\n  function principal() external view returns (uint256);\n\n  function totalSupply() external view returns (uint256);\n\n  function deposit(uint256 amount) external;\n\n  function withdraw(uint256 amount, address recipient) external;\n\n  function kill() external;\n\n  function harvest(address receiver) external;\n}\n"},{"file_path":"project/contracts/common/codec/WordCodec.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n// solhint-disable no-inline-assembly\n\n/// @dev A subset copied from the following contracts:\n///\n/// + `balancer-labs/v2-solidity-utils/contracts/helpers/WordCodec.sol`\n/// + `balancer-labs/v2-solidity-utils/contracts/helpers/WordCodecHelpers.sol`\nlibrary WordCodec {\n  /// @dev Inserts an unsigned integer of bitLength, shifted by an offset, into a 256 bit word,\n  /// replacing the old value. Returns the new word.\n  function insertUint(\n    bytes32 word,\n    uint256 value,\n    uint256 offset,\n    uint256 bitLength\n  ) internal pure returns (bytes32 result) {\n    // Equivalent to:\n    // uint256 mask = (1 << bitLength) - 1;\n    // bytes32 clearedWord = bytes32(uint256(word) & ~(mask << offset));\n    // result = clearedWord | bytes32(value << offset);\n    assembly {\n      let mask := sub(shl(bitLength, 1), 1)\n      let clearedWord := and(word, not(shl(offset, mask)))\n      result := or(clearedWord, shl(offset, value))\n    }\n  }\n\n  /// @dev Decodes and returns an unsigned integer with `bitLength` bits, shifted by an offset, from a 256 bit word.\n  function decodeUint(\n    bytes32 word,\n    uint256 offset,\n    uint256 bitLength\n  ) internal pure returns (uint256 result) {\n    // Equivalent to:\n    // result = uint256(word >> offset) & ((1 << bitLength) - 1);\n    assembly {\n      result := and(shr(offset, word), sub(shl(bitLength, 1), 1))\n    }\n  }\n\n  /// @dev Inserts a signed integer shifted by an offset into a 256 bit word, replacing the old value. Returns\n  /// the new word.\n  ///\n  /// Assumes `value` can be represented using `bitLength` bits.\n  function insertInt(\n    bytes32 word,\n    int256 value,\n    uint256 offset,\n    uint256 bitLength\n  ) internal pure returns (bytes32) {\n    unchecked {\n      uint256 mask = (1 << bitLength) - 1;\n      bytes32 clearedWord = bytes32(uint256(word) & ~(mask << offset));\n      // Integer values need masking to remove the upper bits of negative values.\n      return clearedWord | bytes32((uint256(value) & mask) << offset);\n    }\n  }\n\n  /// @dev Decodes and returns a signed integer with `bitLength` bits, shifted by an offset, from a 256 bit word.\n  function decodeInt(\n    bytes32 word,\n    uint256 offset,\n    uint256 bitLength\n  ) internal pure returns (int256 result) {\n    unchecked {\n      int256 maxInt = int256((1 << (bitLength - 1)) - 1);\n      uint256 mask = (1 << bitLength) - 1;\n\n      int256 value = int256(uint256(word >> offset) & mask);\n      // In case the decoded value is greater than the max positive integer that can be represented with bitLength\n      // bits, we know it was originally a negative integer. Therefore, we mask it to restore the sign in the 256 bit\n      // representation.\n      //\n      // Equivalent to:\n      // result = value > maxInt ? (value | int256(~mask)) : value;\n      assembly {\n        result := or(mul(gt(value, maxInt), not(mask)), value)\n      }\n    }\n  }\n\n  /// @dev Decodes and returns a boolean shifted by an offset from a 256 bit word.\n  function decodeBool(bytes32 word, uint256 offset) internal pure returns (bool result) {\n    // Equivalent to:\n    // result = (uint256(word >> offset) & 1) == 1;\n    assembly {\n      result := and(shr(offset, word), 1)\n    }\n  }\n\n  /// @dev Inserts a boolean value shifted by an offset into a 256 bit word, replacing the old value. Returns the new\n  /// word.\n  function insertBool(\n    bytes32 word,\n    bool value,\n    uint256 offset\n  ) internal pure returns (bytes32 result) {\n    // Equivalent to:\n    // bytes32 clearedWord = bytes32(uint256(word) & ~(1 << offset));\n    // bytes32 referenceInsertBool = clearedWord | bytes32(uint256(value ? 1 : 0) << offset);\n    assembly {\n      let clearedWord := and(word, not(shl(offset, 1)))\n      result := or(clearedWord, shl(offset, value))\n    }\n  }\n\n  function clearWordAtPosition(\n    bytes32 word,\n    uint256 offset,\n    uint256 bitLength\n  ) internal pure returns (bytes32 clearedWord) {\n    unchecked {\n      uint256 mask = (1 << bitLength) - 1;\n      clearedWord = bytes32(uint256(word) & ~(mask << offset));\n    }\n  }\n}\n"},{"file_path":"npm/@openzeppelin/contracts@5.4.0/utils/introspection/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},{"file_path":"npm/@openzeppelin/contracts@5.4.0/utils/structs/EnumerableSet.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.20;\n\nimport {Arrays} from \"../Arrays.sol\";\nimport {Math} from \"../math/Math.sol\";\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n * - Set can be cleared (all elements removed) in O(n).\n *\n * ```solidity\n * contract Example {\n *     // Add the library methods\n *     using EnumerableSet for EnumerableSet.AddressSet;\n *\n *     // Declare a set state variable\n *     EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * The following types are supported:\n *\n * - `bytes32` (`Bytes32Set`) since v3.3.0\n * - `address` (`AddressSet`) since v3.3.0\n * - `uint256` (`UintSet`) since v3.3.0\n * - `string` (`StringSet`) since v5.4.0\n * - `bytes` (`BytesSet`) since v5.4.0\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n    // To implement this library for multiple types with as little code\n    // repetition as possible, we write it in terms of a generic Set type with\n    // bytes32 values.\n    // The Set implementation uses private functions, and user-facing\n    // implementations (such as AddressSet) are just wrappers around the\n    // underlying Set.\n    // This means that we can only create new EnumerableSets for types that fit\n    // in bytes32.\n\n    struct Set {\n        // Storage of set values\n        bytes32[] _values;\n        // Position is the index of the value in the `values` array plus 1.\n        // Position 0 is used to mean a value is not in the set.\n        mapping(bytes32 value => uint256) _positions;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function _add(Set storage set, bytes32 value) private returns (bool) {\n        if (!_contains(set, value)) {\n            set._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._positions[value] = set._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function _remove(Set storage set, bytes32 value) private returns (bool) {\n        // We cache the value's position to prevent multiple reads from the same storage slot\n        uint256 position = set._positions[value];\n\n        if (position != 0) {\n            // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 valueIndex = position - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            if (valueIndex != lastIndex) {\n                bytes32 lastValue = set._values[lastIndex];\n\n                // Move the lastValue to the index where the value to delete is\n                set._values[valueIndex] = lastValue;\n                // Update the tracked position of the lastValue (that was just moved)\n                set._positions[lastValue] = position;\n            }\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the tracked position for the deleted slot\n            delete set._positions[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes all the values from a set. O(n).\n     *\n     * WARNING: This function has an unbounded cost that scales with set size. Developers should keep in mind that\n     * using it may render the function uncallable if the set grows to the point where clearing it consumes too much\n     * gas to fit in a block.\n     */\n    function _clear(Set storage set) private {\n        uint256 len = _length(set);\n        for (uint256 i = 0; i < len; ++i) {\n            delete set._positions[set._values[i]];\n        }\n        Arrays.unsafeSetLength(set._values, 0);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function _contains(Set storage set, bytes32 value) private view returns (bool) {\n        return set._positions[value] != 0;\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function _length(Set storage set) private view returns (uint256) {\n        return set._values.length;\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function _at(Set storage set, uint256 index) private view returns (bytes32) {\n        return set._values[index];\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function _values(Set storage set) private view returns (bytes32[] memory) {\n        return set._values;\n    }\n\n    /**\n     * @dev Return a slice of the set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function _values(Set storage set, uint256 start, uint256 end) private view returns (bytes32[] memory) {\n        unchecked {\n            end = Math.min(end, _length(set));\n            start = Math.min(start, end);\n\n            uint256 len = end - start;\n            bytes32[] memory result = new bytes32[](len);\n            for (uint256 i = 0; i < len; ++i) {\n                result[i] = Arrays.unsafeAccess(set._values, start + i).value;\n            }\n            return result;\n        }\n    }\n\n    // Bytes32Set\n\n    struct Bytes32Set {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _add(set._inner, value);\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _remove(set._inner, value);\n    }\n\n    /**\n     * @dev Removes all the values from a set. O(n).\n     *\n     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the\n     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.\n     */\n    function clear(Bytes32Set storage set) internal {\n        _clear(set._inner);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n        return _contains(set._inner, value);\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(Bytes32Set storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n        return _at(set._inner, index);\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        bytes32[] memory result;\n\n        assembly (\"memory-safe\") {\n            result := store\n        }\n\n        return result;\n    }\n\n    /**\n     * @dev Return a slice of the set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {\n        bytes32[] memory store = _values(set._inner, start, end);\n        bytes32[] memory result;\n\n        assembly (\"memory-safe\") {\n            result := store\n        }\n\n        return result;\n    }\n\n    // AddressSet\n\n    struct AddressSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(AddressSet storage set, address value) internal returns (bool) {\n        return _add(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(AddressSet storage set, address value) internal returns (bool) {\n        return _remove(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Removes all the values from a set. O(n).\n     *\n     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the\n     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.\n     */\n    function clear(AddressSet storage set) internal {\n        _clear(set._inner);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(AddressSet storage set, address value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(AddressSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(AddressSet storage set, uint256 index) internal view returns (address) {\n        return address(uint160(uint256(_at(set._inner, index))));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(AddressSet storage set) internal view returns (address[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        address[] memory result;\n\n        assembly (\"memory-safe\") {\n            result := store\n        }\n\n        return result;\n    }\n\n    /**\n     * @dev Return a slice of the set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {\n        bytes32[] memory store = _values(set._inner, start, end);\n        address[] memory result;\n\n        assembly (\"memory-safe\") {\n            result := store\n        }\n\n        return result;\n    }\n\n    // UintSet\n\n    struct UintSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(UintSet storage set, uint256 value) internal returns (bool) {\n        return _add(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(UintSet storage set, uint256 value) internal returns (bool) {\n        return _remove(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Removes all the values from a set. O(n).\n     *\n     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the\n     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.\n     */\n    function clear(UintSet storage set) internal {\n        _clear(set._inner);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(UintSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n        return uint256(_at(set._inner, index));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(UintSet storage set) internal view returns (uint256[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        uint256[] memory result;\n\n        assembly (\"memory-safe\") {\n            result := store\n        }\n\n        return result;\n    }\n\n    /**\n     * @dev Return a slice of the set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {\n        bytes32[] memory store = _values(set._inner, start, end);\n        uint256[] memory result;\n\n        assembly (\"memory-safe\") {\n            result := store\n        }\n\n        return result;\n    }\n\n    struct StringSet {\n        // Storage of set values\n        string[] _values;\n        // Position is the index of the value in the `values` array plus 1.\n        // Position 0 is used to mean a value is not in the set.\n        mapping(string value => uint256) _positions;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(StringSet storage set, string memory value) internal returns (bool) {\n        if (!contains(set, value)) {\n            set._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._positions[value] = set._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(StringSet storage set, string memory value) internal returns (bool) {\n        // We cache the value's position to prevent multiple reads from the same storage slot\n        uint256 position = set._positions[value];\n\n        if (position != 0) {\n            // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 valueIndex = position - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            if (valueIndex != lastIndex) {\n                string memory lastValue = set._values[lastIndex];\n\n                // Move the lastValue to the index where the value to delete is\n                set._values[valueIndex] = lastValue;\n                // Update the tracked position of the lastValue (that was just moved)\n                set._positions[lastValue] = position;\n            }\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the tracked position for the deleted slot\n            delete set._positions[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes all the values from a set. O(n).\n     *\n     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the\n     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.\n     */\n    function clear(StringSet storage set) internal {\n        uint256 len = length(set);\n        for (uint256 i = 0; i < len; ++i) {\n            delete set._positions[set._values[i]];\n        }\n        Arrays.unsafeSetLength(set._values, 0);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(StringSet storage set, string memory value) internal view returns (bool) {\n        return set._positions[value] != 0;\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function length(StringSet storage set) internal view returns (uint256) {\n        return set._values.length;\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(StringSet storage set, uint256 index) internal view returns (string memory) {\n        return set._values[index];\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(StringSet storage set) internal view returns (string[] memory) {\n        return set._values;\n    }\n\n    /**\n     * @dev Return a slice of the set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(StringSet storage set, uint256 start, uint256 end) internal view returns (string[] memory) {\n        unchecked {\n            end = Math.min(end, length(set));\n            start = Math.min(start, end);\n\n            uint256 len = end - start;\n            string[] memory result = new string[](len);\n            for (uint256 i = 0; i < len; ++i) {\n                result[i] = Arrays.unsafeAccess(set._values, start + i).value;\n            }\n            return result;\n        }\n    }\n\n    struct BytesSet {\n        // Storage of set values\n        bytes[] _values;\n        // Position is the index of the value in the `values` array plus 1.\n        // Position 0 is used to mean a value is not in the set.\n        mapping(bytes value => uint256) _positions;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(BytesSet storage set, bytes memory value) internal returns (bool) {\n        if (!contains(set, value)) {\n            set._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._positions[value] = set._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(BytesSet storage set, bytes memory value) internal returns (bool) {\n        // We cache the value's position to prevent multiple reads from the same storage slot\n        uint256 position = set._positions[value];\n\n        if (position != 0) {\n            // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 valueIndex = position - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            if (valueIndex != lastIndex) {\n                bytes memory lastValue = set._values[lastIndex];\n\n                // Move the lastValue to the index where the value to delete is\n                set._values[valueIndex] = lastValue;\n                // Update the tracked position of the lastValue (that was just moved)\n                set._positions[lastValue] = position;\n            }\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the tracked position for the deleted slot\n            delete set._positions[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes all the values from a set. O(n).\n     *\n     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the\n     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.\n     */\n    function clear(BytesSet storage set) internal {\n        uint256 len = length(set);\n        for (uint256 i = 0; i < len; ++i) {\n            delete set._positions[set._values[i]];\n        }\n        Arrays.unsafeSetLength(set._values, 0);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(BytesSet storage set, bytes memory value) internal view returns (bool) {\n        return set._positions[value] != 0;\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function length(BytesSet storage set) internal view returns (uint256) {\n        return set._values.length;\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(BytesSet storage set, uint256 index) internal view returns (bytes memory) {\n        return set._values[index];\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(BytesSet storage set) internal view returns (bytes[] memory) {\n        return set._values;\n    }\n\n    /**\n     * @dev Return a slice of the set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(BytesSet storage set, uint256 start, uint256 end) internal view returns (bytes[] memory) {\n        unchecked {\n            end = Math.min(end, length(set));\n            start = Math.min(start, end);\n\n            uint256 len = end - start;\n            bytes[] memory result = new bytes[](len);\n            for (uint256 i = 0; i < len; ++i) {\n                result[i] = Arrays.unsafeAccess(set._values, start + i).value;\n            }\n            return result;\n        }\n    }\n}\n"},{"file_path":"npm/@openzeppelin/contracts@5.4.0/utils/Comparators.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Comparators.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides a set of functions to compare values.\n *\n * _Available since v5.1._\n */\nlibrary Comparators {\n    function lt(uint256 a, uint256 b) internal pure returns (bool) {\n        return a < b;\n    }\n\n    function gt(uint256 a, uint256 b) internal pure returns (bool) {\n        return a > b;\n    }\n}\n"},{"file_path":"npm/@openzeppelin/contracts@5.4.0/utils/SlotDerivation.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/SlotDerivation.sol)\n// This file was procedurally generated from scripts/generate/templates/SlotDerivation.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots\n * corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by\n * the solidity language / compiler.\n *\n * See https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays[Solidity docs for mappings and dynamic arrays.].\n *\n * Example usage:\n * ```solidity\n * contract Example {\n *     // Add the library methods\n *     using StorageSlot for bytes32;\n *     using SlotDerivation for bytes32;\n *\n *     // Declare a namespace\n *     string private constant _NAMESPACE = \"<namespace>\"; // eg. OpenZeppelin.Slot\n *\n *     function setValueInNamespace(uint256 key, address newValue) internal {\n *         _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;\n *     }\n *\n *     function getValueInNamespace(uint256 key) internal view returns (address) {\n *         return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value;\n *     }\n * }\n * ```\n *\n * TIP: Consider using this library along with {StorageSlot}.\n *\n * NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking\n * upgrade safety will ignore the slots accessed through this library.\n *\n * _Available since v5.1._\n */\nlibrary SlotDerivation {\n    /**\n     * @dev Derive an ERC-7201 slot from a string (namespace).\n     */\n    function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1))\n            slot := and(keccak256(0x00, 0x20), not(0xff))\n        }\n    }\n\n    /**\n     * @dev Add an offset to a slot to get the n-th element of a structure or an array.\n     */\n    function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) {\n        unchecked {\n            return bytes32(uint256(slot) + pos);\n        }\n    }\n\n    /**\n     * @dev Derive the location of the first element in an array from the slot where the length is stored.\n     */\n    function deriveArray(bytes32 slot) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, slot)\n            result := keccak256(0x00, 0x20)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, and(key, shr(96, not(0))))\n            mstore(0x20, slot)\n            result := keccak256(0x00, 0x40)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, iszero(iszero(key)))\n            mstore(0x20, slot)\n            result := keccak256(0x00, 0x40)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, key)\n            mstore(0x20, slot)\n            result := keccak256(0x00, 0x40)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, key)\n            mstore(0x20, slot)\n            result := keccak256(0x00, 0x40)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, key)\n            mstore(0x20, slot)\n            result := keccak256(0x00, 0x40)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            let length := mload(key)\n            let begin := add(key, 0x20)\n            let end := add(begin, length)\n            let cache := mload(end)\n            mstore(end, slot)\n            result := keccak256(begin, add(length, 0x20))\n            mstore(end, cache)\n        }\n    }\n\n    /**\n     * @dev Derive the location of a mapping element from the key.\n     */\n    function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) {\n        assembly (\"memory-safe\") {\n            let length := mload(key)\n            let begin := add(key, 0x20)\n            let end := add(begin, length)\n            let cache := mload(end)\n            mstore(end, slot)\n            result := keccak256(begin, add(length, 0x20))\n            mstore(end, cache)\n        }\n    }\n}\n"},{"file_path":"project/contracts/interfaces/IShortPool.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { IPool } from \"./IPool.sol\";\n\ninterface IShortPool is IPool {\n  /*************************\n   * Public View Functions *\n   *************************/\n\n  /// @notice The address of the debt token.\n  function debtToken() external view returns (address);\n\n  /// @notice The address of the credit note token.\n  function creditNote() external view returns (address);\n\n  /****************************\n   * Public Mutated Functions *\n   ****************************/\n\n  /// @notice Whether the pool is under collateral.\n  /// @return underCollateral Whether the pool is under collateral.\n  /// @return shortfall The amount of shortfall raw debt token.\n  function isUnderCollateral() external returns (bool underCollateral, uint256 shortfall);\n\n  /// @notice Kill the pool.\n  function kill() external;\n\n  /// @notice Redeem credit note to get collateral tokens.\n  /// @param creditNoteAmount The amount of credit note to redeem.\n  /// @return rawColls The amount of collateral tokens to redeemed.\n  function redeemByCreditNote(uint256 creditNoteAmount) external returns (uint256 rawColls);\n}\n"},{"file_path":"project/contracts/interfaces/ILongPool.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { IPool } from \"./IPool.sol\";\n\ninterface ILongPool is IPool {\n  /// @notice Reduce the collateral of the pool.\n  /// @param rawAmount The amount of raw collateral to reduce.\n  function reduceCollateral(uint256 rawAmount) external;\n}\n"},{"file_path":"project/contracts/interfaces/ILongPoolManager.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { IPoolManager } from \"./IPoolManager.sol\";\n\ninterface ILongPoolManager is IPoolManager {\n  /**********\n   * Events *\n   **********/\n\n  /// @notice Emitted when the threshold for permissionless liquidate/rebalance is updated.\n  /// @param oldThreshold The value of previous threshold.\n  /// @param newThreshold The value of current threshold.\n  event UpdatePermissionedLiquidationThreshold(uint256 oldThreshold, uint256 newThreshold);\n\n  /// @notice Emitted when rebalance for a tick happened.\n  /// @param pool The address of pool rebalanced.\n  /// @param tick The index of tick rebalanced.\n  /// @param colls The amount of collateral tokens rebalanced.\n  /// @param fxUSDDebts The amount of fxUSD rebalanced.\n  /// @param stableDebts The amount of stable token (a.k.a USDC) rebalanced.\n  event RebalanceTick(address indexed pool, int16 indexed tick, uint256 colls, uint256 fxUSDDebts, uint256 stableDebts);\n\n  /// @notice Emitted when rebalance happened.\n  /// @param pool The address of pool rebalanced.\n  /// @param colls The amount of collateral tokens rebalanced.\n  /// @param fxUSDDebts The amount of fxUSD rebalanced.\n  /// @param stableDebts The amount of stable token (a.k.a USDC) rebalanced.\n  event Rebalance(address indexed pool, uint256 colls, uint256 fxUSDDebts, uint256 stableDebts);\n\n  /// @notice Emitted when liquidate happened.\n  /// @param pool The address of pool liquidated.\n  /// @param colls The amount of collateral tokens liquidated.\n  /// @param fxUSDDebts The amount of fxUSD liquidated.\n  /// @param stableDebts The amount of stable token (a.k.a USDC) liquidated.\n  event Liquidate(address indexed pool, uint256 colls, uint256 fxUSDDebts, uint256 stableDebts);\n\n  /// @notice Emitted when the short borrow capacity ratio for the given long pool is updated.\n  /// @param longPool The address of the long pool.\n  /// @param oldRatio The old short borrow capacity ratio.\n  /// @param newRatio The new short borrow capacity ratio.\n  event UpdateShortBorrowCapacityRatio(address indexed longPool, uint256 oldRatio, uint256 newRatio);\n\n  /*************************\n   * Public View Functions *\n   *************************/\n\n  /// @notice The address of FxUSDSave.\n  function fxBASE() external view returns (address);\n\n  /****************************\n   * Public Mutated Functions *\n   ****************************/\n\n  /// @notice Open a new position or operate on an old position.\n  /// @param pool The address of pool to operate.\n  /// @param positionId The id of the position. If `positionId=0`, it means we need to open a new position.\n  /// @param newColl The amount of collateral token to supply (positive value) or withdraw (negative value).\n  /// @param newDebt The amount of debt token to borrow (positive value) or repay (negative value).\n  /// @param useStable Whether to use stable token for repay.\n  /// @return actualPositionId The id of this position.\n  function operate(\n    address pool,\n    uint256 positionId,\n    int256 newColl,\n    int256 newDebt,\n    bool useStable\n  ) external returns (uint256 actualPositionId);\n\n  /// @notice Rebalance all positions in the given tick.\n  /// @param pool The address of pool to rebalance.\n  /// @param receiver The address of recipient for rebalanced tokens.\n  /// @param tick The index of tick to rebalance.\n  /// @param maxFxUSD The maximum amount of fxUSD to rebalance.\n  /// @param maxStable The maximum amount of stable token (a.k.a USDC) to rebalance.\n  /// @return colls The amount of collateral tokens rebalanced.\n  /// @return fxUSDUsed The amount of fxUSD used to rebalance.\n  /// @return stableUsed The amount of stable token used to rebalance.\n  function rebalance(\n    address pool,\n    address receiver,\n    int16 tick,\n    uint256 maxFxUSD,\n    uint256 maxStable\n  ) external returns (uint256 colls, uint256 fxUSDUsed, uint256 stableUsed);\n\n  /// @notice Rebalance all positions in the given tick.\n  /// @param pool The address of pool to rebalance.\n  /// @param receiver The address of recipient for rebalanced tokens.\n  /// @param maxFxUSD The maximum amount of fxUSD to rebalance.\n  /// @param maxStable The maximum amount of stable token (a.k.a USDC) to rebalance.\n  /// @return colls The amount of collateral tokens rebalanced.\n  /// @return fxUSDUsed The amount of fxUSD used to rebalance.\n  /// @return stableUsed The amount of stable token used to rebalance.\n  function rebalance(\n    address pool,\n    address receiver,\n    uint256 maxFxUSD,\n    uint256 maxStable\n  ) external returns (uint256 colls, uint256 fxUSDUsed, uint256 stableUsed);\n\n  /// @notice Liquidate a given position.\n  /// @param pool The address of pool to liquidate.\n  /// @param receiver The address of recipient for liquidated tokens.\n  /// @param maxFxUSD The maximum amount of fxUSD to liquidate.\n  /// @param maxStable The maximum amount of stable token (a.k.a USDC) to liquidate.\n  /// @return colls The amount of collateral tokens liquidated.\n  /// @return fxUSDUsed The amount of fxUSD used to liquidate.\n  /// @return stableUsed The amount of stable token used to liquidate.\n  function liquidate(\n    address pool,\n    address receiver,\n    uint256 maxFxUSD,\n    uint256 maxStable\n  ) external returns (uint256 colls, uint256 fxUSDUsed, uint256 stableUsed);\n\n  /// @notice Borrow collateral token from long pool.\n  /// @param longPool The address of long pool.\n  /// @param shortPool The address of short pool.\n  /// @param amount The amount of collateral token to borrow.\n  function borrow(address longPool, address shortPool, uint256 amount) external;\n\n  /// @notice Repay collateral token to long pool.\n  /// @param longPool The address of long pool.\n  /// @param shortPool The address of short pool.\n  /// @param amount The amount of collateral token to repay.\n  function repay(address longPool, address shortPool, uint256 amount) external;\n\n  /// @notice Repay collateral token to long pool by credit note.\n  /// @param longPool The address of long pool.\n  /// @param shortPool The address of short pool.\n  /// @param amount The amount of credit note token to repay.\n  function repayByCreditNote(address longPool, address shortPool, uint256 amount) external;\n\n  /// @notice Redeem fxUSD for settle killed short pool.\n  /// @param longPool The address of long pool.\n  /// @param amountFxUSD The amount of fxUSD to redeem.\n  /// @return colls The amount of collateral token redeemed.\n  function redeemForSettle(\n    address longPool,\n    uint256 amountFxUSD\n  ) external returns (uint256 colls);\n\n  /// @notice Settle short pool.\n  /// @param longPool The address of long pool.\n  /// @param shortPool The address of short pool.\n  /// @param shortfall The amount of shortfall collateral token.\n  function settleShortPool(address longPool, address shortPool, uint256 shortfall) external;\n}\n"},{"file_path":"project/contracts/core/ProtocolFees.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.26;\n\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { AccessControlUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol\";\nimport { PausableUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol\";\n\nimport { IPool } from \"../interfaces/IPool.sol\";\nimport { IProtocolFees } from \"../interfaces/IProtocolFees.sol\";\n\nimport { WordCodec } from \"../common/codec/WordCodec.sol\";\n\nabstract contract ProtocolFees is AccessControlUpgradeable, PausableUpgradeable, IProtocolFees {\n  using SafeERC20 for IERC20;\n  using WordCodec for bytes32;\n\n  /**********\n   * Errors *\n   **********/\n\n  /// @dev Thrown when the given address is zero.\n  error ErrorZeroAddress();\n\n  /// @dev Thrown when the given value exceeds maximum value.\n  error ErrorValueTooLarge();\n\n  /*************\n   * Constants *\n   *************/\n\n  /// @dev The maximum expense ratio.\n  uint256 private constant MAX_EXPENSE_RATIO = 5e8; // 50%\n\n  /// @dev The maximum harvester ratio.\n  uint256 private constant MAX_HARVESTER_RATIO = 2e8; // 20%\n\n  /// @dev The maximum flash loan fee ratio.\n  uint256 private constant MAX_FLASH_LOAN_FEE_RATIO = 1e8; // 10%\n\n  /// @dev The maximum redeem fee ratio.\n  uint256 private constant MAX_REDEEM_FEE_RATIO = 1e8; // 10%\n\n  /// @dev The offset of general expense ratio in `_miscData`.\n  uint256 private constant REWARDS_EXPENSE_RATIO_OFFSET = 0;\n\n  /// @dev The offset of harvester ratio in `_miscData`.\n  uint256 private constant HARVESTER_RATIO_OFFSET = 30;\n\n  /// @dev The offset of flash loan ratio in `_miscData`.\n  uint256 private constant FLASH_LOAN_RATIO_OFFSET = 60;\n\n  /// @dev The offset of redeem fee ratio in `_miscData`.\n  uint256 private constant REDEEM_FEE_RATIO_OFFSET = 90;\n\n  /// @dev The offset of funding expense ratio in `_miscData`.\n  uint256 private constant FUNDING_EXPENSE_RATIO_OFFSET = 120;\n\n  /// @dev The offset of liquidation expense ratio in `_miscData`.\n  uint256 private constant LIQUIDATION_EXPENSE_RATIO_OFFSET = 150;\n\n  /// @dev The precision used to compute fees.\n  uint256 internal constant FEE_PRECISION = 1e9;\n\n  /*************\n   * Variables *\n   *************/\n\n  /// @dev `_miscData` is a storage slot that can be used to store unrelated pieces of information.\n  /// All pools store the *expense ratio*, *harvester ratio* and *withdraw fee percentage*, but\n  /// the `miscData`can be extended to store more pieces of information.\n  ///\n  /// The *expense ratio* is stored in the first most significant 32 bits, and the *harvester ratio* is\n  /// stored in the next most significant 32 bits, and the *withdraw fee percentage* is stored in the\n  /// next most significant 32 bits, leaving the remaining 160 bits free to store any other information\n  /// derived pools might need.\n  ///\n  /// - The *expense ratio* and *harvester ratio* are charged each time when harvester harvest the pool revenue.\n  /// - The *withdraw fee percentage* is charged each time when user try to withdraw assets from the pool.\n  ///\n  /// [ rewards expense ratio | harvester ratio | flash loan ratio | redeem ratio | funding expense ratio | liquidation expense ratio | available ]\n  /// [        30 bits        |     30 bits     |     30  bits     |   30  bits   |        30 bits        |          30 bits          |  76 bits  ]\n  /// [ MSB                                                                                                                                   LSB ]\n  bytes32 internal _miscData;\n\n  /// @inheritdoc IProtocolFees\n  address public treasury;\n\n  /// @inheritdoc IProtocolFees\n  /// @dev Hold fees including open.\n  address public openRevenuePool;\n\n  /// @inheritdoc IProtocolFees\n  address public reservePool;\n\n  /// @inheritdoc IProtocolFees\n  mapping(address => uint256) public accumulatedPoolOpenFees;\n\n  /// @inheritdoc IProtocolFees\n  /// @dev Hold fees including close\n  address public closeRevenuePool;\n\n  /// @inheritdoc IProtocolFees\n  mapping(address => uint256) public accumulatedPoolCloseFees;\n\n  /// @inheritdoc IProtocolFees\n  /// @dev Hold fees including redeem, liquidation and rebalance.\n  address public miscRevenuePool;\n\n  /// @inheritdoc IProtocolFees\n  mapping(address => uint256) public accumulatedPoolMiscFees;\n\n  /***************\n   * Constructor *\n   ***************/\n\n  function __ProtocolFees_init(\n    uint256 _expenseRatio,\n    uint256 _harvesterRatio,\n    uint256 _flashLoanFeeRatio,\n    address _treasury,\n    address _revenuePool,\n    address _reservePool\n  ) internal onlyInitializing {\n    _updateFundingExpenseRatio(_expenseRatio);\n    _updateRewardsExpenseRatio(_expenseRatio);\n    _updateLiquidationExpenseRatio(_expenseRatio);\n    _updateHarvesterRatio(_harvesterRatio);\n    _updateFlashLoanFeeRatio(_flashLoanFeeRatio);\n    _updateTreasury(_treasury);\n    _updateOpenRevenuePool(_revenuePool);\n    _updateCloseRevenuePool(_revenuePool);\n    _updateMiscRevenuePool(_revenuePool);\n    _updateReservePool(_reservePool);\n  }\n\n  /*************************\n   * Public View Functions *\n   *************************/\n\n  /// @inheritdoc IProtocolFees\n  function getFundingExpenseRatio() public view returns (uint256) {\n    return _miscData.decodeUint(FUNDING_EXPENSE_RATIO_OFFSET, 30);\n  }\n\n  /// @inheritdoc IProtocolFees\n  function getRewardsExpenseRatio() public view returns (uint256) {\n    return _miscData.decodeUint(REWARDS_EXPENSE_RATIO_OFFSET, 30);\n  }\n\n  /// @inheritdoc IProtocolFees\n  function getLiquidationExpenseRatio() public view returns (uint256) {\n    return _miscData.decodeUint(LIQUIDATION_EXPENSE_RATIO_OFFSET, 30);\n  }\n\n  /// @inheritdoc IProtocolFees\n  function getHarvesterRatio() public view returns (uint256) {\n    return _miscData.decodeUint(HARVESTER_RATIO_OFFSET, 30);\n  }\n\n  /* @dev removed to reduce codesize, since it is not used.\n  /// @inheritdoc IProtocolFees\n  function getFundingFxSaveRatio() external view returns (uint256) {\n    return FEE_PRECISION - getFundingExpenseRatio() - getHarvesterRatio();\n  }\n  */\n\n  /* @dev removed to reduce codesize, since it is not used.\n  /// @inheritdoc IProtocolFees\n  function getRewardsFxSaveRatio() external view returns (uint256) {\n    unchecked {\n      return FEE_PRECISION - getRewardsExpenseRatio() - getHarvesterRatio();\n    }\n  }\n  */\n\n  /// @inheritdoc IProtocolFees\n  function getFlashLoanFeeRatio() public view returns (uint256) {\n    return _miscData.decodeUint(FLASH_LOAN_RATIO_OFFSET, 30);\n  }\n\n  /// @inheritdoc IProtocolFees\n  function getRedeemFeeRatio() public view returns (uint256) {\n    return _miscData.decodeUint(REDEEM_FEE_RATIO_OFFSET, 30);\n  }\n\n  /****************************\n   * Public Mutated Functions *\n   ****************************/\n\n  /// @inheritdoc IProtocolFees\n  function withdrawAccumulatedPoolFee(address[] memory pools) external {\n    for (uint256 i = 0; i < pools.length; ++i) {\n      _takeAccumulatedPoolFee(pools[i]);\n    }\n  }\n\n  /************************\n   * Restricted Functions *\n   ************************/\n\n  /// @notice Change address of reserve pool contract.\n  /// @param _newReservePool The new address of reserve pool contract.\n  function updateReservePool(address _newReservePool) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    _updateReservePool(_newReservePool);\n  }\n\n  /// @notice Change address of treasury contract.\n  /// @param _newTreasury The new address of treasury contract.\n  function updateTreasury(address _newTreasury) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    _updateTreasury(_newTreasury);\n  }\n\n  /// @notice Change address of open revenue pool contract.\n  /// @param _newPool The new address of revenue pool contract.\n  function updateOpenRevenuePool(address _newPool) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    _updateOpenRevenuePool(_newPool);\n  }\n\n  /// @notice Change address of close revenue pool contract.\n  /// @param _newPool The new address of revenue pool contract.\n  function updateCloseRevenuePool(address _newPool) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    _updateCloseRevenuePool(_newPool);\n  }\n\n  /// @notice Change address of misc revenue pool contract.\n  /// @param _newPool The new address of revenue pool contract.\n  function updateMiscRevenuePool(address _newPool) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    _updateMiscRevenuePool(_newPool);\n  }\n\n  /// @notice Update the fee ratio distributed to treasury.\n  /// @param newRewardsRatio The new ratio for rewards to update, multiplied by 1e9.\n  /// @param newFundingRatio The new ratio for funding to update, multiplied by 1e9.\n  /// @param newLiquidationRatio The new ratio for liquidation/rebalance to update, multiplied by 1e9.\n  function updateExpenseRatio(\n    uint32 newRewardsRatio,\n    uint32 newFundingRatio,\n    uint32 newLiquidationRatio\n  ) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    _updateRewardsExpenseRatio(newRewardsRatio);\n    _updateFundingExpenseRatio(newFundingRatio);\n    _updateLiquidationExpenseRatio(newLiquidationRatio);\n  }\n\n  /// @notice Update the fee ratio distributed to harvester.\n  /// @param newRatio The new ratio to update, multiplied by 1e9.\n  function updateHarvesterRatio(uint32 newRatio) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    _updateHarvesterRatio(newRatio);\n  }\n\n  /// @notice Update the flash loan fee ratio.\n  /// @param newRatio The new ratio to update, multiplied by 1e9.\n  function updateFlashLoanFeeRatio(uint32 newRatio) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    _updateFlashLoanFeeRatio(newRatio);\n  }\n\n  /// @notice Update the redeem fee ratio.\n  /// @param newRatio The new ratio to update, multiplied by 1e9.\n  function updateRedeemFeeRatio(uint32 newRatio) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    _updateRedeemFeeRatio(newRatio);\n  }\n\n  /**********************\n   * Internal Functions *\n   **********************/\n\n  /// @dev Internal function to change address of treasury contract.\n  /// @param _newTreasury The new address of treasury contract.\n  function _updateTreasury(address _newTreasury) private {\n    _checkAddressNotZero(_newTreasury);\n\n    address _oldTreasury = treasury;\n    treasury = _newTreasury;\n\n    emit UpdateTreasury(_oldTreasury, _newTreasury);\n  }\n\n  /// @dev Internal function to change address of revenue pool contract.\n  /// @param _newPool The new address of revenue pool contract.\n  function _updateOpenRevenuePool(address _newPool) private {\n    _checkAddressNotZero(_newPool);\n\n    address _oldPool = openRevenuePool;\n    openRevenuePool = _newPool;\n\n    emit UpdateOpenRevenuePool(_oldPool, _newPool);\n  }\n\n  /// @dev Internal function to change address of revenue pool contract.\n  /// @param _newPool The new address of revenue pool contract.\n  function _updateCloseRevenuePool(address _newPool) private {\n    _checkAddressNotZero(_newPool);\n\n    address _oldPool = closeRevenuePool;\n    closeRevenuePool = _newPool;\n\n    emit UpdateCloseRevenuePool(_oldPool, _newPool);\n  }\n\n  /// @dev Internal function to change address of revenue pool contract.\n  /// @param _newPool The new address of revenue pool contract.\n  function _updateMiscRevenuePool(address _newPool) private {\n    _checkAddressNotZero(_newPool);\n\n    address _oldPool = miscRevenuePool;\n    miscRevenuePool = _newPool;\n\n    emit UpdateMiscRevenuePool(_oldPool, _newPool);\n  }\n\n  /// @dev Internal function to change the address of reserve pool contract.\n  /// @param newReservePool The new address of reserve pool contract.\n  function _updateReservePool(address newReservePool) private {\n    _checkAddressNotZero(newReservePool);\n\n    address oldReservePool = reservePool;\n    reservePool = newReservePool;\n\n    emit UpdateReservePool(oldReservePool, newReservePool);\n  }\n\n  /// @dev Internal function to update the misc data.\n  /// @param newValue The new value to update.\n  /// @param offset The offset of the value to update.\n  /// @param length The length of the value to update.\n  /// @return oldValue The old value.\n  function _updateMiscData(uint256 newValue, uint256 offset, uint256 length) private returns (uint256 oldValue) {\n    bytes32 _data = _miscData;\n    oldValue = _miscData.decodeUint(offset, length);\n    _miscData = _data.insertUint(newValue, offset, length);\n\n    return oldValue;\n  }\n\n  /// @dev Internal function to update the fee ratio distributed to treasury.\n  /// @param newRatio The new ratio to update, multiplied by 1e9.\n  function _updateRewardsExpenseRatio(uint256 newRatio) private {\n    _checkValueTooLarge(newRatio, MAX_EXPENSE_RATIO);\n    uint256 oldRatio = _updateMiscData(newRatio, REWARDS_EXPENSE_RATIO_OFFSET, 30);\n    emit UpdateRewardsExpenseRatio(oldRatio, newRatio);\n  }\n\n  /// @dev Internal function to update the fee ratio distributed to treasury.\n  /// @param newRatio The new ratio to update, multiplied by 1e9.\n  function _updateLiquidationExpenseRatio(uint256 newRatio) private {\n    _checkValueTooLarge(newRatio, MAX_EXPENSE_RATIO);\n    uint256 oldRatio = _updateMiscData(newRatio, LIQUIDATION_EXPENSE_RATIO_OFFSET, 30);\n    emit UpdateLiquidationExpenseRatio(oldRatio, newRatio);\n  }\n\n  /// @dev Internal function to update the fee ratio distributed to treasury.\n  /// @param newRatio The new ratio to update, multiplied by 1e9.\n  function _updateFundingExpenseRatio(uint256 newRatio) private {\n    _checkValueTooLarge(newRatio, MAX_EXPENSE_RATIO);\n    uint256 oldRatio = _updateMiscData(newRatio, FUNDING_EXPENSE_RATIO_OFFSET, 30);\n    emit UpdateFundingExpenseRatio(oldRatio, newRatio);\n  }\n\n  /// @dev Internal function to update the fee ratio distributed to harvester.\n  /// @param newRatio The new ratio to update, multiplied by 1e9.\n  function _updateHarvesterRatio(uint256 newRatio) private {\n    _checkValueTooLarge(newRatio, MAX_HARVESTER_RATIO);\n    uint256 oldRatio = _updateMiscData(newRatio, HARVESTER_RATIO_OFFSET, 30);\n    emit UpdateHarvesterRatio(oldRatio, newRatio);\n  }\n\n  /// @dev Internal function to update the flash loan fee ratio.\n  /// @param newRatio The new ratio to update, multiplied by 1e9.\n  function _updateFlashLoanFeeRatio(uint256 newRatio) private {\n    _checkValueTooLarge(newRatio, MAX_FLASH_LOAN_FEE_RATIO);\n    uint256 oldRatio = _updateMiscData(newRatio, FLASH_LOAN_RATIO_OFFSET, 30);\n    emit UpdateFlashLoanFeeRatio(oldRatio, newRatio);\n  }\n\n  /// @dev Internal function to update the redeem fee ratio.\n  /// @param newRatio The new ratio to update, multiplied by 1e9.\n  function _updateRedeemFeeRatio(uint256 newRatio) private {\n    _checkValueTooLarge(newRatio, MAX_REDEEM_FEE_RATIO);\n    uint256 oldRatio = _updateMiscData(newRatio, REDEEM_FEE_RATIO_OFFSET, 30);\n    emit UpdateRedeemFeeRatio(oldRatio, newRatio);\n  }\n\n  /// @dev Internal function to accumulate protocol fee for the given pool.\n  /// @param pool The address of pool.\n  /// @param amount The amount of protocol fee.\n  function _accumulatePoolOpenFee(address pool, uint256 amount) internal {\n    unchecked {\n      accumulatedPoolOpenFees[pool] += amount;\n    }\n  }\n\n  /// @dev Internal function to accumulate protocol fee for the given pool.\n  /// @param pool The address of pool.\n  /// @param amount The amount of protocol fee.\n  function _accumulatePoolCloseFee(address pool, uint256 amount) internal {\n    unchecked {\n      accumulatedPoolCloseFees[pool] += amount;\n    }\n  }\n\n  /// @dev Internal function to accumulate protocol fee for the given pool.\n  /// @param pool The address of pool.\n  /// @param amount The amount of protocol fee.\n  function _accumulatePoolMiscFee(address pool, uint256 amount) internal {\n    unchecked {\n      accumulatedPoolMiscFees[pool] += amount;\n    }\n  }\n\n  /// @dev Internal function to withdraw accumulated protocol fee for the given pool.\n  /// @param pool The address of pool.\n  function _takeAccumulatedPoolFee(address pool) internal virtual {\n    address collateralToken = IPool(pool).collateralToken();\n    uint256 fees = accumulatedPoolOpenFees[pool];\n    if (fees > 0) {\n      IERC20(collateralToken).safeTransfer(openRevenuePool, fees);\n      accumulatedPoolOpenFees[pool] = 0;\n    }\n    fees = accumulatedPoolCloseFees[pool];\n    if (fees > 0) {\n      IERC20(collateralToken).safeTransfer(closeRevenuePool, fees);\n      accumulatedPoolCloseFees[pool] = 0;\n    }\n    fees = accumulatedPoolMiscFees[pool];\n    if (fees > 0) {\n      IERC20(collateralToken).safeTransfer(miscRevenuePool, fees);\n      accumulatedPoolMiscFees[pool] = 0;\n    }\n  }\n\n  /// @dev Internal function to check value not too large.\n  /// @param value The value to check.\n  /// @param upperBound The upper bound for the given value.\n  function _checkValueTooLarge(uint256 value, uint256 upperBound) internal pure {\n    if (value > upperBound) revert ErrorValueTooLarge();\n  }\n\n  /// @dev Internal function to check address is nonzero\n  function _checkAddressNotZero(address value) internal pure {\n    if (value == address(0)) revert ErrorZeroAddress();\n  }\n\n  /**\n   * @dev This empty reserved space is put in place to allow future versions to add new\n   * variables without shifting down storage in the inheritance chain.\n   */\n  uint256[41] private __gap;\n}\n"},{"file_path":"project/contracts/rate-provider/interfaces/IRateProvider.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IRateProvider {\n  /// @notice Return the exchange rate from wrapped token to underlying rate,\n  /// multiplied by 1e18.\n  function getRate() external view returns (uint256);\n}\n"},{"file_path":"project/contracts/interfaces/ICreditNote.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface ICreditNote {\n  /****************************\n   * Public Mutated Functions *\n   ****************************/\n\n  /// @notice Mint the credit note to the given address.\n  /// @param to The address to mint the credit note to.\n  /// @param amount The amount of credit note to mint.\n  function mint(address to, uint256 amount) external;\n\n  /// @notice Burn the credit note from the given address.\n  /// @param from The address to burn the credit note from.\n  /// @param amount The amount of credit note to burn.\n  function burn(address from, uint256 amount) external;\n}\n"},{"file_path":"npm/@openzeppelin/contracts@5.4.0/utils/math/Math.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\nimport {Panic} from \"../Panic.sol\";\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Return the 512-bit addition of two uint256.\n     *\n     * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.\n     */\n    function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n        assembly (\"memory-safe\") {\n            low := add(a, b)\n            high := lt(low, a)\n        }\n    }\n\n    /**\n     * @dev Return the 512-bit multiplication of two uint256.\n     *\n     * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.\n     */\n    function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n        // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use\n        // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n        // variables such that product = high * 2²⁵⁶ + low.\n        assembly (\"memory-safe\") {\n            let mm := mulmod(a, b, not(0))\n            low := mul(a, b)\n            high := sub(sub(mm, low), lt(mm, low))\n        }\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a + b;\n            success = c >= a;\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a - b;\n            success = c <= a;\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a * b;\n            assembly (\"memory-safe\") {\n                // Only true when the multiplication doesn't overflow\n                // (c / a == b) || (a == 0)\n                success := or(eq(div(c, a), b), iszero(a))\n            }\n            // equivalent to: success ? c : 0\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            success = b > 0;\n            assembly (\"memory-safe\") {\n                // The `DIV` opcode returns zero when the denominator is 0.\n                result := div(a, b)\n            }\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            success = b > 0;\n            assembly (\"memory-safe\") {\n                // The `MOD` opcode returns zero when the denominator is 0.\n                result := mod(a, b)\n            }\n        }\n    }\n\n    /**\n     * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.\n     */\n    function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\n        (bool success, uint256 result) = tryAdd(a, b);\n        return ternary(success, result, type(uint256).max);\n    }\n\n    /**\n     * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\n     */\n    function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\n        (, uint256 result) = trySub(a, b);\n        return result;\n    }\n\n    /**\n     * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.\n     */\n    function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\n        (bool success, uint256 result) = tryMul(a, b);\n        return ternary(success, result, type(uint256).max);\n    }\n\n    /**\n     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\n     *\n     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\n     * one branch when needed, making this function more expensive.\n     */\n    function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\n        unchecked {\n            // branchless ternary works because:\n            // b ^ (a ^ b) == a\n            // b ^ 0 == b\n            return b ^ ((a ^ b) * SafeCast.toUint(condition));\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return ternary(a > b, a, b);\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return ternary(a < b, a, b);\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n\n        // The following calculation ensures accurate ceiling division without overflow.\n        // Since a is non-zero, (a - 1) / b will not overflow.\n        // The largest possible result occurs when (a - 1) / b is type(uint256).max,\n        // but the largest value we can obtain is type(uint256).max - 1, which happens\n        // when a = type(uint256).max and b = 1.\n        unchecked {\n            return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\n        }\n    }\n\n    /**\n     * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n     * denominator == 0.\n     *\n     * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            (uint256 high, uint256 low) = mul512(x, y);\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (high == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return low / denominator;\n            }\n\n            // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.\n            if (denominator <= high) {\n                Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\n            }\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [high low].\n            uint256 remainder;\n            assembly (\"memory-safe\") {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                high := sub(high, gt(remainder, low))\n                low := sub(low, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\n            assembly (\"memory-safe\") {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [high low] by twos.\n                low := div(low, twos)\n\n                // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from high into low.\n            low |= high * twos;\n\n            // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such\n            // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv ≡ 1 mod 2⁴.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n            // works in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶\n            inverse *= 2 - denominator * inverse; // inverse mod 2³²\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is\n            // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high\n            // is no longer required.\n            result = low * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\n    }\n\n    /**\n     * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\n     */\n    function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\n        unchecked {\n            (uint256 high, uint256 low) = mul512(x, y);\n            if (high >= 1 << n) {\n                Panic.panic(Panic.UNDER_OVERFLOW);\n            }\n            return (high << (256 - n)) | (low >> n);\n        }\n    }\n\n    /**\n     * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\n     */\n    function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\n        return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\n    }\n\n    /**\n     * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\n     *\n     * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\n     * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\n     *\n     * If the input value is not inversible, 0 is returned.\n     *\n     * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\n     * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\n     */\n    function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\n        unchecked {\n            if (n == 0) return 0;\n\n            // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\n            // Used to compute integers x and y such that: ax + ny = gcd(a, n).\n            // When the gcd is 1, then the inverse of a modulo n exists and it's x.\n            // ax + ny = 1\n            // ax = 1 + (-y)n\n            // ax ≡ 1 (mod n) # x is the inverse of a modulo n\n\n            // If the remainder is 0 the gcd is n right away.\n            uint256 remainder = a % n;\n            uint256 gcd = n;\n\n            // Therefore the initial coefficients are:\n            // ax + ny = gcd(a, n) = n\n            // 0a + 1n = n\n            int256 x = 0;\n            int256 y = 1;\n\n            while (remainder != 0) {\n                uint256 quotient = gcd / remainder;\n\n                (gcd, remainder) = (\n                    // The old remainder is the next gcd to try.\n                    remainder,\n                    // Compute the next remainder.\n                    // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\n                    // where gcd is at most n (capped to type(uint256).max)\n                    gcd - remainder * quotient\n                );\n\n                (x, y) = (\n                    // Increment the coefficient of a.\n                    y,\n                    // Decrement the coefficient of n.\n                    // Can overflow, but the result is casted to uint256 so that the\n                    // next value of y is \"wrapped around\" to a value between 0 and n - 1.\n                    x - y * int256(quotient)\n                );\n            }\n\n            if (gcd != 1) return 0; // No inverse exists.\n            return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\n        }\n    }\n\n    /**\n     * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\n     *\n     * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\n     * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that\n     * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\n     *\n     * NOTE: this function does NOT check that `p` is a prime greater than `2`.\n     */\n    function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\n        unchecked {\n            return Math.modExp(a, p - 2, p);\n        }\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\n     *\n     * Requirements:\n     * - modulus can't be zero\n     * - underlying staticcall to precompile must succeed\n     *\n     * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\n     * sure the chain you're using it on supports the precompiled contract for modular exponentiation\n     * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\n     * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\n     * interpreted as 0.\n     */\n    function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\n        (bool success, uint256 result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\n     * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\n     * to operate modulo 0 or if the underlying precompile reverted.\n     *\n     * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\n     * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\n     * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\n     * of a revert, but the result may be incorrectly interpreted as 0.\n     */\n    function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\n        if (m == 0) return (false, 0);\n        assembly (\"memory-safe\") {\n            let ptr := mload(0x40)\n            // | Offset    | Content    | Content (Hex)                                                      |\n            // |-----------|------------|--------------------------------------------------------------------|\n            // | 0x00:0x1f | size of b  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x20:0x3f | size of e  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x40:0x5f | size of m  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x60:0x7f | value of b | 0x<.............................................................b> |\n            // | 0x80:0x9f | value of e | 0x<.............................................................e> |\n            // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\n            mstore(ptr, 0x20)\n            mstore(add(ptr, 0x20), 0x20)\n            mstore(add(ptr, 0x40), 0x20)\n            mstore(add(ptr, 0x60), b)\n            mstore(add(ptr, 0x80), e)\n            mstore(add(ptr, 0xa0), m)\n\n            // Given the result < m, it's guaranteed to fit in 32 bytes,\n            // so we can use the memory scratch space located at offset 0.\n            success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\n            result := mload(0x00)\n        }\n    }\n\n    /**\n     * @dev Variant of {modExp} that supports inputs of arbitrary length.\n     */\n    function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\n        (bool success, bytes memory result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\n     */\n    function tryModExp(\n        bytes memory b,\n        bytes memory e,\n        bytes memory m\n    ) internal view returns (bool success, bytes memory result) {\n        if (_zeroBytes(m)) return (false, new bytes(0));\n\n        uint256 mLen = m.length;\n\n        // Encode call args in result and move the free memory pointer\n        result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\n\n        assembly (\"memory-safe\") {\n            let dataPtr := add(result, 0x20)\n            // Write result on top of args to avoid allocating extra memory.\n            success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\n            // Overwrite the length.\n            // result.length > returndatasize() is guaranteed because returndatasize() == m.length\n            mstore(result, mLen)\n            // Set the memory pointer after the returned data.\n            mstore(0x40, add(dataPtr, mLen))\n        }\n    }\n\n    /**\n     * @dev Returns whether the provided byte array is zero.\n     */\n    function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\n        for (uint256 i = 0; i < byteArray.length; ++i) {\n            if (byteArray[i] != 0) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n     * towards zero.\n     *\n     * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\n     * using integer operations.\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        unchecked {\n            // Take care of easy edge cases when a == 0 or a == 1\n            if (a <= 1) {\n                return a;\n            }\n\n            // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a\n            // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\n            // the current value as `ε_n = | x_n - sqrt(a) |`.\n            //\n            // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\n            // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is\n            // bigger than any uint256.\n            //\n            // By noticing that\n            // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`\n            // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\n            // to the msb function.\n            uint256 aa = a;\n            uint256 xn = 1;\n\n            if (aa >= (1 << 128)) {\n                aa >>= 128;\n                xn <<= 64;\n            }\n            if (aa >= (1 << 64)) {\n                aa >>= 64;\n                xn <<= 32;\n            }\n            if (aa >= (1 << 32)) {\n                aa >>= 32;\n                xn <<= 16;\n            }\n            if (aa >= (1 << 16)) {\n                aa >>= 16;\n                xn <<= 8;\n            }\n            if (aa >= (1 << 8)) {\n                aa >>= 8;\n                xn <<= 4;\n            }\n            if (aa >= (1 << 4)) {\n                aa >>= 4;\n                xn <<= 2;\n            }\n            if (aa >= (1 << 2)) {\n                xn <<= 1;\n            }\n\n            // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).\n            //\n            // We can refine our estimation by noticing that the middle of that interval minimizes the error.\n            // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).\n            // This is going to be our x_0 (and ε_0)\n            xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)\n\n            // From here, Newton's method give us:\n            // x_{n+1} = (x_n + a / x_n) / 2\n            //\n            // One should note that:\n            // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a\n            //              = ((x_n² + a) / (2 * x_n))² - a\n            //              = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a\n            //              = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)\n            //              = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)\n            //              = (x_n² - a)² / (2 * x_n)²\n            //              = ((x_n² - a) / (2 * x_n))²\n            //              ≥ 0\n            // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n\n            //\n            // This gives us the proof of quadratic convergence of the sequence:\n            // ε_{n+1} = | x_{n+1} - sqrt(a) |\n            //         = | (x_n + a / x_n) / 2 - sqrt(a) |\n            //         = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |\n            //         = | (x_n - sqrt(a))² / (2 * x_n) |\n            //         = | ε_n² / (2 * x_n) |\n            //         = ε_n² / | (2 * x_n) |\n            //\n            // For the first iteration, we have a special case where x_0 is known:\n            // ε_1 = ε_0² / | (2 * x_0) |\n            //     ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))\n            //     ≤ 2**(2*e-4) / (3 * 2**(e-1))\n            //     ≤ 2**(e-3) / 3\n            //     ≤ 2**(e-3-log2(3))\n            //     ≤ 2**(e-4.5)\n            //\n            // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:\n            // ε_{n+1} = ε_n² / | (2 * x_n) |\n            //         ≤ (2**(e-k))² / (2 * 2**(e-1))\n            //         ≤ 2**(2*e-2*k) / 2**e\n            //         ≤ 2**(e-2*k)\n            xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5)  -- special case, see above\n            xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9)    -- general case with k = 4.5\n            xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18)   -- general case with k = 9\n            xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36)   -- general case with k = 18\n            xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72)   -- general case with k = 36\n            xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144)  -- general case with k = 72\n\n            // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision\n            // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\n            // sqrt(a) or sqrt(a) + 1.\n            return xn - SafeCast.toUint(xn > a / xn);\n        }\n    }\n\n    /**\n     * @dev Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 x) internal pure returns (uint256 r) {\n        // If value has upper 128 bits set, log2 result is at least 128\n        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n        // If upper 64 bits of 128-bit half set, add 64 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n        // If upper 32 bits of 64-bit half set, add 32 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n        // If upper 16 bits of 32-bit half set, add 16 to result\n        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n        // If upper 8 bits of 16-bit half set, add 8 to result\n        r |= SafeCast.toUint((x >> r) > 0xff) << 3;\n        // If upper 4 bits of 8-bit half set, add 4 to result\n        r |= SafeCast.toUint((x >> r) > 0xf) << 2;\n\n        // Shifts value right by the current result and use it as an index into this lookup table:\n        //\n        // | x (4 bits) |  index  | table[index] = MSB position |\n        // |------------|---------|-----------------------------|\n        // |    0000    |    0    |        table[0] = 0         |\n        // |    0001    |    1    |        table[1] = 0         |\n        // |    0010    |    2    |        table[2] = 1         |\n        // |    0011    |    3    |        table[3] = 1         |\n        // |    0100    |    4    |        table[4] = 2         |\n        // |    0101    |    5    |        table[5] = 2         |\n        // |    0110    |    6    |        table[6] = 2         |\n        // |    0111    |    7    |        table[7] = 2         |\n        // |    1000    |    8    |        table[8] = 3         |\n        // |    1001    |    9    |        table[9] = 3         |\n        // |    1010    |   10    |        table[10] = 3        |\n        // |    1011    |   11    |        table[11] = 3        |\n        // |    1100    |   12    |        table[12] = 3        |\n        // |    1101    |   13    |        table[13] = 3        |\n        // |    1110    |   14    |        table[14] = 3        |\n        // |    1111    |   15    |        table[15] = 3        |\n        //\n        // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\n        assembly (\"memory-safe\") {\n            r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 x) internal pure returns (uint256 r) {\n        // If value has upper 128 bits set, log2 result is at least 128\n        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n        // If upper 64 bits of 128-bit half set, add 64 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n        // If upper 32 bits of 64-bit half set, add 32 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n        // If upper 16 bits of 32-bit half set, add 16 to result\n        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n        // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\n        return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n}\n"},{"file_path":"npm/@openzeppelin/contracts@5.4.0/utils/StorageSlot.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC-1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n *     function _getImplementation() internal view returns (address) {\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n *     }\n *\n *     function _setImplementation(address newImplementation) internal {\n *         require(newImplementation.code.length > 0);\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary StorageSlot {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct BooleanSlot {\n        bool value;\n    }\n\n    struct Bytes32Slot {\n        bytes32 value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    struct Int256Slot {\n        int256 value;\n    }\n\n    struct StringSlot {\n        string value;\n    }\n\n    struct BytesSlot {\n        bytes value;\n    }\n\n    /**\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n     */\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `Int256Slot` with member `value` located at `slot`.\n     */\n    function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns a `StringSlot` with member `value` located at `slot`.\n     */\n    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n     */\n    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n\n    /**\n     * @dev Returns a `BytesSlot` with member `value` located at `slot`.\n     */\n    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n     */\n    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n        assembly (\"memory-safe\") {\n            r.slot := store.slot\n        }\n    }\n}\n"},{"file_path":"npm/@openzeppelin/contracts@5.4.0/utils/math/SafeCast.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeCast {\n    /**\n     * @dev Value doesn't fit in an uint of `bits` size.\n     */\n    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\n\n    /**\n     * @dev An int value doesn't fit in an uint of `bits` size.\n     */\n    error SafeCastOverflowedIntToUint(int256 value);\n\n    /**\n     * @dev Value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\n\n    /**\n     * @dev An uint value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedUintToInt(uint256 value);\n\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        if (value > type(uint248).max) {\n            revert SafeCastOverflowedUintDowncast(248, value);\n        }\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        if (value > type(uint240).max) {\n            revert SafeCastOverflowedUintDowncast(240, value);\n        }\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        if (value > type(uint232).max) {\n            revert SafeCastOverflowedUintDowncast(232, value);\n        }\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        if (value > type(uint224).max) {\n            revert SafeCastOverflowedUintDowncast(224, value);\n        }\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        if (value > type(uint216).max) {\n            revert SafeCastOverflowedUintDowncast(216, value);\n        }\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        if (value > type(uint208).max) {\n            revert SafeCastOverflowedUintDowncast(208, value);\n        }\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        if (value > type(uint200).max) {\n            revert SafeCastOverflowedUintDowncast(200, value);\n        }\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        if (value > type(uint192).max) {\n            revert SafeCastOverflowedUintDowncast(192, value);\n        }\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        if (value > type(uint184).max) {\n            revert SafeCastOverflowedUintDowncast(184, value);\n        }\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        if (value > type(uint176).max) {\n            revert SafeCastOverflowedUintDowncast(176, value);\n        }\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        if (value > type(uint168).max) {\n            revert SafeCastOverflowedUintDowncast(168, value);\n        }\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        if (value > type(uint160).max) {\n            revert SafeCastOverflowedUintDowncast(160, value);\n        }\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        if (value > type(uint152).max) {\n            revert SafeCastOverflowedUintDowncast(152, value);\n        }\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        if (value > type(uint144).max) {\n            revert SafeCastOverflowedUintDowncast(144, value);\n        }\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        if (value > type(uint136).max) {\n            revert SafeCastOverflowedUintDowncast(136, value);\n        }\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        if (value > type(uint128).max) {\n            revert SafeCastOverflowedUintDowncast(128, value);\n        }\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        if (value > type(uint120).max) {\n            revert SafeCastOverflowedUintDowncast(120, value);\n        }\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        if (value > type(uint112).max) {\n            revert SafeCastOverflowedUintDowncast(112, value);\n        }\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        if (value > type(uint104).max) {\n            revert SafeCastOverflowedUintDowncast(104, value);\n        }\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        if (value > type(uint96).max) {\n            revert SafeCastOverflowedUintDowncast(96, value);\n        }\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        if (value > type(uint88).max) {\n            revert SafeCastOverflowedUintDowncast(88, value);\n        }\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        if (value > type(uint80).max) {\n            revert SafeCastOverflowedUintDowncast(80, value);\n        }\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        if (value > type(uint72).max) {\n            revert SafeCastOverflowedUintDowncast(72, value);\n        }\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        if (value > type(uint64).max) {\n            revert SafeCastOverflowedUintDowncast(64, value);\n        }\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        if (value > type(uint56).max) {\n            revert SafeCastOverflowedUintDowncast(56, value);\n        }\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        if (value > type(uint48).max) {\n            revert SafeCastOverflowedUintDowncast(48, value);\n        }\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        if (value > type(uint40).max) {\n            revert SafeCastOverflowedUintDowncast(40, value);\n        }\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        if (value > type(uint32).max) {\n            revert SafeCastOverflowedUintDowncast(32, value);\n        }\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        if (value > type(uint24).max) {\n            revert SafeCastOverflowedUintDowncast(24, value);\n        }\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        if (value > type(uint16).max) {\n            revert SafeCastOverflowedUintDowncast(16, value);\n        }\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        if (value > type(uint8).max) {\n            revert SafeCastOverflowedUintDowncast(8, value);\n        }\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        if (value < 0) {\n            revert SafeCastOverflowedIntToUint(value);\n        }\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(248, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(240, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(232, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(224, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(216, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(208, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(200, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(192, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(184, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(176, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(168, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(160, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(152, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(144, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(136, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(128, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(120, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(112, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(104, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(96, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(88, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(80, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(72, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(64, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(56, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(48, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(40, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(32, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(24, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(16, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(8, value);\n        }\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        if (value > uint256(type(int256).max)) {\n            revert SafeCastOverflowedUintToInt(value);\n        }\n        return int256(value);\n    }\n\n    /**\n     * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\n     */\n    function toUint(bool b) internal pure returns (uint256 u) {\n        assembly (\"memory-safe\") {\n            u := iszero(iszero(b))\n        }\n    }\n}\n"},{"file_path":"project/contracts/interfaces/IFxUSDRegeneracy.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IFxUSDRegeneracy {\n  /**********\n   * Events *\n   **********/\n  \n  /// @notice Emitted when rebalance/liquidate with stable token.\n  /// @param amountStable The amount of stable token used.\n  /// @param amountFxUSD The corresponding amount of fxUSD.\n  event RebalanceWithStable(uint256 amountStable, uint256 amountFxUSD);\n  \n  /// @notice Emitted when buyback fxUSD with stable reserve.\n  /// @param amountStable the amount of stable token used.\n  /// @param amountFxUSD The amount of fxUSD bought.\n  /// @param bonusFxUSD The amount of fxUSD as bonus for caller.\n  event Buyback(uint256 amountStable, uint256 amountFxUSD, uint256 bonusFxUSD);\n\n  /*************************\n   * Public View Functions *\n   *************************/\n\n  /// @notice The address of `PoolManager` contract.\n  function poolManager() external view returns (address);\n\n  /// @notice The address of stable token.\n  function stableToken() external view returns (address);\n\n  /// @notice The address of `PegKeeper` contract.\n  function pegKeeper() external view returns (address);\n\n  /****************************\n   * Public Mutated Functions *\n   ****************************/\n\n  /// @notice Mint fxUSD token someone.\n  function mint(address to, uint256 amount) external;\n\n  /// @notice Burn fxUSD from someone.\n  function burn(address from, uint256 amount) external;\n\n  /// @notice Hook for rebalance/liquidate with stable token.\n  /// @param amountStableToken The amount of stable token.\n  /// @param amountFxUSD The amount of fxUSD.\n  function onRebalanceWithStable(uint256 amountStableToken, uint256 amountFxUSD) external;\n\n  /// @notice Buyback fxUSD with stable token.\n  /// @param amountIn the amount of stable token to use.\n  /// @param receiver The address of bonus receiver.\n  /// @param data The hook data to PegKeeper.\n  /// @return amountOut The amount of fxUSD swapped.\n  /// @return bonusOut The amount of bonus fxUSD.\n  function buyback(\n    uint256 amountIn,\n    address receiver,\n    bytes calldata data\n  ) external returns (uint256 amountOut, uint256 bonusOut);\n}\n"},{"file_path":"npm/@openzeppelin/contracts@5.4.0/token/ERC20/extensions/IERC20Metadata.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"},{"file_path":"project/contracts/interfaces/IReservePool.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\ninterface IReservePool {\n  /// @notice Emitted when the market request bonus.\n  /// @param token The address of the token requested.\n  /// @param receiver The address of token receiver.\n  /// @param bonus The amount of bonus token.\n  event RequestBonus(address indexed token, address indexed receiver, uint256 bonus);\n\n  /*************************\n   * Public View Functions *\n   *************************/\n\n  /// @notice Return the balance of token in this contract.\n  function getBalance(address token) external view returns (uint256);\n\n  /****************************\n   * Public Mutated Functions *\n   ****************************/\n\n  /// @notice Request bonus token from Reserve Pool.\n  /// @param token The address of token to request.\n  /// @param receiver The address recipient for the bonus token.\n  /// @param bonus The amount of bonus token to send.\n  function requestBonus(address token, address receiver, uint256 bonus) external;\n\n  /// @notice Withdraw dust assets in this contract.\n  /// @param token The address of token to withdraw.\n  /// @param amount The amount of token to withdraw.\n  /// @param recipient The address of token receiver.\n  function withdrawFund(address token, uint256 amount, address recipient) external;\n}\n"},{"file_path":"npm/@openzeppelin/contracts@5.4.0/interfaces/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)\n\npragma solidity >=0.4.16;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\n"},{"file_path":"npm/@openzeppelin/contracts@5.4.0/access/IAccessControl.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/IAccessControl.sol)\n\npragma solidity >=0.8.4;\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n    /**\n     * @dev The `account` is missing a role.\n     */\n    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n    /**\n     * @dev The caller of a function is not the expected one.\n     *\n     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n     */\n    error AccessControlBadConfirmation();\n\n    /**\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n     *\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n     * {RoleAdminChanged} not being emitted to signal this.\n     */\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n    /**\n     * @dev Emitted when `account` is granted `role`.\n     *\n     * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).\n     * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.\n     */\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Emitted when `account` is revoked `role`.\n     *\n     * `sender` is the account that originated the contract call:\n     *   - if using `revokeRole`, it is the admin role bearer\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\n     */\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) external view returns (bool);\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `callerConfirmation`.\n     */\n    function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"_fxUSD","type":"address"},{"internalType":"address","name":"_fxBASE","type":"address"},{"internalType":"address","name":"_counterparty","type":"address"},{"internalType":"address","name":"_configuration","type":"address"},{"internalType":"address","name":"_whitelist","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ErrorBorrowExceedCapacity","type":"error"},{"inputs":[],"name":"ErrorCallerNotCounterparty","type":"error"},{"inputs":[],"name":"ErrorCallerNotFxUSDSave","type":"error"},{"inputs":[],"name":"ErrorCollateralExceedCapacity","type":"error"},{"inputs":[],"name":"ErrorDebtExceedCapacity","type":"error"},{"inputs":[],"name":"ErrorInsufficientRedeemedCollateral","type":"error"},{"inputs":[],"name":"ErrorInvalidLongShortPair","type":"error"},{"inputs":[],"name":"ErrorInvalidOperation","type":"error"},{"inputs":[],"name":"ErrorInvalidPool","type":"error"},{"inputs":[],"name":"ErrorLiquidateDebtsTooSmall","type":"error"},{"inputs":[],"name":"ErrorPoolNotRegistered","type":"error"},{"inputs":[],"name":"ErrorRebalanceDebtsTooSmall","type":"error"},{"inputs":[],"name":"ErrorRedeemDebtsTooSmall","type":"error"},{"inputs":[],"name":"ErrorRedeemExceedBalance","type":"error"},{"inputs":[],"name":"ErrorRedeemNotAllowed","type":"error"},{"inputs":[],"name":"ErrorStableRepayNotAllowed","type":"error"},{"inputs":[],"name":"ErrorTopLevelCall","type":"error"},{"inputs":[],"name":"ErrorValueTooLarge","type":"error"},{"inputs":[],"name":"ErrorZeroAddress","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountRewards","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountFunding","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"performanceFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"harvestBounty","type":"uint256"}],"name":"Harvest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"uint256","name":"colls","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fxUSDDebts","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stableDebts","type":"uint256"}],"name":"Liquidate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":true,"internalType":"uint256","name":"position","type":"uint256"},{"indexed":false,"internalType":"int256","name":"deltaColls","type":"int256"},{"indexed":false,"internalType":"int256","name":"deltaDebts","type":"int256"},{"indexed":false,"internalType":"uint256","name":"protocolFees","type":"uint256"}],"name":"Operate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"uint256","name":"colls","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fxUSDDebts","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stableDebts","type":"uint256"}],"name":"Rebalance","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":true,"internalType":"int16","name":"tick","type":"int16"},{"indexed":false,"internalType":"uint256","name":"colls","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fxUSDDebts","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stableDebts","type":"uint256"}],"name":"RebalanceTick","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"uint256","name":"colls","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debts","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"protocolFees","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"uint256","name":"colls","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debts","type":"uint256"}],"name":"RedeemForSettle","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ReduceDebt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"}],"name":"RegisterPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldPool","type":"address"},{"indexed":true,"internalType":"address","name":"newPool","type":"address"}],"name":"UpdateCloseRevenuePool","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRatio","type":"uint256"}],"name":"UpdateFlashLoanFeeRatio","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRatio","type":"uint256"}],"name":"UpdateFundingExpenseRatio","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRatio","type":"uint256"}],"name":"UpdateHarvesterRatio","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRatio","type":"uint256"}],"name":"UpdateLiquidationExpenseRatio","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldPool","type":"address"},{"indexed":true,"internalType":"address","name":"newPool","type":"address"}],"name":"UpdateMiscRevenuePool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldPool","type":"address"},{"indexed":true,"internalType":"address","name":"newPool","type":"address"}],"name":"UpdateOpenRevenuePool","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldThreshold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newThreshold","type":"uint256"}],"name":"UpdatePermissionedLiquidationThreshold","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"uint256","name":"collateralCapacity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debtCapacity","type":"uint256"}],"name":"UpdatePoolCapacity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRatio","type":"uint256"}],"name":"UpdateRedeemFeeRatio","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldReservePool","type":"address"},{"indexed":true,"internalType":"address","name":"newReservePool","type":"address"}],"name":"UpdateReservePool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":true,"internalType":"address","name":"oldSplitter","type":"address"},{"indexed":true,"internalType":"address","name":"newSplitter","type":"address"}],"name":"UpdateRewardSplitter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRatio","type":"uint256"}],"name":"UpdateRewardsExpenseRatio","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"longPool","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldRatio","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRatio","type":"uint256"}],"name":"UpdateShortBorrowCapacityRatio","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"scalar","type":"uint256"},{"indexed":false,"internalType":"address","name":"provider","type":"address"}],"name":"UpdateTokenRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldTreasury","type":"address"},{"indexed":true,"internalType":"address","name":"newTreasury","type":"address"}],"name":"UpdateTreasury","type":"event"},{"inputs":[],"name":"ASSET_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEBT_REDUCER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMERGENCY_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HARVESTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"accumulatedPoolCloseFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"accumulatedPoolMiscFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"accumulatedPoolOpenFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"strategy","type":"address"},{"internalType":"uint96","name":"capacity","type":"uint96"}],"name":"alloc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"allocations","outputs":[{"internalType":"address","name":"strategy","type":"address"},{"internalType":"uint96","name":"capacity","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"longPool","type":"address"},{"internalType":"address","name":"shortPool","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"borrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"closeRevenuePool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"configuration","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"counterparty","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fxBASE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fxUSD","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFlashLoanFeeRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFundingExpenseRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHarvesterRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLiquidationExpenseRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"getPoolInfo","outputs":[{"internalType":"uint256","name":"collateralCapacity","type":"uint256"},{"internalType":"uint256","name":"collateralBalance","type":"uint256"},{"internalType":"uint256","name":"rawCollateral","type":"uint256"},{"internalType":"uint256","name":"debtCapacity","type":"uint256"},{"internalType":"uint256","name":"debtBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRedeemFeeRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewardsExpenseRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getTokenScalingFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"harvest","outputs":[{"internalType":"uint256","name":"amountRewards","type":"uint256"},{"internalType":"uint256","name":"amountFunding","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint256","name":"_expenseRatio","type":"uint256"},{"internalType":"uint256","name":"_harvesterRatio","type":"uint256"},{"internalType":"uint256","name":"_flashLoanFeeRatio","type":"uint256"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_revenuePool","type":"address"},{"internalType":"address","name":"_reservePool","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"kill","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"maxFxUSD","type":"uint256"},{"internalType":"uint256","name":"maxStable","type":"uint256"}],"name":"liquidate","outputs":[{"internalType":"uint256","name":"colls","type":"uint256"},{"internalType":"uint256","name":"fxUSDUsed","type":"uint256"},{"internalType":"uint256","name":"stableUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"manage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"miscRevenuePool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"openRevenuePool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"positionId","type":"uint256"},{"internalType":"int256","name":"newColl","type":"int256"},{"internalType":"int256","name":"newDebt","type":"int256"}],"name":"operate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"positionId","type":"uint256"},{"internalType":"int256","name":"newColl","type":"int256"},{"internalType":"int256","name":"newDebt","type":"int256"},{"internalType":"bool","name":"useStable","type":"bool"}],"name":"operate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"permissionedLiquidationThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"int16","name":"tick","type":"int16"},{"internalType":"uint256","name":"maxFxUSD","type":"uint256"},{"internalType":"uint256","name":"maxStable","type":"uint256"}],"name":"rebalance","outputs":[{"internalType":"uint256","name":"colls","type":"uint256"},{"internalType":"uint256","name":"fxUSDUsed","type":"uint256"},{"internalType":"uint256","name":"stableUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"maxFxUSD","type":"uint256"},{"internalType":"uint256","name":"maxStable","type":"uint256"}],"name":"rebalance","outputs":[{"internalType":"uint256","name":"colls","type":"uint256"},{"internalType":"uint256","name":"fxUSDUsed","type":"uint256"},{"internalType":"uint256","name":"stableUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"debts","type":"uint256"},{"internalType":"uint256","name":"minColls","type":"uint256"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"actualDebts","type":"uint256"},{"internalType":"uint256","name":"colls","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"debts","type":"uint256"}],"name":"redeemForSettle","outputs":[{"internalType":"uint256","name":"colls","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"reduceDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint96","name":"collateralCapacity","type":"uint96"},{"internalType":"uint96","name":"debtCapacity","type":"uint96"}],"name":"registerPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"longPool","type":"address"},{"internalType":"address","name":"shortPool","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"repay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"longPool","type":"address"},{"internalType":"address","name":"shortPool","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"repayByCreditNote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reservePool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardSplitter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"status","type":"bool"}],"name":"setPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"longPool","type":"address"},{"internalType":"address","name":"shortPool","type":"address"},{"internalType":"uint256","name":"shortfall","type":"uint256"}],"name":"settleShortPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"shortBorrowCapacityRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenRates","outputs":[{"internalType":"uint96","name":"scalar","type":"uint96"},{"internalType":"address","name":"rateProvider","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newPool","type":"address"}],"name":"updateCloseRevenuePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"newRewardsRatio","type":"uint32"},{"internalType":"uint32","name":"newFundingRatio","type":"uint32"},{"internalType":"uint32","name":"newLiquidationRatio","type":"uint32"}],"name":"updateExpenseRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"newRatio","type":"uint32"}],"name":"updateFlashLoanFeeRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"newRatio","type":"uint32"}],"name":"updateHarvesterRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newPool","type":"address"}],"name":"updateMiscRevenuePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newPool","type":"address"}],"name":"updateOpenRevenuePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint96","name":"collateralCapacity","type":"uint96"},{"internalType":"uint96","name":"debtCapacity","type":"uint96"}],"name":"updatePoolCapacity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"provider","type":"address"}],"name":"updateRateProvider","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"newRatio","type":"uint32"}],"name":"updateRedeemFeeRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newReservePool","type":"address"}],"name":"updateReservePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"longPool","type":"address"},{"internalType":"uint256","name":"newRatio","type":"uint256"}],"name":"updateShortBorrowCapacityRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newThreshold","type":"uint256"}],"name":"updateThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newTreasury","type":"address"}],"name":"updateTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"whitelist","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"pools","type":"address[]"}],"name":"withdrawAccumulatedPoolFee","outputs":[],"stateMutability":"nonpayable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"0x000000000000000000000000085780639cc2cacd35e474e71f4d000e2405d8f600000000000000000000000065c9a641afceb9c0e6034e558a319488fa0fa3be000000000000000000000000acdc0ab51178d0ae8f70c1ead7d3cf5421fdd66d00000000000000000000000016b334f2644cc00b85db1a1eff0c2c395e00c28d0000000000000000000000000000000000000000000000000000000000000000"}