LoanManagerOwnable2StepWithShortcut

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/IPriceOracle.sol": {
      "content": "// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;

interface IPriceOracleGetter {
    function getAssetPrice(address _asset) external view returns (uint256);
    function getAssetsPrices(address[] calldata _assets) external view returns(uint256[] memory);
    function getSourceOfAsset(address _asset) external view returns(address);
    function getFallbackOracle() external view returns(address);
}"
    },
    "@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/LoanManager.sol": {
      "content": "/* SPDX-License-Identifier: UNLICENSED */
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import '@itb/quant-common/contracts/solidity8/ITBContract.sol';
import '@itb/quant-common/contracts/solidity8/ILoanManager.sol';
import './aaveV3/IPriceOracle.sol';
import './aaveV3/IPool.sol';
import './aaveV3/IProtocolDataProviderV3.sol';
import './aaveV3/IRewardsControllerV3.sol';

/// @title LoanManager that targets Aave V2 markets.
/// @author IntoTheBlock Corp
contract LoanManager is ITBContract, ILoanManager {
    enum SnapshotUpdateAction { SUPPLY, BORROW, REPAY, WITHDRAW }
    event SnapshotUpdate(SnapshotUpdateAction indexed action, uint256 amount, address executor, address supplyToken, address borrowToken, uint256 totalSupplied, uint256 totalDebt);
    event ClaimRewards(address[] claimedTokens, uint256[] claimedAmounts);
    event UpdateLoanConfig(LoanConfig oldConfig, LoanConfig newConfig);
    event EnableCollateral(address supplyToken);
    event DisableCollateral(address supplyToken);
    event UpdateLendingPool(IPool oldPool, IPool newPool);
    event UpdatePriceOracle(IPriceOracleGetter oldOracle, IPriceOracleGetter newOracle);
    event UpdateProtocolDataProvider(IProtocolDataProviderV3 oldProvider, IProtocolDataProviderV3 newProvider);
    event UpdateRewardsController(IRewardsControllerV3 oldController, IRewardsControllerV3 newController);
    event UpdateEModeCategory(uint8 emode_category);
    event SetEMode(uint8 emode_category);

    IPriceOracleGetter priceOracle;
    IPool lendingPool;
    IProtocolDataProviderV3 protocolDataProvider;
    IRewardsControllerV3 rewardsController;
    LoanConfig public loanConfig;
    uint8 public emodeCategory;

    /// @param _executors Array of executors addresses.
    /// @param _wnative Native token address.
    /// @param _supplyAddress Supplied token address.
    /// @param _borrowAddress Borrowed token address.
    /// @param _minHealthFactor Minimum health factor. 1e18 is equivalent to 1.00.
    /// @param _lendingPool Address of the Aave V3 lending pool.
    /// @param _priceOracle Address of the Aave V3 price oracle.
    /// @param _protocolDataProvider Address of the Aave V3 protocol data provider.
    /// @param _rewardsController Address of the Aave V3 protocol rewards controller.
    constructor(
        address[] memory _executors,
        address payable _wnative,
        address _supplyAddress,
        address _borrowAddress,
        uint _minHealthFactor,
        IPool _lendingPool,
        IPriceOracleGetter _priceOracle,
        IProtocolDataProviderV3 _protocolDataProvider,
        IRewardsControllerV3 _rewardsController
    ) ITBContract (_executors, _wnative) {
        setConfig(_supplyAddress, _borrowAddress, _minHealthFactor);
        updateLendingPool(_lendingPool);
        updatePriceOracle(_priceOracle);
        updateProtocolDataProvider(_protocolDataProvider);
        updateRewardsController(_rewardsController);
    }

    /* Helpers */

    /// @notice Compares after execution health factor vs min health factor and reverts if below min health factor
    modifier healthFactorCheck() {
        _;
        require(getHealthFactor() >= loanConfig.minHealthFactor, "Dangerous Health Factor reached");
    }

    modifier hasIncentivesController() {
        require(address(rewardsController) != address(0), 'C1'); // IncentivesController not set
        _;
    }

    /// @notice Converts a given amount from base to asset using the oracle and returns the result.
    /// @param asset Address of the asset to convert to.
    /// @param baseAmount Amount in base token to be converted.
    /// @return convertedAmount amount converted.
    function _baseToAsset(address asset, uint baseAmount) internal view returns (uint convertedAmount) {
        return baseAmount * (10 ** _decimals(asset)) / priceOracle.getAssetPrice(asset);
    }

    /// @notice Fetches the number of decimals of a given asset.
    /// @param asset Address of the asset to fetch the decimals from.
    /// @return decimals decimals of the asset.
    function _decimals(address asset) internal view returns (uint decimals) {
        decimals = ERC20(asset).decimals();
    }

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

    /// @notice Checks if the supplied asset is enabled as collateral
    /// @return isCollateral true if the asset is enabled as collateral, false otherwise
    function _isCollateral() internal view returns (bool isCollateral){
        (, , , , , , , , isCollateral) = protocolDataProvider.getUserReserveData(loanConfig.supplyAddress, address(this));
    }

    function _logSnapshot(SnapshotUpdateAction _action, uint256 _amount) internal {
        emit SnapshotUpdate(_action, _amount, msg.sender, loanConfig.supplyAddress, loanConfig.borrowAddress, getSupply(), getBorrow());
    }
    
    /* Internal */

    /// @notice Fetches the current supply rate of the configured supply market (internal implementation).
    /// @return supplyRate Supply rate.
    function _getSupplyRate() internal view returns (uint256 supplyRate){
        (, , , , , supplyRate, , , , , ,) = protocolDataProvider.getReserveData(loanConfig.supplyAddress);
    }

    /// @notice Fetches the current borrow rate of the configured borrow market (internal implementation).
    /// @return borrowRate Borrow rate.
    function _getBorrowRate() internal view returns (uint256 borrowRate){
        (, , , , , , borrowRate, , , , ,) = protocolDataProvider.getReserveData(loanConfig.borrowAddress);
    }

    /// @notice Fetches total supply and debt of the configured markets (internal implementation).
    /// @return supplyMarketDeposits Total supply of the configured supply market.
    /// @return supplyMarketDebt Total debt of the configured supply market.
    /// @return borrowMarketDeposits Total supply of the configured borrow market.
    /// @return borrowMarketDebt Total debt of the configured borrow market.
    function _getMarketsData() internal view returns (uint256 supplyMarketDeposits, uint256 supplyMarketDebt, uint256 borrowMarketDeposits, uint256 borrowMarketDebt){
        (, , uint256 supplyMarketTotalSupply, uint256 supplyMarketStableDebt, uint256 supplyMarketVariableDebt, , , , , , , ) = protocolDataProvider.getReserveData(loanConfig.supplyAddress);
        (, , uint256 borrowMarketTotalSupply, uint256 borrowMarketStableDebt, uint256 borrowMarketVariableDebt, , , , , , , ) = protocolDataProvider.getReserveData(loanConfig.borrowAddress);
        supplyMarketDeposits = supplyMarketTotalSupply;
        supplyMarketDebt = supplyMarketStableDebt + supplyMarketVariableDebt;
        borrowMarketDeposits = borrowMarketTotalSupply;
        borrowMarketDebt = borrowMarketStableDebt + borrowMarketVariableDebt;
    }
    
    /// @notice Supplies the given amount of supply token to pool (internal implementation).
    /// @param _amount Amount of token to supply.
    function _supply(uint256 _amount) internal {
        lendingPool.supply(loanConfig.supplyAddress, _amount, address(this), 0);
    }
    
    /// @notice Borrows the given amount of borrow token from pool (internal implementation).
    /// @param _amount Amount of token to borrow.
    function _borrow(uint256 _amount) internal {
        lendingPool.borrow(loanConfig.borrowAddress, _amount, 2, 0, address(this));
    }

    /// @notice Repays the given amount of borrow token debt to lending pool (internal implementation).
    /// @param _amount Amount of debt to repay.
    function _repay(uint256 _amount) internal virtual {
        _checkAllowanceAndApprove(loanConfig.borrowAddress, address(lendingPool), _amount);
        lendingPool.repay(loanConfig.borrowAddress, _amount, 2, address(this));
    }

    /// @notice Withdraw supplied tokens from a given market (internal implementation).
    /// @param _amount Amount to withdraw.
    function _withdrawSupply(uint256 _amount) internal virtual {
        lendingPool.withdraw(loanConfig.supplyAddress, _amount, address(this));
    }

    /// @notice Claims pending rewards for the configured markets (internal implementation).
    /// @param tokens Array of token addresses to claim.
    /// @return claimedTokens Array of claimed tokens addresses.
    /// @return claimedAmounts Array of claimed amounts.
    function _claimRewards(address[] memory tokens) internal returns (address[] memory claimedTokens, uint256 [] memory claimedAmounts){
        (claimedTokens, claimedAmounts) = rewardsController.claimAllRewards(tokens, address(this));
    }
    
    /* Infra */

    /// @notice Only owner. Sets V3 config parameters.
    /// @param _supplyAddress Address of the token to supply to pool.
    /// @param _borrowAddress Address of the token to borrow from pool.
    /// @param _minHealthFactor Minimum acceptable health factor.
    function setConfig(address _supplyAddress, address _borrowAddress, uint _minHealthFactor) public onlyOwner {
        LoanConfig memory new_config = LoanConfig(_supplyAddress, _borrowAddress, _minHealthFactor);
        emit UpdateLoanConfig(loanConfig, new_config);
        loanConfig = new_config;
    }

    /// @notice Only owner. Sets V3 config parameters.
    /// @param _supplyAddress Address of the token to supply to pool.
    /// @param _borrowAddress Address of the token to borrow from pool.
    /// @param _minHealthFactor Minimum acceptable health factor.
    /// @param _emode_category Emode category to use
    function setConfig(address _supplyAddress, address _borrowAddress, uint _minHealthFactor, uint8 _emode_category) public onlyOwner {
        setConfig(_supplyAddress, _borrowAddress, _minHealthFactor);

        emit UpdateEModeCategory(_emode_category);
        emodeCategory = _emode_category;
    }

    /// @notice Only owner. Sets EMode category to the one set by config
    function setEMode() external onlyOwner {
        lendingPool.setUserEMode(emodeCategory);
        emit SetEMode(emodeCategory);
    }

    /// @notice Only owner. Enables supplied token to be used as collateral.
    function enableCollateral() external onlyOwner {
        lendingPool.setUserUseReserveAsCollateral(loanConfig.supplyAddress, true);
        emit EnableCollateral(loanConfig.supplyAddress);
    }

    /// @notice Only owner. Disables supplied token to be used as collateral.
    function disableCollateral() external onlyOwner healthFactorCheck {
        lendingPool.setUserUseReserveAsCollateral(loanConfig.supplyAddress, false);
        emit DisableCollateral(loanConfig.supplyAddress);
    }

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

    /// @notice Only owner. Update PriceOracle address
    /// @param _address New address
    function updatePriceOracle(IPriceOracleGetter _address) public onlyOwner {
        emit UpdatePriceOracle(priceOracle, _address);
        priceOracle = _address;
    }

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

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

    /* View */

    /// @notice Fetches config parameters.
    /// @return config config parameters.
    function getConfig() public view returns (LoanConfig memory config) {
        config = loanConfig;
    }

    /// @notice Fetches prices from Aave Price Oracle.
    /// @return supplyTokenPrice supply token price.
    /// @return borrowTokenPrice borrow token price.
    function getPrices() public view returns (uint256 supplyTokenPrice, uint256 borrowTokenPrice){
        address[] memory tokens = new address[](2);
        uint256[] memory prices = new uint256[](2);
        tokens[0] = loanConfig.supplyAddress;
        tokens[1] = loanConfig.borrowAddress;
        prices = priceOracle.getAssetsPrices(tokens);
        return (prices[0], prices[1]);
    }

    /// @notice Fetches health factor from pool.
    /// @return healthFactor health factor.
    function getHealthFactor() public view returns (uint256 healthFactor){
        (, , , , , healthFactor) = lendingPool.getUserAccountData(address(this));
    }

    /// @notice Fetches liquidity and shortfall from pool.
    /// @return liquidity Liquidity (or 0 if undercollateralized).
    /// @return shortfall Shortfall (or 0 if overcollateralized).
    function getLiquidityAndShortFall() public view returns (uint256 liquidity, uint256 shortfall){
        (liquidity, shortfall) = getLiquidityAndShortFallAsBase();
        liquidity = _baseToAsset(loanConfig.supplyAddress, liquidity);
        shortfall = _baseToAsset(loanConfig.borrowAddress, shortfall);
    }

    /// @notice Fetches amount of token supplied to pool.
    /// @return supplied Amount of token supplied to pool.
    function getSupply() public view returns (uint256 supplied){
        (address atoken, ,) = _getAaveTokens(loanConfig.supplyAddress);
        supplied = _erc20Balance(atoken);
    }

    /// @notice Fetches amount of token borrowed from pool.
    /// @return borrowed Amount of token borrowed from pool.
    function getBorrow() public view returns (uint256 borrowed){
        (, , address variableDebtToken) = _getAaveTokens(loanConfig.borrowAddress);
        borrowed = _erc20Balance(variableDebtToken);
    }

    /// @notice Fetches the current supply rate of the configured supply market.
    /// @return supplyRate Supply rate.
    function getSupplyRate() public view returns (uint256 supplyRate){
        supplyRate = _getSupplyRate();
    }

    /// @notice Fetches the current borrow rate of the configured borrow market.
    /// @return borrowRate Borrow rate.
    function getBorrowRate() public view returns (uint256 borrowRate){
        borrowRate = _getBorrowRate();
    }

    /// @notice Aggregates and returns position data.
    /// @return healthFactor Health factor.
    /// @return liquidity Liquidity (or 0 if undercollateralized).
    /// @return shortfall Shortfall (or 0 if overcollateralized).
    /// @return supplied Amount of tokens supplied to pool.
    /// @return borrowed Amount of tokens borrowed from pool.
    /// @return supplyRate Supply rate of the configured supply market.
    /// @return borrowRate Borrow rate of the configured borrow market.
    function getPositionDataSnapshot() public view returns (uint256 healthFactor, uint256 liquidity, uint256 shortfall, uint256 supplied, uint256 borrowed, uint256 supplyRate, uint256 borrowRate){
        healthFactor = getHealthFactor();
        (liquidity, shortfall) = getLiquidityAndShortFall();
        supplied = getSupply();
        borrowed = getBorrow();
        supplyRate = getSupplyRate();
        borrowRate = getBorrowRate();
    }

    /// @notice Fetches total supply, debt and current price of the configured markets.
    /// @return supplyMarketDeposits Total supply of the configured supply market.
    /// @return supplyMarketDebt Total debt of the configured supply market.
    /// @return supplyMarketAssetPrice Price of the configured supply market underlying.
    /// @return borrowMarketDeposits Total supply of the configured borrow market.
    /// @return borrowMarketDebt Total debt of the configured borrow market.
    /// @return borrowMarketAssetPrice Price of the configured borrow market underlying.
    function getMarketsData() public view returns (uint256 supplyMarketDeposits, uint256 supplyMarketDebt, uint256 supplyMarketAssetPrice, uint256 borrowMarketDeposits, uint256 borrowMarketDebt, uint256 borrowMarketAssetPrice){
        (supplyMarketDeposits, supplyMarketDebt, borrowMarketDeposits, borrowMarketDebt) = _getMarketsData();
        (supplyMarketAssetPrice, borrowMarketAssetPrice ) = getPrices();
    }

    /// @notice Fetches amount of token supplied to pool as base.
    /// @return supplyAsBase Amount of token supplied to pool as base.
    function getSupplyAsBase() public view returns (uint256 supplyAsBase){
        (supplyAsBase, , , , ,) = lendingPool.getUserAccountData(address(this));
    }

    /// @notice Fetches amount of token borrowed from pool as base.
    /// @return borrowAsBase Amount of token borrowed from pool as base.
    function getBorrowAsBase() public view returns (uint256 borrowAsBase){
        (, borrowAsBase, , , ,) = lendingPool.getUserAccountData(address(this));
    }

    /// @notice Fetches liquidity and shortfall from pool as base.
    /// @return liquidity Liquidity (or 0 if undercollateralized) as base.
    /// @return shortfall Shortfall (or 0 if overcollateralized) as base.
    function getLiquidityAndShortFallAsBase() public view returns (uint256 liquidity, uint256 shortfall){
        (uint256 supplied, uint256 borrowed, , , uint256 ltv, ) = lendingPool.getUserAccountData(address(this));
        uint256 borrow_power = supplied * ltv / 1e4;
        liquidity = borrow_power > borrowed ? borrow_power - borrowed : 0;
        shortfall = borrow_power < borrowed ? borrowed - borrow_power : 0;
    }

    /// @notice Fetches collateral factor for the given collateral.
    /// @param _collateral Address of the collateral.
    /// @return Collateral factor.
    function getLiquidationThreshold(address _collateral) public view returns (uint256){
        (, , uint256 liquidationThreshold, , , , , , ,) = protocolDataProvider.getReserveConfigurationData(_collateral);
        return liquidationThreshold * 1e18 / 1e4;
    }

    /* Primitives */

    /// @notice Only executor. Supplies the given amount of supply token to pool.
    /// @param _amount Amount of token to supply.
    function supply(uint256 _amount) public onlyExecutor {
        _checkAllowanceAndApprove(loanConfig.supplyAddress, address(lendingPool), _amount);
        _supply(_amount);
        _logSnapshot(SnapshotUpdateAction.SUPPLY, _amount);
    }

    /// @notice Only executor. Borrows the given amount of borrow token from pool.
    /// @param _amount Amount of token to borrow.
    function borrow(uint256 _amount) public onlyExecutor healthFactorCheck {
        _borrow(_amount);
        _logSnapshot(SnapshotUpdateAction.BORROW, _amount);
    }

    /// @notice Only executor. Repays the given amount of borrow token debt to pool.
    /// @param _amount Amount of token debt to repay.
    function repay(uint256 _amount) public onlyExecutor {
        _repay(_amount);
        _logSnapshot(SnapshotUpdateAction.REPAY, _amount);
    }

    /// @notice Only executor. Repays all borrow token debt.
    function repayAll() public onlyExecutor {
        uint256 totalBorrow = getBorrow();
        if (totalBorrow == 0)
            return;
        _repay(type(uint).max);
        _approveToken(loanConfig.borrowAddress, address(lendingPool), 0);
        _logSnapshot(SnapshotUpdateAction.REPAY, totalBorrow);
    }

    /// @notice Only executor. Withdraws the given amount of underlying from pool.
    /// @param _amount Amount of underlying to withdraw.
    function withdrawSupply(uint256 _amount) public onlyExecutor healthFactorCheck {
        _withdrawSupply(_amount);
        _logSnapshot(SnapshotUpdateAction.WITHDRAW, _amount);
    }

    /// @notice Only executor. Withdraws all underlying from pool.
    function withdrawSupplyAll() public onlyExecutor healthFactorCheck {
        uint256 totalSupply = getSupply();
        _withdrawSupply(type(uint).max);
        _logSnapshot(SnapshotUpdateAction.WITHDRAW, totalSupply);
    }

    /// @notice Only executor. Repays all borrow token debt and withdraws all underlying from pool.
    /// @return amountWithdrawn Amount of tokens withdrawn.
    function repayAllAndWithdrawSupplyAll() public onlyExecutor healthFactorCheck returns (uint256 amountWithdrawn){
        repayAll();
        uint256 previousBalance = _erc20Balance(loanConfig.supplyAddress);
        withdrawSupplyAll();
        amountWithdrawn = _erc20Balance(loanConfig.supplyAddress) - previousBalance;
    }

    /// @notice Only executor. Claims pending rewards for the configured markets.
    /// @return claimedTokens Array of claimed tokens addresses.
    /// @return claimedAmounts Array of claimed amounts.
    function claimRewards() public onlyExecutor hasIncentivesController returns (address[] memory claimedTokens, uint256[] memory claimedAmounts){
        address[] memory tokens = new address[](4);
        (address aToken, , address variableDebtToken) = _getAaveTokens(loanConfig.supplyAddress);
        tokens[0] = aToken;
        tokens[1] = variableDebtToken;
        (address aTokenB, , address variableDebtTokenB) = _getAaveTokens(loanConfig.borrowAddress);
        tokens[2] = aTokenB;
        tokens[3] = variableDebtTokenB;
        (claimedTokens, claimedAmounts) = _claimRewards(tokens);
        emit ClaimRewards(claimedTokens, claimedAmounts);
    }

    /* Interfaces for Harvester */
    
    /// @notice Only executor. Supply tokens to the configured market.
    /// @param _amount Amount to supply.
    /// @dev For Harvester compatibility.
    function deposit(address, uint _amount) external virtual onlyExecutor {
        supply(_amount);
    }

    /// @notice Only executor. Claim rewards across all markets.
    /// @dev For Harvester compatibility.
    function claimRewards(address, uint) external virtual onlyExecutor hasIncentivesController returns (uint){
        (, uint[] memory claimedAmounts) = claimRewards();
        return claimedAmounts[0];
    }
}"
    },
    "@itb/aave/contracts/LoanManagerOwnable2StepWithShortcut.sol": {
      "content": "/* SPDX-License-Identifier: UNLICENSED */
pragma solidity ^0.8.0;

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

contract LoanManagerOwnable2StepWithShortcut is LoanManager, Ownable2StepWithShortcut {
    constructor(address[] memory _executors, address payable _wnative, address _supplyAddress, address _borrowAddress, uint _minHealthFactor, IPool _lendingPool, IPriceOracleGetter _priceOracle, IProtocolDataProviderV3 _protocolDataProvider, IRewardsControllerV3 _rewardsController) LoanManager(_executors, _wnative, _supplyAddress, _borrowAddress, _minHealthFactor, _lendingPool, _priceOracle, _protocolDataProvider, _rewardsController) {}
}"
    },
    "@itb/quant-common/contracts/solidity8/ILoanManager.sol": {
      "content": "/* SPDX-License-Identifier: UNLICENSED */
pragma solidity ^0.8.20;

import './ITBContract.sol';

interface ILoanManager {
    struct LoanConfig {
        address supplyAddress;
        address borrowAddress;
        uint minHealthFactor;
    }

    function getConfig() external view returns (LoanConfig memory);

    function setConfig(address supplyAddress, address borrowAddress, uint minHealthFactor) external;

    function supply(uint amount) external;

    function borrow(uint amount) external;

    function repay(uint256 _amount) external;

    function repayAll() external;

    function withdrawSupply(uint256 _amount) external;

    function withdrawSupplyAll() external;

    function repayAllAndWithdrawSupplyAll() external returns (uint256);

    function getPrices() external view returns (uint256, uint256);

    function getHealthFactor() external view returns (uint256);

    function getLiquidityAndShortFall() external view returns (uint256, uint256);

    function getSupply() external view returns (uint256);

    function getBorrow() external view returns (uint256);

    function getSupplyRate() external view returns (uint256);

    function getBorrowRate() external view returns (uint256);

    function getPositionDataSnapshot() external view returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256);

    function claimRewards() external returns (address[] memory, uint256[] memory);

    function getMarketsData() external returns (uint256, uint256, uint256, uint256, uint256, uint256);

    function getLiquidationThreshold(address _collateral) external view returns (uint256);
}"
    },
    "@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;
    }

    /// @notice Set allowance for a given token, amount and spender
    /// @param _token Token to spend
    /// @param _guy Spender
    /// @param _wad Max amount to spend
    function _approveToken(address _token, address _guy, uint256 _wad) internal {
        if (_wad != 0)
            IERC20(_token).forceApprove(_guy, _wad);
        else
            IERC20(_token).approve(_guy, _wad);
        emit ApproveToken(_token, _guy, _wad);
    }

    /// @notice For a given token, amount and spender, check if contract can spend amount and, if necessary, set the allowance to amount
    /// @param _token Token to spend
    /// @param _guy Spender
    /// @param _amount Amount to spend
    function _checkAllowanceAndApprove(address _token, address _guy, uint256 _amount) internal {
        _checkAllowanceAndApprove(_token, _guy, _amount, _amount);
    }

    /// @notice For a given token, amount and spender, check if contract can spend amount and, if necessary, set the allowance to approval amount
    /// @param _token Token to spend
    /// @param _guy Spender
    /// @param _amount Amount to spend
    /// @param _approval_amount Amount to approve
    function _checkAllowanceAndApprove(address _token, address _guy, uint256 _amount, uint256 _approval_amount) internal {
        if (IERC20(_token).allowance(address(this), _guy) < _amount)
            _approveToken(_token, _guy, _approval_amount);
    }

    /// @notice Only owner. Set allowance for a given token, amount and spender
    /// @param _token Token to spend
    /// @param _guy Spender
    /// @param _wad Max amount to spend
    function approveToken(address _token, address _guy, uint256 _wad) external onlyOwner {
        _approveToken(_token, _guy, _wad);
    }

    /// @notice Only owner. Revoke allowance for a given token and spender
    /// @param _token Token to spend
    /// @param _guy Spender
    function revokeToken(address _token, address _guy) external onlyOwner {
        _approveToken(_token, _guy, 0);
    }

    /// @notice Only owner. Execute an arbitrary call
    /// @param _to Target address
    /// @param _value Value (i. e. msg.value)
    /// @param _data Invocation data
    function execute(address _to, uint256 _value, bytes calldata _data) external payable onlyOwner {
        (bool success, bytes memory returnData) = _to.call{ value: _value }(_data);
        require(success, string(returnData));
    }

    /// @notice Only owner. Execute multiple arbitrary calls in order
    /// @param _tos Target address for each call
    /// @param _values Value for each call (i. e. msg.value)
    /// @param _datas Invocation data for each call
    function batchExecute(address[] calldata _tos, uint256[] calldata _values, bytes[] calldata _datas) external payable onlyOwner {
        require(_tos.length == _values.length && _tos.length == _datas.length, "Arguments length mismatch");
        for (uint256 i = 0; i < _tos.length; i++) {
            (bool success, bytes memory returnData) = _tos[i].call{ value: _values[i] }(_datas[i]);
            require(success, string(returnData));
        }
    }

    function wrapNative(uint256 _amount) public onlyExecutor {
        IWETH(WNATIVE).deposit{ value: _amount }();
    }

    function unwrapNative(uint256 _amount) public onlyExecutor {
        IWETH(WNATIVE).withdraw(_amount);
    }
}"
    },
    "@itb/quant-common/contracts/solidity8/utils/Executable.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/access/Ownable2Step.sol";

/// @title Base contract that implements executor related functions
/// @author IntoTheBlock Corp
/// @dev Abstract
abstract contract Executable is Ownable2Step {
    mapping(address => bool) public executors;

    event ExecutorUpdated(address indexed executor, bool enabled);

    /// @param _executors Initial whitelisted executor addresses
    constructor(address[] memory _executors) Ownable(msg.sender) {
        for (uint256 i = 0; i < _executors.length; i++) {
            addExecutor(_executors[i]);
        }
    }

    /// @notice Revert if call is not being made from the owner or an executor
    modifier onlyExecutor() {
        require(owner() == msg.sender || executors[msg.sender], "Executable: caller is not the executor");
        _;
    }

    /// @notice Only owner. Add an executor
    /// @param _executor New executor address
    function addExecutor(address _executor) public onlyOwner {
        emit ExecutorUpdated(_executor, true);
        executors[_executor] = true;
    }

    /// @notice Only owner. Remove an executor
    /// @param _executor Executor address to remove
    function removeExecutor(address _executor) external onlyOwner {
        emit ExecutorUpdated(_executor, false);
        executors[_executor] = false;
    }
}
"
    },
    "@itb/quant-common/contracts/solidity8/utils/IWETH.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

interface IWETH {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint8);

    event Approval(address indexed src, address indexed guy, uint256 wad);
    event Transfer(address indexed src, address indexed dst, uint256 wad);
    event Deposit(address indexed dst, uint256 wad);
    event Withdrawal(address indexed src, uint256 wad);

    function balanceOf(address) external view returns (uint256);
    function allowance(address, address) external view returns (uint256);

    fallback() external payable;
    receive() external payable;
    function deposit() external payable;
    function withdraw(uint256 wad) external;
    function totalSupply() external view returns (uint256);
    function approve(address guy, uint256 wad) external returns (bool);
    function transfer(address dst, uint256 wad) external returns (bool);
    function transferFrom(address src, address dst, uint256 wad) external returns (bool);
}"
    },
    "@itb/quant-common/contracts/solidity8/utils/Ownable2StepWithShortcut.sol": {
      "content": "/* SPDX-License-Identifier: UNLICENSED */
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/access/Ownable2Step.sol";

abstr

Tags:
ERC20, ERC165, Multisig, Liquidity, Multi-Signature, Factory, Oracle|addr:0x2afbd96fb854083574b738b36af34703c89b8656|verified:true|block:23695131|tx:0x31d8a52f0f0f8ffd4a7e4fb24aac6b1fa47e3931c3f5e55e1b80a397ca26a133|first_check:1761910021

Submitted on: 2025-10-31 12:27:02

Comments

Log in to comment.

No comments yet.