PositionManagerMerklOwnable2StepWithShortcut

Description:

Multi-signature wallet contract requiring multiple confirmations for transaction execution.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "@itb/aave/contracts/aaveV3/DataTypesV3.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.10;

library DataTypesV3 {
  struct ReserveData {
    //stores the reserve configuration
    ReserveConfigurationMap configuration;
    //the liquidity index. Expressed in ray
    uint128 liquidityIndex;
    //the current supply rate. Expressed in ray
    uint128 currentLiquidityRate;
    //variable borrow index. Expressed in ray
    uint128 variableBorrowIndex;
    //the current variable borrow rate. Expressed in ray
    uint128 currentVariableBorrowRate;
    //the current stable borrow rate. Expressed in ray
    uint128 currentStableBorrowRate;
    //timestamp of last update
    uint40 lastUpdateTimestamp;
    //the id of the reserve. Represents the position in the list of the active reserves
    uint16 id;
    //aToken address
    address aTokenAddress;
    //stableDebtToken address
    address stableDebtTokenAddress;
    //variableDebtToken address
    address variableDebtTokenAddress;
    //address of the interest rate strategy
    address interestRateStrategyAddress;
    //the current treasury balance, scaled
    uint128 accruedToTreasury;
    //the outstanding unbacked aTokens minted through the bridging feature
    uint128 unbacked;
    //the outstanding debt borrowed against this asset in isolation mode
    uint128 isolationModeTotalDebt;
  }

  struct ReserveConfigurationMap {
    //bit 0-15: LTV
    //bit 16-31: Liq. threshold
    //bit 32-47: Liq. bonus
    //bit 48-55: Decimals
    //bit 56: reserve is active
    //bit 57: reserve is frozen
    //bit 58: borrowing is enabled
    //bit 59: stable rate borrowing enabled
    //bit 60: asset is paused
    //bit 61: borrowing in isolation mode is enabled
    //bit 62-63: reserved
    //bit 64-79: reserve factor
    //bit 80-115 borrow cap in whole tokens, borrowCap == 0 => no cap
    //bit 116-151 supply cap in whole tokens, supplyCap == 0 => no cap
    //bit 152-167 liquidation protocol fee
    //bit 168-175 eMode category
    //bit 176-211 unbacked mint cap in whole tokens, unbackedMintCap == 0 => minting disabled
    //bit 212-251 debt ceiling for isolation mode with (ReserveConfiguration::DEBT_CEILING_DECIMALS) decimals
    //bit 252-255 unused

    uint256 data;
  }

  struct UserConfigurationMap {
    /**
     * @dev Bitmap of the users collaterals and borrows. It is divided in pairs of bits, one pair per asset.
     * The first bit indicates if an asset is used as collateral by the user, the second whether an
     * asset is borrowed by the user.
     */
    uint256 data;
  }

  struct EModeCategory {
    // each eMode category has a custom ltv and liquidation threshold
    uint16 ltv;
    uint16 liquidationThreshold;
    uint16 liquidationBonus;
    // each eMode category may or may not have a custom oracle to override the individual assets price oracles
    address priceSource;
    string label;
  }

  enum InterestRateMode {
    NONE,
    STABLE,
    VARIABLE
  }

  struct ReserveCache {
    uint256 currScaledVariableDebt;
    uint256 nextScaledVariableDebt;
    uint256 currPrincipalStableDebt;
    uint256 currAvgStableBorrowRate;
    uint256 currTotalStableDebt;
    uint256 nextAvgStableBorrowRate;
    uint256 nextTotalStableDebt;
    uint256 currLiquidityIndex;
    uint256 nextLiquidityIndex;
    uint256 currVariableBorrowIndex;
    uint256 nextVariableBorrowIndex;
    uint256 currLiquidityRate;
    uint256 currVariableBorrowRate;
    uint256 reserveFactor;
    ReserveConfigurationMap reserveConfiguration;
    address aTokenAddress;
    address stableDebtTokenAddress;
    address variableDebtTokenAddress;
    uint40 reserveLastUpdateTimestamp;
    uint40 stableDebtLastUpdateTimestamp;
  }

  struct ExecuteLiquidationCallParams {
    uint256 reservesCount;
    uint256 debtToCover;
    address collateralAsset;
    address debtAsset;
    address user;
    bool receiveAToken;
    address priceOracle;
    uint8 userEModeCategory;
    address priceOracleSentinel;
  }

  struct ExecuteSupplyParams {
    address asset;
    uint256 amount;
    address onBehalfOf;
    uint16 referralCode;
  }

  struct ExecuteBorrowParams {
    address asset;
    address user;
    address onBehalfOf;
    uint256 amount;
    InterestRateMode interestRateMode;
    uint16 referralCode;
    bool releaseUnderlying;
    uint256 maxStableRateBorrowSizePercent;
    uint256 reservesCount;
    address oracle;
    uint8 userEModeCategory;
    address priceOracleSentinel;
  }

  struct ExecuteRepayParams {
    address asset;
    uint256 amount;
    InterestRateMode interestRateMode;
    address onBehalfOf;
    bool useATokens;
  }

  struct ExecuteWithdrawParams {
    address asset;
    uint256 amount;
    address to;
    uint256 reservesCount;
    address oracle;
    uint8 userEModeCategory;
  }

  struct ExecuteSetUserEModeParams {
    uint256 reservesCount;
    address oracle;
    uint8 categoryId;
  }

  struct FinalizeTransferParams {
    address asset;
    address from;
    address to;
    uint256 amount;
    uint256 balanceFromBefore;
    uint256 balanceToBefore;
    uint256 reservesCount;
    address oracle;
    uint8 fromEModeCategory;
  }

  struct FlashloanParams {
    address receiverAddress;
    address[] assets;
    uint256[] amounts;
    uint256[] interestRateModes;
    address onBehalfOf;
    bytes params;
    uint16 referralCode;
    uint256 flashLoanPremiumToProtocol;
    uint256 flashLoanPremiumTotal;
    uint256 maxStableRateBorrowSizePercent;
    uint256 reservesCount;
    address addressesProvider;
    uint8 userEModeCategory;
    bool isAuthorizedFlashBorrower;
  }

  struct FlashloanSimpleParams {
    address receiverAddress;
    address asset;
    uint256 amount;
    bytes params;
    uint16 referralCode;
    uint256 flashLoanPremiumToProtocol;
    uint256 flashLoanPremiumTotal;
  }

  struct FlashLoanRepaymentParams {
    uint256 amount;
    uint256 totalPremium;
    uint256 flashLoanPremiumToProtocol;
    address asset;
    address receiverAddress;
    uint16 referralCode;
  }

  struct CalculateUserAccountDataParams {
    UserConfigurationMap userConfig;
    uint256 reservesCount;
    address user;
    address oracle;
    uint8 userEModeCategory;
  }

  struct ValidateBorrowParams {
    ReserveCache reserveCache;
    UserConfigurationMap userConfig;
    address asset;
    address userAddress;
    uint256 amount;
    InterestRateMode interestRateMode;
    uint256 maxStableLoanPercent;
    uint256 reservesCount;
    address oracle;
    uint8 userEModeCategory;
    address priceOracleSentinel;
    bool isolationModeActive;
    address isolationModeCollateralAddress;
    uint256 isolationModeDebtCeiling;
  }

  struct ValidateLiquidationCallParams {
    ReserveCache debtReserveCache;
    uint256 totalDebt;
    uint256 healthFactor;
    address priceOracleSentinel;
  }

  struct CalculateInterestRatesParams {
    uint256 unbacked;
    uint256 liquidityAdded;
    uint256 liquidityTaken;
    uint256 totalStableDebt;
    uint256 totalVariableDebt;
    uint256 averageStableBorrowRate;
    uint256 reserveFactor;
    address reserve;
    address aToken;
  }

  struct InitReserveParams {
    address asset;
    address aTokenAddress;
    address stableDebtAddress;
    address variableDebtAddress;
    address interestRateStrategyAddress;
    uint16 reservesCount;
    uint16 maxNumberReserves;
  }
}"
    },
    "@itb/aave/contracts/aaveV3/IPool.sol": {
      "content": "/* SPDX-License-Identifier: UNLICENSED */
pragma solidity ^0.8.0;

import {DataTypesV3} from './DataTypesV3.sol';

struct EModeCategory {
  // each eMode category has a custom ltv and liquidation threshold
  uint16 ltv;
  uint16 liquidationThreshold;
  uint16 liquidationBonus;
  // each eMode category may or may not have a custom oracle to override the individual assets price oracles
  address priceSource;
  string label;
}

interface IPool {

  /**
   * @dev Emitted on withdraw()
   * @param reserve The address of the underlying asset being withdrawn
   * @param user The address initiating the withdrawal, owner of aTokens
   * @param to The address that will receive the underlying
   * @param amount The amount to be withdrawn
   */
  event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);

  /**
   * @dev Emitted on repay()
   * @param reserve The address of the underlying asset of the reserve
   * @param user The beneficiary of the repayment, getting his debt reduced
   * @param repayer The address of the user initiating the repay(), providing the funds
   * @param amount The amount repaid
   * @param useATokens True if the repayment is done using aTokens, `false` if done with underlying asset directly
   */
  event Repay(
    address indexed reserve,
    address indexed user,
    address indexed repayer,
    uint256 amount,
    bool useATokens
  );

  /**
   * @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the
   * equivalent debt tokens
   * - E.g. User repays 100 USDC using 100 aUSDC, burning 100 variable/stable debt tokens
   * @dev  Passing uint256.max as amount will clean up any residual aToken dust balance, if the user aToken
   * balance is not enough to cover the whole debt
   * @param asset The address of the borrowed underlying asset previously borrowed
   * @param amount The amount to repay
   * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
   * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
   * @return The final amount repaid
   **/
  function repayWithATokens(
    address asset,
    uint256 amount,
    uint256 interestRateMode
  ) external returns (uint256);

  /**
   * @notice Returns the data of an eMode category
   * @param id The id of the category
   * @return The configuration data of the category
   */
  function getEModeCategoryData(uint8 id) external view returns (EModeCategory memory);

  /**
   * @notice Allows a user to use the protocol in eMode
   * @param categoryId The id of the category
   */
  function setUserEMode(uint8 categoryId) external;

  /**
   * @notice Returns the eMode the user is using
   * @param user The address of the user
   * @return The eMode id
   */
  function getUserEMode(address user) external view returns (uint256);

  /**
   * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
   * - E.g. User supplies 100 USDC and gets in return 100 aUSDC
   * @param asset The address of the underlying asset to supply
   * @param amount The amount to be supplied
   * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
   *   wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
   *   is a different wallet
   * @param referralCode Code used to register the integrator originating the operation, for potential rewards.
   *   0 if the action is executed directly by the user, without any middle-man
   **/
  function supply(
    address asset,
    uint256 amount,
    address onBehalfOf,
    uint16 referralCode
  ) external;

  /**
   * @notice Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned
   * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC
   * @param asset The address of the underlying asset to withdraw
   * @param amount The underlying amount to be withdrawn
   *   - Send the value type(uint256).max in order to withdraw the whole aToken balance
   * @param to The address that will receive the underlying, same as msg.sender if the user
   *   wants to receive it on his own wallet, or a different address if the beneficiary is a
   *   different wallet
   * @return The final amount withdrawn
   **/
  function withdraw(
    address asset,
    uint256 amount,
    address to
  ) external returns (uint256);

  /**
   * @notice Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower
   * already supplied enough collateral, or he was given enough allowance by a credit delegator on the
   * corresponding debt token (StableDebtToken or VariableDebtToken)
   * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet
   *   and 100 stable/variable debt tokens, depending on the `interestRateMode`
   * @param asset The address of the underlying asset to borrow
   * @param amount The amount to be borrowed
   * @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable
   * @param referralCode The code used to register the integrator originating the operation, for potential rewards.
   *   0 if the action is executed directly by the user, without any middle-man
   * @param onBehalfOf The address of the user who will receive the debt. Should be the address of the borrower itself
   * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator
   * if he has been given credit delegation allowance
   **/
  function borrow(
    address asset,
    uint256 amount,
    uint256 interestRateMode,
    uint16 referralCode,
    address onBehalfOf
  ) external;

  /**
   * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned
   * - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address
   * @param asset The address of the borrowed underlying asset previously borrowed
   * @param amount The amount to repay
   * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
   * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
   * @param onBehalfOf The address of the user who will get his debt reduced/removed. Should be the address of the
   * user calling the function if he wants to reduce/remove his own debt, or the address of any other
   * other borrower whose debt should be removed
   * @return The final amount repaid
   **/
  function repay(
    address asset,
    uint256 amount,
    uint256 interestRateMode,
    address onBehalfOf
  ) external returns (uint256);

  /**
   * @notice Allows suppliers to enable/disable a specific supplied asset as collateral
   * @param asset The address of the underlying asset supplied
   * @param useAsCollateral True if the user wants to use the supply as collateral, false otherwise
   **/
  function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;

  /**
   * @notice Returns the user account data across all the reserves
   * @param user The address of the user
   * @return totalCollateralBase The total collateral of the user in the base currency used by the price feed
   * @return totalDebtBase The total debt of the user in the base currency used by the price feed
   * @return availableBorrowsBase The borrowing power left of the user in the base currency used by the price feed
   * @return currentLiquidationThreshold The liquidation threshold of the user
   * @return ltv The loan to value of The user
   * @return healthFactor The current health factor of the user
   **/
  function getUserAccountData(address user)
    external
    view
    returns (
      uint256 totalCollateralBase,
      uint256 totalDebtBase,
      uint256 availableBorrowsBase,
      uint256 currentLiquidationThreshold,
      uint256 ltv,
      uint256 healthFactor
    );
  
  /**
   * @notice Returns the state and configuration of the reserve
   * @param asset The address of the underlying asset of the reserve
   * @return The state and configuration data of the reserve
   **/
  function getReserveData(address asset) external view returns (DataTypesV3.ReserveData memory);

  /**
   * @dev Returns the configuration of the reserve
   * @param asset The address of the underlying asset of the reserve
   * @return The configuration of the reserve
   **/
  function getConfiguration(address asset) external view returns (uint);
}"
    },
    "@itb/aave/contracts/aaveV3/IProtocolDataProviderV3.sol": {
      "content": "// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;

interface IProtocolDataProviderV3 {
  function getReserveTokensAddresses(address asset) external view returns (address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress);

  function getReserveConfigurationData(address asset) external view returns (uint256 decimals, uint256 ltv, uint256 liquidationThreshold, uint256 liquidationBonus, uint256 reserveFactor, bool collateralEnabled, bool borrowingEnabled, bool stableRateBorrowingEnabled, bool isActive, bool isFrozen);

  function getReserveData(address asset) external view returns (uint256 unbacked, uint256 accruedToTreasuryScaled, uint256 totalAToken, uint256 totalStableDebt, uint256 totalVariableDebt, uint256 liquidityRate, uint256 variableBorrowRate, uint256 stableBorrowRate, uint256 averageStableBorrowRate, uint256 liquidityIndex, uint256 variableBorrowIndex, uint40 lastUpdateTimestamp);
  
  function getReserveCaps(address asset) external view returns (uint256 borrowCap, uint256 supplyCap);

  function getUserReserveData(address asset, address user) external view returns (uint256 aTokenBalance, uint256 stableDebt, uint256 variableDebt, uint256 principalStableDebt, uint256 scaledVariableDebt, uint256 stableBorrowRate, uint256 reserveLiquidityRate, uint40 stableRateLastUpdate, bool usedAsCollateral);
}"
    },
    "@itb/aave/contracts/aaveV3/IRewardsControllerV3.sol": {
      "content": "// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;

import {IRewardsDistributorV3} from './IRewardsDistributorV3.sol';

/**
 * @title IRewardsController
 * @author Aave
 * @notice Defines the basic interface for a Rewards Controller.
 */
interface IRewardsControllerV3 is IRewardsDistributorV3 {
  /**
   * @dev Emitted when a new address is whitelisted as claimer of rewards on behalf of a user
   * @param user The address of the user
   * @param claimer The address of the claimer
   */
  event ClaimerSet(address indexed user, address indexed claimer);

  /**
   * @dev Emitted when rewards are claimed
   * @param user The address of the user rewards has been claimed on behalf of
   * @param reward The address of the token reward is claimed
   * @param to The address of the receiver of the rewards
   * @param claimer The address of the claimer
   * @param amount The amount of rewards claimed
   */
  event RewardsClaimed(
    address indexed user,
    address indexed reward,
    address indexed to,
    address claimer,
    uint256 amount
  );

  /**
   * @dev Emitted when a transfer strategy is installed for the reward distribution
   * @param reward The address of the token reward
   * @param transferStrategy The address of TransferStrategy contract
   */
  event TransferStrategyInstalled(address indexed reward, address indexed transferStrategy);

  /**
   * @dev Emitted when the reward oracle is updated
   * @param reward The address of the token reward
   * @param rewardOracle The address of oracle
   */
  event RewardOracleUpdated(address indexed reward, address indexed rewardOracle);

  /**
   * @dev Whitelists an address to claim the rewards on behalf of another address
   * @param user The address of the user
   * @param claimer The address of the claimer
   */
  function setClaimer(address user, address claimer) external;

  /**
   * @dev Get the price aggregator oracle address
   * @param reward The address of the reward
   * @return The price oracle of the reward
   */
  function getRewardOracle(address reward) external view returns (address);

  /**
   * @dev Returns the whitelisted claimer for a certain address (0x0 if not set)
   * @param user The address of the user
   * @return The claimer address
   */
  function getClaimer(address user) external view returns (address);

  /**
   * @dev Returns the Transfer Strategy implementation contract address being used for a reward address
   * @param reward The address of the reward
   * @return The address of the TransferStrategy contract
   */
  function getTransferStrategy(address reward) external view returns (address);

  /**
   * @dev Called by the corresponding asset on any update that affects the rewards distribution
   * @param user The address of the user
   * @param userBalance The user balance of the asset
   * @param totalSupply The total supply of the asset
   **/
  function handleAction(
    address user,
    uint256 userBalance,
    uint256 totalSupply
  ) external;

  /**
   * @dev Claims reward for a user to the desired address, on all the assets of the pool, accumulating the pending rewards
   * @param assets List of assets to check eligible distributions before claiming rewards
   * @param amount The amount of rewards to claim
   * @param to The address that will be receiving the rewards
   * @param reward The address of the reward token
   * @return The amount of rewards claimed
   **/
  function claimRewards(
    address[] calldata assets,
    uint256 amount,
    address to,
    address reward
  ) external returns (uint256);

  /**
   * @dev Claims reward for a user on behalf, on all the assets of the pool, accumulating the pending rewards. The
   * caller must be whitelisted via "allowClaimOnBehalf" function by the RewardsAdmin role manager
   * @param assets The list of assets to check eligible distributions before claiming rewards
   * @param amount The amount of rewards to claim
   * @param user The address to check and claim rewards
   * @param to The address that will be receiving the rewards
   * @param reward The address of the reward token
   * @return The amount of rewards claimed
   **/
  function claimRewardsOnBehalf(
    address[] calldata assets,
    uint256 amount,
    address user,
    address to,
    address reward
  ) external returns (uint256);

  /**
   * @dev Claims reward for msg.sender, on all the assets of the pool, accumulating the pending rewards
   * @param assets The list of assets to check eligible distributions before claiming rewards
   * @param amount The amount of rewards to claim
   * @param reward The address of the reward token
   * @return The amount of rewards claimed
   **/
  function claimRewardsToSelf(
    address[] calldata assets,
    uint256 amount,
    address reward
  ) external returns (uint256);

  /**
   * @dev Claims all rewards for a user to the desired address, on all the assets of the pool, accumulating the pending rewards
   * @param assets The list of assets to check eligible distributions before claiming rewards
   * @param to The address that will be receiving the rewards
   * @return rewardsList List of addresses of the reward tokens
   * @return claimedAmounts List that contains the claimed amount per reward, following same order as "rewardList"
   **/
  function claimAllRewards(address[] calldata assets, address to)
    external
    returns (address[] memory rewardsList, uint256[] memory claimedAmounts);

  /**
   * @dev Claims all rewards for a user on behalf, on all the assets of the pool, accumulating the pending rewards. The caller must
   * be whitelisted via "allowClaimOnBehalf" function by the RewardsAdmin role manager
   * @param assets The list of assets to check eligible distributions before claiming rewards
   * @param user The address to check and claim rewards
   * @param to The address that will be receiving the rewards
   * @return rewardsList List of addresses of the reward tokens
   * @return claimedAmounts List that contains the claimed amount per reward, following same order as "rewardsList"
   **/
  function claimAllRewardsOnBehalf(
    address[] calldata assets,
    address user,
    address to
  ) external returns (address[] memory rewardsList, uint256[] memory claimedAmounts);

  /**
   * @dev Claims all reward for msg.sender, on all the assets of the pool, accumulating the pending rewards
   * @param assets The list of assets to check eligible distributions before claiming rewards
   * @return rewardsList List of addresses of the reward tokens
   * @return claimedAmounts List that contains the claimed amount per reward, following same order as "rewardsList"
   **/
  function claimAllRewardsToSelf(address[] calldata assets)
    external
    returns (address[] memory rewardsList, uint256[] memory claimedAmounts);
}
"
    },
    "@itb/aave/contracts/aaveV3/IRewardsDistributorV3.sol": {
      "content": "// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;

/**
 * @title IRewardsDistributor
 * @author Aave
 * @notice Defines the basic interface for a Rewards Distributor.
 */
interface IRewardsDistributorV3 {
  /**
   * @dev Emitted when the configuration of the rewards of an asset is updated.
   * @param asset The address of the incentivized asset
   * @param reward The address of the reward token
   * @param oldEmission The old emissions per second value of the reward distribution
   * @param newEmission The new emissions per second value of the reward distribution
   * @param oldDistributionEnd The old end timestamp of the reward distribution
   * @param newDistributionEnd The new end timestamp of the reward distribution
   * @param assetIndex The index of the asset distribution
   */
  event AssetConfigUpdated(
    address indexed asset,
    address indexed reward,
    uint256 oldEmission,
    uint256 newEmission,
    uint256 oldDistributionEnd,
    uint256 newDistributionEnd,
    uint256 assetIndex
  );

  /**
   * @dev Emitted when rewards of an asset are accrued on behalf of a user.
   * @param asset The address of the incentivized asset
   * @param reward The address of the reward token
   * @param user The address of the user that rewards are accrued on behalf of
   * @param assetIndex The index of the asset distribution
   * @param userIndex The index of the asset distribution on behalf of the user
   * @param rewardsAccrued The amount of rewards accrued
   */
  event Accrued(
    address indexed asset,
    address indexed reward,
    address indexed user,
    uint256 assetIndex,
    uint256 userIndex,
    uint256 rewardsAccrued
  );

  /**
   * @dev Emitted when the emission manager address is updated.
   * @param oldEmissionManager The address of the old emission manager
   * @param newEmissionManager The address of the new emission manager
   */
  event EmissionManagerUpdated(
    address indexed oldEmissionManager,
    address indexed newEmissionManager
  );

  /**
   * @dev Sets the end date for the distribution
   * @param asset The asset to incentivize
   * @param reward The reward token that incentives the asset
   * @param newDistributionEnd The end date of the incentivization, in unix time format
   **/
  function setDistributionEnd(
    address asset,
    address reward,
    uint32 newDistributionEnd
  ) external;

  /**
   * @dev Sets the emission per second of a set of reward distributions
   * @param asset The asset is being incentivized
   * @param rewards List of reward addresses are being distributed
   * @param newEmissionsPerSecond List of new reward emissions per second
   */
  function setEmissionPerSecond(
    address asset,
    address[] calldata rewards,
    uint88[] calldata newEmissionsPerSecond
  ) external;

  /**
   * @dev Gets the end date for the distribution
   * @param asset The incentivized asset
   * @param reward The reward token of the incentivized asset
   * @return The timestamp with the end of the distribution, in unix time format
   **/
  function getDistributionEnd(address asset, address reward) external view returns (uint256);

  /**
   * @dev Returns the index of a user on a reward distribution
   * @param user Address of the user
   * @param asset The incentivized asset
   * @param reward The reward token of the incentivized asset
   * @return The current user asset index, not including new distributions
   **/
  function getUserAssetIndex(
    address user,
    address asset,
    address reward
  ) external view returns (uint256);

  /**
   * @dev Returns the configuration of the distribution reward for a certain asset
   * @param asset The incentivized asset
   * @param reward The reward token of the incentivized asset
   * @return The index of the asset distribution
   * @return The emission per second of the reward distribution
   * @return The timestamp of the last update of the index
   * @return The timestamp of the distribution end
   **/
  function getRewardsData(address asset, address reward)
    external
    view
    returns (
      uint256,
      uint256,
      uint256,
      uint256
    );

  /**
   * @dev Returns the list of available reward token addresses of an incentivized asset
   * @param asset The incentivized asset
   * @return List of rewards addresses of the input asset
   **/
  function getRewardsByAsset(address asset) external view returns (address[] memory);

  /**
   * @dev Returns the list of available reward addresses
   * @return List of rewards supported in this contract
   **/
  function getRewardsList() external view returns (address[] memory);

  /**
   * @dev Returns the accrued rewards balance of a user, not including virtually accrued rewards since last distribution.
   * @param user The address of the user
   * @param reward The address of the reward token
   * @return Unclaimed rewards, not including new distributions
   **/
  function getUserAccruedRewards(address user, address reward) external view returns (uint256);

  /**
   * @dev Returns a single rewards balance of a user, including virtually accrued and unrealized claimable rewards.
   * @param assets List of incentivized assets to check eligible distributions
   * @param user The address of the user
   * @param reward The address of the reward token
   * @return The rewards amount
   **/
  function getUserRewards(
    address[] calldata assets,
    address user,
    address reward
  ) external view returns (uint256);

  /**
   * @dev Returns a list all rewards of a user, including already accrued and unrealized claimable rewards
   * @param assets List of incentivized assets to check eligible distributions
   * @param user The address of the user
   * @return The list of reward addresses
   * @return The list of unclaimed amount of rewards
   **/
  function getAllUserRewards(address[] calldata assets, address user)
    external
    view
    returns (address[] memory, uint256[] memory);

  /**
   * @dev Returns the decimals of an asset to calculate the distribution delta
   * @param asset The address to retrieve decimals
   * @return The decimals of an underlying asset
   */
  function getAssetDecimals(address asset) external view returns (uint8);

  /**
   * @dev Returns the address of the emission manager
   * @return The address of the EmissionManager
   */
  function getEmissionManager() external view returns (address);

  /**
   * @dev Updates the address of the emission manager
   * @param emissionManager The address of the new EmissionManager
   */
  function setEmissionManager(address emissionManager) external;
}
"
    },
    "@itb/aave/contracts/BasePositionManager.sol": {
      "content": "/* SPDX-License-Identifier: UNLICENSED */
pragma solidity ^0.8.0;

import '@openzeppelin/contracts/utils/math/Math.sol';
import '@itb/quant-common/contracts/solidity8/ITBContract.sol';
import './aaveV3/IRewardsControllerV3.sol';
import './aaveV3/IPool.sol';
import './aaveV3/IProtocolDataProviderV3.sol';

/// @title BasePositionManager that implements common functions accross different Aave markets and defaults to Aave V2
/// @author IntoTheBlock Corp
/// @dev Abstract
contract BasePositionManager is ITBContract {
    IRewardsControllerV3 public rewards_controller;
    IPool public lending_pool;
    IProtocolDataProviderV3 public protocol_data_provider;

    event Deposit(address indexed token, uint amount);
    event Withdraw(address indexed token, uint amount);
    event Borrow(address indexed token, uint amount);
    event Repay(address indexed token, uint amount);
    event UpdateLendingPool(IPool old_pool, IPool new_pool);
    event UpdateRewardsController(IRewardsControllerV3 old_controller, IRewardsControllerV3 new_controller);
    event UpdateProtocolDataProvider(IProtocolDataProviderV3 old_provider, IProtocolDataProviderV3 new_provider);
    event ClaimRewards(address reward, uint amount);

    /// @param _executors Executor addresses
    /// @param _wnative Wrapped native token address
    /// @param _lending_pool Aave V3 Pool address
    /// @param _rewards_controller Aave V3 RewardsController address
    /// @param _protocol_data_provider Aave V3 ProtocolDataProvider address
    constructor(address[] memory _executors, address payable _wnative, IPool _lending_pool, IRewardsControllerV3 _rewards_controller, IProtocolDataProviderV3 _protocol_data_provider) ITBContract(_executors, _wnative) {
        updateLendingPool(_lending_pool);
        updateRewardsController(_rewards_controller);
        updateProtocolDataProvider(_protocol_data_provider);
    }

    modifier hasRewardsController() {
        require(address(rewards_controller) != address(0), 'C1'); // RewardsController not set
        _;
    }

    /* Helpers */

    /// @notice Atoken addresses for a given market
    /// @param _token Underlying market
    /// @return Atoken address
    /// @return Stable debt address
    /// @return Variable debt address
    function _getAaveTokens(address _token) internal view returns (address, address, address) {
        return protocol_data_provider.getReserveTokensAddresses(_token); /* aToken, stableDebtToken, variableDebtToken */
    }

    /// @notice Get the LTV of a given market taking into account current EMode category
    /// @return LTV scaled to 1e18 
    function _getLTV(address _token) internal view returns (uint) {
        uint current_emode_category = lending_pool.getUserEMode(address(this));
        uint ltv_1e4;
        if (current_emode_category == 0) {
            uint mask = lending_pool.getConfiguration(_token);
            ltv_1e4 = mask % 2**16;
        }
        else
            ltv_1e4 = lending_pool.getEModeCategoryData(uint8(current_emode_category)).ltv;
        return ltv_1e4 * 1e18 / 1e4;
    }

    /// @notice Supply tokens to a given market
    /// @param _token Underlying market
    /// @param _amount Amount to supply
    function _deposit(address _token, uint _amount) internal {
        _checkAllowanceAndApprove(_token, address(lending_pool), _amount);
        lending_pool.supply(_token, _amount, address(this), 0);
        emit Deposit(_token, _amount);
    }

    /// @notice Withdraw supplied tokens from a given market
    /// @param _token Underlying market
    /// @param _amount Amount to withdraw
    function _withdrawSupply(address _token, uint256 _amount) internal {
        lending_pool.withdraw(_token, _amount, address(this));
        emit Withdraw(_token, _amount);
    }

    /// @notice Borrow tokens from a given market
    /// @param _token Underlying market
    /// @param _amount Amount to borrow
    function _borrow(address _token, uint _amount) internal {
        lending_pool.borrow(_token, _amount, 2, 0, address(this));
        emit Borrow(_token, _amount);
    }

    /// @notice Repay debt for a given market
    /// @param _token Underlying market
    /// @param _amount Amount to repay
    function _repay(address _token, uint _amount) internal {
        _checkAllowanceAndApprove(_token, address(lending_pool), _amount);
        lending_pool.repay(_token, _amount, 2, address(this));
        emit Repay(_token, _amount);
    }

    /// @notice Repay all debt for a given market
    /// @param _token Underlying market
    function _repayAll(address _token) internal {
        _repay(_token, type(uint).max);
    }

    /* Infra */

    /// @notice Only owner. Update LendingPool address
    /// @param _address New address
    function updateLendingPool(IPool _address) public onlyOwner {
        emit UpdateLendingPool(lending_pool, _address);
        lending_pool = _address;        
    }

    /// @notice Only owner. Update RewardsController address
    /// @param _address New address
    function updateRewardsController(IRewardsControllerV3 _address) public onlyOwner {
        emit UpdateRewardsController(rewards_controller, _address);
        rewards_controller = _address;        
    }

    /// @notice Only owner. Update ProtocolDataProvider address
    /// @param _address New address
    function updateProtocolDataProvider(IProtocolDataProviderV3 _address) public onlyOwner {
        emit UpdateProtocolDataProvider(protocol_data_provider, _address);
        protocol_data_provider = _address;
    }

    /* Primitives */


}"
    },
    "@itb/aave/contracts/merkl/IMerkleDistributor.sol": {
      "content": "/* SPDX-License-Identifier: UNLICENSED */
pragma solidity ^0.8.0;

interface IMerkleDistributor {
    event Claimed(address indexed user, address indexed token, uint256 amount);

    function claim(address[] calldata users, address[] calldata tokens, uint256[] calldata amounts, bytes32[][] calldata proofs) external;

    function claimed(address user, address token) external view returns (uint208 amount, uint48 timestamp, bytes32 merkleRoot);

    function toggleOperator(address user, address operator) external;

    function operators(address user, address operator) external view returns (uint);
}"
    },
    "@itb/aave/contracts/single/PositionManager.sol": {
      "content": "/* SPDX-License-Identifier: UNLICENSED */
pragma solidity ^0.8.0;

import '../BasePositionManager.sol';

/// @title PositionManager that targets Aave V2 markets
/// @author IntoTheBlock Corp
/// @notice Assembles a leveraged position using the same market for supply and borrow in Aave V2
/// @dev Deprecated, Aave now uses V3 markets
contract PositionManager is BasePositionManager {
    /// @notice Mapping of underlying market to maximum leverage factor set by owner scaled by 1e18 (2x leverage: 2e18)
    mapping (address => uint) public maxLFByMarket;
    event Assemble(address token, uint amount, uint leverage_factor);
    event Disassemble(address token, uint amount, uint leverage_factor);
    event IncreaseLeverage(address token, uint amount, uint leverage_factor);
    event DecreaseLeverage(address token, uint amount, uint leverage_factor);
    event UpdatePositionConfig(PositionConfig old_config, PositionConfig new_config);
    event UpdateMaxLF(address token, uint max_lf);
    event SetEMode(uint8 category);
    event RepayWithATokens(address indexed token, uint amount);

    struct PositionConfig {
      address underlying_token;
      uint min_withdraw_step;
      uint min_borrow_step;
      uint leverage_factor_mantissa;
    }

    PositionConfig public parameters_config;

    /// @param _executors Executor addresses
    /// @param _wnative Wrapped native token address
    /// @param _tokens Array of supported underlying markets
    /// @param _max_lfs For each supported market in _tokens, maximum leverage factor set by owner scaled by 1e18
    /// @param _lending_pool Aave V3 Pool address
    /// @param _rewards_controller Aave V3 RewardsController address
    /// @param _protocol_data_provider Aave V3 ProtocolDataProvider address
    /// @param _parameters_config Configuration for assemble/disassemble without parameters
    constructor(
      address[] memory _executors, 
      address payable _wnative, 
      address[] memory _tokens, 
      uint[] memory _max_lfs, 
      IPool _lending_pool, 
      IRewardsControllerV3 _rewards_controller, 
      IProtocolDataProviderV3 _protocol_data_provider,
      PositionConfig memory _parameters_config
    ) BasePositionManager(_executors, _wnative, _lending_pool, _rewards_controller, _protocol_data_provider) {
        for (uint i = 0; i < _tokens.length; i++)
            updateMaxLF(_tokens[i], _max_lfs[i]);
        updatePositionConfig(_parameters_config);
    }

    function VERSION() external pure returns (string memory) {
        return "2.0.0";
    }

    /// @notice Only executor. Update parameters configuration.
    function updatePositionConfig(PositionConfig memory _parameters_config) public onlyExecutor {
        emit UpdatePositionConfig(parameters_config, _parameters_config);
        parameters_config = _parameters_config;
    }
    
    /* Helpers */
    
    /// @notice Get underlyings addresses
    /// @return assets all underlying assets
    function getPositionAssets() public view returns (address[] memory assets) {
        assets = new address[](1);
        assets[0] = parameters_config.underlying_token;
    }

    /// @notice Get underlyings address and amounts
    /// @return assets all underlying assets
    /// @return amounts amounts of all underlying assets
    function getUnderlyings() public view returns (address[] memory assets, uint256[] memory amounts) {
        assets = getPositionAssets();
        amounts = new uint[](1);
        (uint supplied, uint borrowed) = accountMarketSnapshot(parameters_config.underlying_token);
        amounts[0] = supplied - borrowed;
    }

    /// @notice Calculate liquidity and shortfall based on borrowing power (credit) and borrowed amount (debt)
    /// @param _borrowing_power Borrowing power
    /// @param _borrowed Borrowed amount
    /// @return Liquidity (0 if undercollateralized)
    /// @return Shortfall (0 if overcollateralized)
    function _calculateLiquidity(uint _borrowing_power, uint _borrowed) internal pure returns (uint, uint) {
        uint liquidity = _borrowing_power > _borrowed ? _borrowing_power - _borrowed : 0;
        uint shortfall = _borrowing_power < _borrowed ? _borrowed - _borrowing_power : 0;
        return (liquidity, shortfall);
    }

    /// @notice Use supply side aTokens to repay debt incurred in the same market
    /// @param _token Underlying market
    /// @param _amount Amount to repay
    function _repayWithATokens(address _token, uint _amount) internal {
        (, uint borrow_amount) = accountMarketSnapshot(_token);
        if (borrow_amount != 0)
            lending_pool.repayWithATokens(_token, _amount, 2);
        emit RepayWithATokens(_token, _amount);
    }

    /// @notice Claim rewards in a given token for a given market and amount
    /// @dev Will claim both supply and variable debt rewards
    /// @param _token Underlying market
    /// @param _amount Amount of _reward_address to claim
    /// @param _reward_address Reward token to claim
    /// @return claimed_amount claimed
    function _claim_rewards(address _token, uint _amount, address _reward_address) internal returns (uint claimed_amount) {
        address[] memory tokens = new address[](2);
        (address atoken, , address variable_debt_token) = _getAaveTokens(_token);
        tokens[0] = atoken;
        tokens[1] = variable_debt_token;
        uint bal_before = _erc20Balance(_reward_address);
        rewards_controller.claimRewards(tokens, _amount, address(this), _reward_address);
        uint bal_after = _erc20Balance(_reward_address);
        claimed_amount = bal_after - bal_before;
        emit ClaimRewards(_reward_address, claimed_amount);
    }

    /// @notice Compares after execution leverage vs max leverage factor and reverts if above max leverage factor
    modifier leverageCheck(address _token) virtual {
        _;
        (uint supplied, uint borrowed) = accountMarketSnapshot(_token);
        if (borrowed == 0)
            return;
        require(supplied >= borrowed, 'Dangerous LF');
        uint net = supplied - borrowed;
        uint max_lf_mantissa = maxLFByMarket[_token];
        require(net * max_lf_mantissa / 1e18 >= supplied, 'Dangerous LF');
    }

    /* Infra */

    /// @notice Only owner. Set maximum leverage for a given market
    /// @param _token Underlying market
    /// @param _max_lf Maximum leverage factor scaled by 1e18
    function updateMaxLF(address _token, uint _max_lf) public onlyOwner {
        maxLFByMarket[_token] = _max_lf;
        emit UpdateMaxLF(_token, _max_lf);
    }

    /// @notice Only owner. Set EMode category and update maxLFs accordingly
    /// @param _category Emode category
    /// @param _tokens Array of supported underlying markets to update
    /// @param _max_lfs For each supported market in _tokens, maximum leverage factor scaled by 1e18 (2x leverage: 2e18)
    function setEMode(uint8 _category, address[] memory _tokens, uint[] memory _max_lfs) external onlyOwner {
        lending_pool.setUserEMode(_category);
        for (uint i = 0; i < _tokens.length; i++)
            updateMaxLF(_tokens[i], _max_lfs[i]);
        emit SetEMode(_category);
    }

    /* View */

    /// @notice Atoken addresses for a given market
    /// @param _token Underlying market
    /// @return Atoken address
    /// @return Stable debt address
    /// @return Variable debt address
    function getAaveTokens(address _token) external view returns(address, address, address) {
        return _getAaveTokens(_token);
    }

    /// @notice Liquidity of the position accross all markets
    /// @return Liquidity (or 0 if undercollateralized)
    /// @return Shortfall (or 0 if overcollateralized)
    function accountLiquidity() external view returns(uint, uint) {
        (, uint borrow_oracle, uint borrowing_power_oracle, , ,) = lending_pool.getUserAccountData(address(this));
        return _calculateLiquidity(borrowing_power_oracle, borrow_oracle);
    }

    /// @notice Liquidity of the position for a given market
    /// @param _token Underlying market
    /// @return Liquidity (or 0 if undercollateralized)
    /// @return Shortfall (or 0 if overcollateralized)
    function accountMarketLiquidity(address _token) external view returns (uint, uint) {
        (uint supply_amount, uint borrow_amount) = accountMarketSnapshot(_token);
        uint borrowing_power = supply_amount * _getLTV(_token) / 1e18;
        return _calculateLiquidity(borrowing_power, borrow_amount);
    }

    /// @notice Snapshot of the position accross all markets
    /// @return Total supplied measured in ETH
    /// @return Total borrowed measured in ETH
    function accountSnapshot() external virtual view returns(uint, uint) {
        (uint supply_oracle, uint borrow_oracle, , , ,) = lending_pool.getUserAccountData(address(this));
        return (supply_oracle, borrow_oracle);
    }

    /// @notice Snapshot of the position for a given market
    /// @param _token Underlying market
    /// @return Total supplied measured in _token
    /// @return Total borrowed measured in _token
    function accountMarketSnapshot(address _token) public view returns(uint, uint) {
        (address _atoken, , address _variable_token) = _getAaveTokens(_token);
        uint supply_amount = _erc20Balance(_atoken);
        uint borrow_amount = _erc20Balance(_variable_token);
        return (supply_amount, borrow_amount);
    }

    /* Primitives */

    /// @notice Only executor. Supply tokens to a given market
    /// @param _token Underlying market
    /// @param _amount Amount to supply
    function deposit(address _token, uint _amount) external virtual onlyExecutor {
        _deposit(_token, _amount);
    }

    /// @notice Only executor. Withdraw supplied tokens from a given market
    /// @param _token Underlying market
    /// @param _amount Amount to withdraw
    function withdrawSupply(address _token, uint _amount) external virtual onlyExecutor leverageCheck(_token) {
        _withdrawSupply(_token, _amount);
    }

    /// @notice Only executor. Withdraw all supplied tokens from a given market
    /// @param _token Underlying market
    function withdrawSupplyAll(address _token) public virtual onlyExecutor leverageCheck(_token) {
        _withdrawSupply(_token, type(uint).max);
    }

    /// @notice Only executor. Borrow tokens from a given market
    /// @param _token Underlying market
    /// @param _amount Amount to borrow
    function borrow(address _token, uint _amount) external virtual onlyExecutor leverageCheck(_token) {
        _borrow(_token, _amount);
    }

    /// @notice Only executor. Repay debt for a given market
    /// @param _token Underlying market
    /// @param _amount Amount to repay
    function repay(address _token, uint _amount) external virtual onlyExecutor {
        _repay(_token, _amount);
    }

    /// @notice Only executor. Repay all debt for a given market
    /// @param _token Underlying market
    function repayAll(address _token) external virtual onlyExecutor {
        _repayAll(_token);
    }

    /// @notice Only executor. Use supply side aTokens to repay debt incurred in the same market
    /// @param _amount Amount to repay
    function repayWithATokens(address _token, uint _amount) external onlyExecutor {
        _repayWithATokens(_token, _amount);
    }

    /// @notice Only executor. Use supply side aTokens to repay all debt incurred in the same market
    /// @param _token Underlying market
    function repayAllWithATokens(address _token) external onlyExecutor {
        _repayWithATokens(_token, type(uint).max);
    }

    /* Assembling */
    
    /// @notice Only executor. Supply tokens to the market and assemble a leveraged position. Resulting leverage cant go above maxLF set by owner
    /// @dev Recursively supply-borrow-supply until desired leverage is reached or supplied amount is too small to make a difference
    /// @param _token Underlying market
    /// @param _amount Initial amount to supply to the market. Can be 0 to increase leverage without adding external collateral
    /// @param _max_leverage_factor_mantissa Desired leverage scaled to 1e18
    /// @param _min_borrow_step Minimum amount of tokens to borrow/supply on each step to avoid looping with small amounts
    function increaseLeverage(address _token, uint _amount, uint _max_leverage_factor_mantissa, uint _min_borrow_step) public onlyExecutor leverageCheck(_token) {
        if (_amount > 0)
            _deposit(_token, _amount);

        (uint supply_amount, uint borrow_amount) = accountMarketSnapshot(_token);
        uint net_amount = supply_amount - borrow_amount;
        uint collateral_factor_mantissa = _getLTV(_token);
        /*
            desired borrow based on desired leverage factor and net

            S = LF * net
            B = S - net
            
            nB = nS - net
            nB = nLF * net - net
        */
        uint desired_borrow = net_amount * _max_leverage_factor_mantissa / 1e18 - net_amount;

        while (desired_borrow > borrow_amount) {
            uint max_to_borrow = desired_borrow - borrow_amount;
            uint approx_borrow_limit = supply_amount * collateral_factor_mantissa / 1e18;
            uint approx_current_liquidity = approx_borrow_limit - borrow_amount - 10;
            
            uint to_borrow = Math.min(max_to_borrow, approx_current_liquidity);
            if (to_borrow < _min_borrow_step)
                break;

            _borrow(_token, to_borrow);
            _deposit(_token, to_borrow);
            supply_amount = supply_amount + to_borrow;
            borrow_amount = borrow_amount + to_borrow;
        }

        (supply_amount, borrow_amount) = accountMarketSnapshot(_token);
        emit IncreaseLeverage(_token, _amount, _max_leverage_factor_mantissa);
    }

    /// @notice Only executor. Withdraw tokens to the market and disassemble a leveraged position. Resulting leverage cant go above maxLF set by owner
    /// @dev Repay debt using supply to reach the desired leverage
    /// @param _token Underlying market
    /// @param _amount Initial amount to withdraw from the market
    /// @param _min_leverage_factor_mantissa Desired leverage scaled to 1e18
    function decreaseLeverage(address _token, uint _amount, uint _min_leverage_factor_mantissa, uint ) public onlyExecutor leverageCheck(_token) {
        if (_amount > 0)
            _deposit(_token, _amount);
        if (_min_leverage_factor_mantissa == 1e18) {
            _repayWithATokens(_token, type(uint).max);
            return;
        }

        (uint supply_amount, uint borrow_amount) = accountMarketSnapshot(_token);
        uint net_amount = supply_amount - borrow_amount;
        /*
            desired borrow based on desired leverage factor and net

            S = LF * net
            B = S - net
            
            nB = nS - net
            nB = nLF * net - net
        */
        uint desired_borrow = net_amount * _min_leverage_factor_mantissa / 1e18 - net_amount;
        uint to_repay = borrow_amount - desired_borrow;

        _repayWithATokens(_token, to_repay);
        emit DecreaseLeverage(_token, _amount, _min_leverage_factor_mantissa);
    }

    function _fullDisassemble(address _token) internal {
        decreaseLeverage(_token, 0, 1e18, 0);
        withdrawSupplyAll(_token);
    }

    /// @notice Only executor. Disassemble all leverage and withdraw everything from supply
    /// @param _token Underlying market
    function fullDisassemble(address _token) external onlyExecutor {
        _fullDisassemble(_token);
    }

    /* Rewards */

    /// @notice Only executor. Claim rewards in the first reward token for a given market and amount
    /// @dev Will claim both supply and variable debt rewards. Assumes only 1 reward token and atoken reward token = variable debt reward token
    /// @param _token Underlying market
    /// @param _amount Amount of _reward_address to claim
    /// @return Amount claimed
    function claimRewards(address _token, uint _amount) external onlyExecutor hasRewardsController returns (uint) {
        (address atoken, , ) = _getAaveTokens(_token);
        address[] memory rewards = rewards_controller.getRewardsByAsset(atoken);
        return _claim_rewards(_token, _amount, rewards[0]);
    }

    /// @notice Only executor. Claim rewards in a given token for a given market and amount
    /// @dev Will claim both supply and variable debt rewards
    /// @param _token Underlying market
    /// @param _amount Amount of _reward_address to claim
    /// @param _reward_address Reward token to claim
    /// @return Amount claimed
    function claimRewards(address _token, uint _amount, address _reward_address) external onlyExecutor hasRewardsController returns (uint) {
        return _claim_rewards(_token, _amount, _reward_address);
    }

    /// @notice Only executor. Claim rewards in all reward tokens for a given market and amount
    /// @dev Will claim both supply and variable debt rewards. TODO: develop Harvester with multiple reward tokens support
    /// @param _token Underlying market
    function claimAllRewards(address _token) public onlyExecutor hasRewardsController returns (address[] memory reward_addresses, uint[] memory claimed_amounts) {
        address[] memory tokens = new address[](2);
        (address atoken, , address variable_debt_token) = _getAaveTokens(_token);
        tokens[0] = atoken;
        tokens[1] = variable_debt_token;
        return rewards_controller.claimAllRewards(tokens, address(this));
    }

    /// @notice Only executor. Claim all rewards using underlying_token from parameters_config
    /// @return rewards_addresses all rewards address
    /// @return claimed_amounts all amounts claimed
    function claimRewards() public onlyExecutor hasRewardsController returns (address[] memory rewards_addresses, uint[] memory claimed_amounts) {
      return claimAllRewards(parameters_config.underlying_token);
    }

    /* Assemble via parameters config */

    /// @notice Checks if all parameters_config used in the assembly have the correct value
    modifier hasConfig() {
        require(parameters_config.underlying_token != address(0));
        require(parameters_config.leverage_factor_mantissa >= 1e18);
        _;
    }

    function _assemble() internal returns (uint) {
        PositionConfig memory pc = parameters_config;
        uint amount = _erc20Balance(pc.underlying_token);
        increaseLeverage(pc.underlying_token, amount, pc.leverage_factor_mantissa, pc.min_borrow_step);
        emit Assemble(pc.underlying_token, amount, pc.leverage_factor_mantissa);
        return amount;
    }

    function _disassemble(uint _percent) internal returns (uint) {
        (uint supply_amount, uint borrow_amount) = accountMarketSnapshot(parameters_config.underlying_token);
        uint initial_net = supply_amount - borrow_amount;

        uint final_net = initial_net * (1e18 - _percent) / 1e18;
        uint final_lf = parameters_config.leverage_factor_mantissa;
        uint final_supply = final_net * final_lf / 1e18;
        uint to_withdraw = initial_net - final_net;
        uint temp_supply = to_withdraw + final_supply;
        uint temp_leverage_factor = 1e18 * temp_supply / initial_net;

        decreaseLeverage(parameters_config.underlying_token, 0, temp_leverage_factor, parameters_config.min_withdraw_step);
        if (to_withdraw != 0)
            _withdrawSupply(parameters_config.underlying_token, to_withdraw);
        (supply_amount, borrow_amount) = accountMarketSnapshot(parameters_config.underlying_token);
        
        uint net = supply_amount - borrow_amount;
        uint lf_mantissa = net != 0 ? supply_amount * 1e18 / net : 0;
        emit Disassemble(parameters_config.underlying_token, initial_net - net /* should be same as to_withdraw */, lf_mantissa);
        return to_withdraw;
    }

    /// @notice Only executor. assemble by configuration, use all amount available
    function assemble() external onlyExecutor hasConfig {
        _assemble();
    }

    /// @notice Only executor. Disassemble by configuration
    /// @param _percent Amount to disassemble and withdrawSupply expressed as a percentage. 1e18 is equivalent to 100%.
    function disassemble(uint _percent) external onlyExecutor hasConfig {
        _disassemble(_percent);
    }

    /// @notice Only executor. fullDisassemble by configuration
    function fullDisassemble() external onlyExecutor hasConfig {
        _fullDisassemble(parameters_config.underlying_token);
    }

    /* YieldPositionMinOuts interface */

    function assemble(uint) external onlyExecutor hasConfig returns (uint) {
        return _assemble();
    }

    function disassemble(uint _percentage, uint[] memory) external onlyExecutor hasConfig returns (uint[] memory) {
        uint[] memory amounts_out = new uint[](1);
        amounts_out[0] = _disassemble(_percentage);
        return amounts_out;
    }
}"
    },
    "@itb/aave/contracts/single/PositionManagerMerkl.sol": {
      "content": "/* SPDX-License-Identifier: UNLICENSED */
pragma solidity ^0.8.0;

import './PositionManager.sol';
import '../UseMerkl.sol';

/// @title PositionManager that allows to set claimer operator for Merkl rewards
/// @author IntoTheBlock Corp
contract PositionManagerMerkl is PositionManager, UseMerkl {
    /// @param _executors Executor addresses
    /// @param _wnative Wrapped native token address
    /// @param _tokens Array of supported underlying markets
    /// @param _max_lfs For each supported market in _tokens, maximum leverage factor set by owner scaled by 1e18 (2x leverage: 2e18)
    /// @param _lending_pool Aave V3 LendingPool address
    /// @param _rewards_controller Aave V3 RewardsController address
    /// @param _protocol_data_provider Aave V3 ProtocolDataProvider address
    /// @param _position_config Configuration for assemble/disassemble without parameters
    /// @param _merkl_distributor Merkl distributor address
    /// @param _merkl_operator Merkl operator address for claiming rewards
    constructor(address[] memory _executors, address payable _wnative, address[] memory _tokens, uint[] memory _max_lfs, IPool _lending_pool, IRewardsControllerV3 _rewards_controller, IProtocolDataProviderV3 _protocol_data_provider, PositionConfig memory _position_config, IMerkleDistributor _merkl_distributor, address _merkl_operator) PositionManager(_executors, _wnative, _tokens, _max_lfs, _lending_pool, _rewards_controller, _protocol_data_provider, _position_config) UseMerkl(_merkl_distributor, _merkl_operator) {}
}"
    },
    "@itb/aave/contracts/single/PositionManagerMerklOwnable2StepWithShortcut.sol": {
      "content": "/* SPDX-License-Identifier: UNLICENSED */
pragma solidity ^0.8.0;

import './PositionManagerMerkl.sol';
import '@itb/quant-common/contracts/solidity8/utils/Ownable2StepWithShortcut.sol';

contract PositionManagerMerklOwnable2StepWithShortcut is PositionManagerMerkl, Ownable2StepWithShortcut {
    constructor(address[] memory _executors, address payable _wnative, address[] memory _tokens, uint[] memory _max_lfs, IPool _lending_pool, IRewardsControllerV3 _rewards_controller, IProtocolDataProviderV3 _protocol_data_provider, PositionConfig memory _position_config, IMerkleDistributor _merkl_distributor, address _merkl_operator) PositionManagerMerkl(_executors, _wnative, _tokens, _max_lfs, _lending_pool, _rewards_controller, _protocol_data_provider, _position_config, _merkl_distributor, _merkl_operator) {}
}"
    },
    "@itb/aave/contracts/UseMerkl.sol": {
      "content": "/* SPDX-License-Identifier: UNLICENSED */
pragma solidity ^0.8.0;

import './merkl/IMerkleDistributor.sol';
import '@openzeppelin/contracts/access/Ownable2Step.sol';

/// @title Allows to set claimer operator for Merkl rewards
/// @author IntoTheBlock Corp
abstract contract UseMerkl is Ownable2Step {
    IMerkleDistributor public merkl_distributor;

    event UpdateMerklDistributor(address merkl_distributor);
    event AddMerklOperator(address indexed operator);
    event RemoveMerklOperator(address indexed operator);

    /// @param _merkl_distributor Merkl distributor address
    /// @param _merkl_operator Merkl operator address for claiming rewards
    constructor(IMerkleDistributor _merkl_distributor, address _merkl_operator) {
        updateMerklDistributor(_merkl_distributor);
        if (_merkl_operator != address(0))
            addMerklOperator(_merkl_operator);
    }

    function updateMerklDistributor(IMerkleDistributor _merkl_distributor) public onlyOwner {
        merkl_distributor = _merkl_distributor;
        emit UpdateMerklDistributor(address(_merkl_distributor));
    }

    function addMerklOperator(address _operator) public onlyOwner {
        require(merkl_distributor.operators(address(this), _operator) == 0, 'O1'); // It's already an operator
        merkl_distributor.toggleOperator(address(this), _operator);
        emit AddMerklOperator(_operator);
    }

    function removeMerklOperator(address _operator) external onlyOwner {
        require(merkl_distributor.operators(address(this), _operator) > 0, 'O2'); // It's not an operator
        merkl_distributor.toggleOperator(address(this), _operator);
        emit RemoveMerklOperator(_operator);
    }
}"
    },
    "@itb/quant-common/contracts/solidity8/ITBContract.sol": {
      "content": "/* SPDX-License-Identifier: UNLICENSED */
pragma solidity ^0.8.20;

import './utils/Withdrawable.sol';
import './utils/IWETH.sol';


/// @title ITBContract contract that implements common owner only functions accros all strategies
/// @author IntoTheBlock Corp
/// @dev Abstract
abstract contract ITBContract is Withdrawable {
    using SafeERC20 for IERC20;
    event ApproveToken(address indexed token, address guy, uint256 wad);
    address payable immutable public WNATIVE;

    uint constant ONE = 1e18;

    /// @param _executors Executor addresses
    constructor(address[] memory _executors, address payable _wnative) Executable(_executors) {
        WNATIVE = _wnative;
    }

    function _percentageAmount(uint _amount, uint _percentage) internal pure returns (uint) {
        return _amount * _percentage / ONE;
    }

    ///

Tags:
ERC20, ERC165, Multisig, Liquidity, Yield, Multi-Signature, Factory, Oracle|addr:0x135df9a87f4d90ba5164e487c654166a24530ad4|verified:true|block:23544258|tx:0x44521e0775db9761a474853fc022adae26663aa1ae35c20268a1c32bd203e2ea|first_check:1760082905

Submitted on: 2025-10-10 09:55:05

Comments

Log in to comment.

No comments yet.