creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/periphery/rewards/RewardsController.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.10;\n\nimport {VersionedInitializable} from '@aave/core-v3/contracts/protocol/libraries/aave-upgradeability/VersionedInitializable.sol';\nimport {SafeCast} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/SafeCast.sol';\nimport {IScaledBalanceToken} from '@aave/core-v3/contracts/interfaces/IScaledBalanceToken.sol';\nimport {RewardsDistributor} from './RewardsDistributor.sol';\nimport {IRewardsController} from './interfaces/IRewardsController.sol';\nimport {ITransferStrategyBase} from './interfaces/ITransferStrategyBase.sol';\nimport {RewardsDataTypes} from './libraries/RewardsDataTypes.sol';\nimport {IEACAggregatorProxy} from '../misc/interfaces/IEACAggregatorProxy.sol';\n\n/**\n * @title RewardsController\n * @notice Abstract contract template to build Distributors contracts for ERC20 rewards to protocol participants\n * @author Aave\n **/\ncontract RewardsController is RewardsDistributor, VersionedInitializable, IRewardsController {\n  using SafeCast for uint256;\n\n  uint256 public constant REVISION = 1;\n\n  // This mapping allows whitelisted addresses to claim on behalf of others\n  // useful for contracts that hold tokens to be rewarded but don't have any native logic to claim Liquidity Mining rewards\n  mapping(address => address) internal _authorizedClaimers;\n\n  // reward => transfer strategy implementation contract\n  // The TransferStrategy contract abstracts the logic regarding\n  // the source of the reward and how to transfer it to the user.\n  mapping(address => ITransferStrategyBase) internal _transferStrategy;\n\n  // This mapping contains the price oracle per reward.\n  // A price oracle is enforced for integrators to be able to show incentives at\n  // the current Aave UI without the need to setup an external price registry\n  // At the moment of reward configuration, the Incentives Controller performs\n  // a check to see if the provided reward oracle contains `latestAnswer`.\n  mapping(address => IEACAggregatorProxy) internal _rewardOracle;\n\n  modifier onlyAuthorizedClaimers(address claimer, address user) {\n    require(_authorizedClaimers[user] == claimer, 'CLAIMER_UNAUTHORIZED');\n    _;\n  }\n\n  constructor(address emissionManager) RewardsDistributor(emissionManager) {}\n\n  /**\n   * @dev Initialize for RewardsController\n   * @dev It expects an address as argument since its initialized via PoolAddressesProvider._updateImpl()\n   **/\n  function initialize(address) external initializer {}\n\n  /// @inheritdoc IRewardsController\n  function getClaimer(address user) external view override returns (address) {\n    return _authorizedClaimers[user];\n  }\n\n  /**\n   * @dev Returns the revision of the implementation contract\n   * @return uint256, current revision version\n   */\n  function getRevision() internal pure override returns (uint256) {\n    return REVISION;\n  }\n\n  /// @inheritdoc IRewardsController\n  function getRewardOracle(address reward) external view override returns (address) {\n    return address(_rewardOracle[reward]);\n  }\n\n  /// @inheritdoc IRewardsController\n  function getTransferStrategy(address reward) external view override returns (address) {\n    return address(_transferStrategy[reward]);\n  }\n\n  /// @inheritdoc IRewardsController\n  function configureAssets(RewardsDataTypes.RewardsConfigInput[] memory config)\n    external\n    override\n    onlyEmissionManager\n  {\n    for (uint256 i = 0; i < config.length; i++) {\n      // Get the current Scaled Total Supply of AToken or Debt token\n      config[i].totalSupply = IScaledBalanceToken(config[i].asset).scaledTotalSupply();\n\n      // Install TransferStrategy logic at IncentivesController\n      _installTransferStrategy(config[i].reward, config[i].transferStrategy);\n\n      // Set reward oracle, enforces input oracle to have latestPrice function\n      _setRewardOracle(config[i].reward, config[i].rewardOracle);\n    }\n    _configureAssets(config);\n  }\n\n  /// @inheritdoc IRewardsController\n  function setTransferStrategy(address reward, ITransferStrategyBase transferStrategy)\n    external\n    onlyEmissionManager\n  {\n    _installTransferStrategy(reward, transferStrategy);\n  }\n\n  /// @inheritdoc IRewardsController\n  function setRewardOracle(address reward, IEACAggregatorProxy rewardOracle)\n    external\n    onlyEmissionManager\n  {\n    _setRewardOracle(reward, rewardOracle);\n  }\n\n  /// @inheritdoc IRewardsController\n  function handleAction(\n    address user,\n    uint256 totalSupply,\n    uint256 userBalance\n  ) external override {\n    _updateData(msg.sender, user, userBalance, totalSupply);\n  }\n\n  /// @inheritdoc IRewardsController\n  function claimRewards(\n    address[] calldata assets,\n    uint256 amount,\n    address to,\n    address reward\n  ) external override returns (uint256) {\n    require(to != address(0), 'INVALID_TO_ADDRESS');\n    return _claimRewards(assets, amount, msg.sender, msg.sender, to, reward);\n  }\n\n  /// @inheritdoc IRewardsController\n  function claimRewardsOnBehalf(\n    address[] calldata assets,\n    uint256 amount,\n    address user,\n    address to,\n    address reward\n  ) external override onlyAuthorizedClaimers(msg.sender, user) returns (uint256) {\n    require(user != address(0), 'INVALID_USER_ADDRESS');\n    require(to != address(0), 'INVALID_TO_ADDRESS');\n    return _claimRewards(assets, amount, msg.sender, user, to, reward);\n  }\n\n  /// @inheritdoc IRewardsController\n  function claimRewardsToSelf(\n    address[] calldata assets,\n    uint256 amount,\n    address reward\n  ) external override returns (uint256) {\n    return _claimRewards(assets, amount, msg.sender, msg.sender, msg.sender, reward);\n  }\n\n  /// @inheritdoc IRewardsController\n  function claimAllRewards(address[] calldata assets, address to)\n    external\n    override\n    returns (address[] memory rewardsList, uint256[] memory claimedAmounts)\n  {\n    require(to != address(0), 'INVALID_TO_ADDRESS');\n    return _claimAllRewards(assets, msg.sender, msg.sender, to);\n  }\n\n  /// @inheritdoc IRewardsController\n  function claimAllRewardsOnBehalf(\n    address[] calldata assets,\n    address user,\n    address to\n  )\n    external\n    override\n    onlyAuthorizedClaimers(msg.sender, user)\n    returns (address[] memory rewardsList, uint256[] memory claimedAmounts)\n  {\n    require(user != address(0), 'INVALID_USER_ADDRESS');\n    require(to != address(0), 'INVALID_TO_ADDRESS');\n    return _claimAllRewards(assets, msg.sender, user, to);\n  }\n\n  /// @inheritdoc IRewardsController\n  function claimAllRewardsToSelf(address[] calldata assets)\n    external\n    override\n    returns (address[] memory rewardsList, uint256[] memory claimedAmounts)\n  {\n    return _claimAllRewards(assets, msg.sender, msg.sender, msg.sender);\n  }\n\n  /// @inheritdoc IRewardsController\n  function setClaimer(address user, address caller) external override onlyEmissionManager {\n    _authorizedClaimers[user] = caller;\n    emit ClaimerSet(user, caller);\n  }\n\n  /**\n   * @dev Get user balances and total supply of all the assets specified by the assets parameter\n   * @param assets List of assets to retrieve user balance and total supply\n   * @param user Address of the user\n   * @return userAssetBalances contains a list of structs with user balance and total supply of the given assets\n   */\n  function _getUserAssetBalances(address[] calldata assets, address user)\n    internal\n    view\n    override\n    returns (RewardsDataTypes.UserAssetBalance[] memory userAssetBalances)\n  {\n    userAssetBalances = new RewardsDataTypes.UserAssetBalance[](assets.length);\n    for (uint256 i = 0; i < assets.length; i++) {\n      userAssetBalances[i].asset = assets[i];\n      (userAssetBalances[i].userBalance, userAssetBalances[i].totalSupply) = IScaledBalanceToken(\n        assets[i]\n      ).getScaledUserBalanceAndSupply(user);\n    }\n    return userAssetBalances;\n  }\n\n  /**\n   * @dev Claims one type of reward for a user on behalf, on all the assets of the pool, accumulating the pending rewards.\n   * @param assets List of assets to check eligible distributions before claiming rewards\n   * @param amount Amount of rewards to claim\n   * @param claimer Address of the claimer who claims rewards on behalf of user\n   * @param user Address to check and claim rewards\n   * @param to Address that will be receiving the rewards\n   * @param reward Address of the reward token\n   * @return Rewards claimed\n   **/\n  function _claimRewards(\n    address[] calldata assets,\n    uint256 amount,\n    address claimer,\n    address user,\n    address to,\n    address reward\n  ) internal returns (uint256) {\n    if (amount == 0) {\n      return 0;\n    }\n    uint256 totalRewards;\n\n    _updateDataMultiple(user, _getUserAssetBalances(assets, user));\n    for (uint256 i = 0; i < assets.length; i++) {\n      address asset = assets[i];\n      totalRewards += _assets[asset].rewards[reward].usersData[user].accrued;\n\n      if (totalRewards <= amount) {\n        _assets[asset].rewards[reward].usersData[user].accrued = 0;\n      } else {\n        uint256 difference = totalRewards - amount;\n        totalRewards -= difference;\n        _assets[asset].rewards[reward].usersData[user].accrued = difference.toUint128();\n        break;\n      }\n    }\n\n    if (totalRewards == 0) {\n      return 0;\n    }\n\n    _transferRewards(to, reward, totalRewards);\n    emit RewardsClaimed(user, reward, to, claimer, totalRewards);\n\n    return totalRewards;\n  }\n\n  /**\n   * @dev Claims one type of reward for a user on behalf, on all the assets of the pool, accumulating the pending rewards.\n   * @param assets List of assets to check eligible distributions before claiming rewards\n   * @param claimer Address of the claimer on behalf of user\n   * @param user Address to check and claim rewards\n   * @param to Address that will be receiving the rewards\n   * @return\n   *   rewardsList List of reward addresses\n   *   claimedAmount List of claimed amounts, follows \"rewardsList\" items order\n   **/\n  function _claimAllRewards(\n    address[] calldata assets,\n    address claimer,\n    address user,\n    address to\n  ) internal returns (address[] memory rewardsList, uint256[] memory claimedAmounts) {\n    uint256 rewardsListLength = _rewardsList.length;\n    rewardsList = new address[](rewardsListLength);\n    claimedAmounts = new uint256[](rewardsListLength);\n\n    _updateDataMultiple(user, _getUserAssetBalances(assets, user));\n\n    for (uint256 i = 0; i < assets.length; i++) {\n      address asset = assets[i];\n      for (uint256 j = 0; j < rewardsListLength; j++) {\n        if (rewardsList[j] == address(0)) {\n          rewardsList[j] = _rewardsList[j];\n        }\n        uint256 rewardAmount = _assets[asset].rewards[rewardsList[j]].usersData[user].accrued;\n        if (rewardAmount != 0) {\n          claimedAmounts[j] += rewardAmount;\n          _assets[asset].rewards[rewardsList[j]].usersData[user].accrued = 0;\n        }\n      }\n    }\n    for (uint256 i = 0; i < rewardsListLength; i++) {\n      _transferRewards(to, rewardsList[i], claimedAmounts[i]);\n      emit RewardsClaimed(user, rewardsList[i], to, claimer, claimedAmounts[i]);\n    }\n    return (rewardsList, claimedAmounts);\n  }\n\n  /**\n   * @dev Function to transfer rewards to the desired account using delegatecall and\n   * @param to Account address to send the rewards\n   * @param reward Address of the reward token\n   * @param amount Amount of rewards to transfer\n   */\n  function _transferRewards(\n    address to,\n    address reward,\n    uint256 amount\n  ) internal {\n    ITransferStrategyBase transferStrategy = _transferStrategy[reward];\n\n    bool success = transferStrategy.performTransfer(to, reward, amount);\n\n    require(success == true, 'TRANSFER_ERROR');\n  }\n\n  /**\n   * @dev Returns true if `account` is a contract.\n   * @param account The address of the account\n   * @return bool, true if contract, false otherwise\n   */\n  function _isContract(address account) internal view returns (bool) {\n    // This method relies on extcodesize, which returns 0 for contracts in\n    // construction, since the code is only stored at the end of the\n    // constructor execution.\n\n    uint256 size;\n    // solhint-disable-next-line no-inline-assembly\n    assembly {\n      size := extcodesize(account)\n    }\n    return size > 0;\n  }\n\n  /**\n   * @dev Internal function to call the optional install hook at the TransferStrategy\n   * @param reward The address of the reward token\n   * @param transferStrategy The address of the reward TransferStrategy\n   */\n  function _installTransferStrategy(address reward, ITransferStrategyBase transferStrategy)\n    internal\n  {\n    require(address(transferStrategy) != address(0), 'STRATEGY_CAN_NOT_BE_ZERO');\n    require(_isContract(address(transferStrategy)) == true, 'STRATEGY_MUST_BE_CONTRACT');\n\n    _transferStrategy[reward] = transferStrategy;\n\n    emit TransferStrategyInstalled(reward, address(transferStrategy));\n  }\n\n  /**\n   * @dev Update the Price Oracle of a reward token. The Price Oracle must follow Chainlink IEACAggregatorProxy interface.\n   * @notice The Price Oracle of a reward is used for displaying correct data about the incentives at the UI frontend.\n   * @param reward The address of the reward token\n   * @param rewardOracle The address of the price oracle\n   */\n\n  function _setRewardOracle(address reward, IEACAggregatorProxy rewardOracle) internal {\n    require(rewardOracle.latestAnswer() > 0, 'ORACLE_MUST_RETURN_PRICE');\n    _rewardOracle[reward] = rewardOracle;\n    emit RewardOracleUpdated(reward, address(rewardOracle));\n  }\n}\n"
      },
      "node_modules/@aave/core-v3/contracts/protocol/libraries/aave-upgradeability/VersionedInitializable.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0\npragma solidity 0.8.10;\n\n/**\n * @title VersionedInitializable\n * @author Aave, inspired by the OpenZeppelin Initializable contract\n * @notice Helper contract to implement initializer functions. To use it, replace\n * the constructor with a function that has the `initializer` modifier.\n * @dev WARNING: Unlike constructors, initializer functions must be manually\n * invoked. This applies both to deploying an Initializable contract, as well\n * as extending an Initializable contract via inheritance.\n * WARNING: When used with inheritance, manual care must be taken to not invoke\n * a parent initializer twice, or ensure that all initializers are idempotent,\n * because this is not dealt with automatically as with constructors.\n */\nabstract contract VersionedInitializable {\n  /**\n   * @dev Indicates that the contract has been initialized.\n   */\n  uint256 private lastInitializedRevision = 0;\n\n  /**\n   * @dev Indicates that the contract is in the process of being initialized.\n   */\n  bool private initializing;\n\n  /**\n   * @dev Modifier to use in the initializer function of a contract.\n   */\n  modifier initializer() {\n    uint256 revision = getRevision();\n    require(\n      initializing || isConstructor() || revision > lastInitializedRevision,\n      'Contract instance has already been initialized'\n    );\n\n    bool isTopLevelCall = !initializing;\n    if (isTopLevelCall) {\n      initializing = true;\n      lastInitializedRevision = revision;\n    }\n\n    _;\n\n    if (isTopLevelCall) {\n      initializing = false;\n    }\n  }\n\n  /**\n   * @notice Returns the revision number of the contract\n   * @dev Needs to be defined in the inherited class as a constant.\n   * @return The revision number\n   **/\n  function getRevision() internal pure virtual returns (uint256);\n\n  /**\n   * @notice Returns true if and only if the function is running in the constructor\n   * @return True if the function is running in the constructor\n   **/\n  function isConstructor() private view returns (bool) {\n    // extcodesize checks the size of the code stored in an address, and\n    // address returns the current address. Since the code is still not\n    // deployed when running a constructor, any checks on its code size will\n    // yield zero, making it an effective way to detect if a contract is\n    // under construction or not.\n    uint256 cs;\n    //solium-disable-next-line\n    assembly {\n      cs := extcodesize(address())\n    }\n    return cs == 0;\n  }\n\n  // Reserved storage space to allow for layout changes in the future.\n  uint256[50] private ______gap;\n}\n"
      },
      "node_modules/@aave/core-v3/contracts/dependencies/openzeppelin/contracts/SafeCast.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol)\npragma solidity 0.8.10;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n  /**\n   * @dev Returns the downcasted uint224 from uint256, reverting on\n   * overflow (when the input is greater than largest uint224).\n   *\n   * Counterpart to Solidity's `uint224` operator.\n   *\n   * Requirements:\n   *\n   * - input must fit into 224 bits\n   */\n  function toUint224(uint256 value) internal pure returns (uint224) {\n    require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n    return uint224(value);\n  }\n\n  /**\n   * @dev Returns the downcasted uint128 from uint256, reverting on\n   * overflow (when the input is greater than largest uint128).\n   *\n   * Counterpart to Solidity's `uint128` operator.\n   *\n   * Requirements:\n   *\n   * - input must fit into 128 bits\n   */\n  function toUint128(uint256 value) internal pure returns (uint128) {\n    require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n    return uint128(value);\n  }\n\n  /**\n   * @dev Returns the downcasted uint96 from uint256, reverting on\n   * overflow (when the input is greater than largest uint96).\n   *\n   * Counterpart to Solidity's `uint96` operator.\n   *\n   * Requirements:\n   *\n   * - input must fit into 96 bits\n   */\n  function toUint96(uint256 value) internal pure returns (uint96) {\n    require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n    return uint96(value);\n  }\n\n  /**\n   * @dev Returns the downcasted uint64 from uint256, reverting on\n   * overflow (when the input is greater than largest uint64).\n   *\n   * Counterpart to Solidity's `uint64` operator.\n   *\n   * Requirements:\n   *\n   * - input must fit into 64 bits\n   */\n  function toUint64(uint256 value) internal pure returns (uint64) {\n    require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n    return uint64(value);\n  }\n\n  /**\n   * @dev Returns the downcasted uint32 from uint256, reverting on\n   * overflow (when the input is greater than largest uint32).\n   *\n   * Counterpart to Solidity's `uint32` operator.\n   *\n   * Requirements:\n   *\n   * - input must fit into 32 bits\n   */\n  function toUint32(uint256 value) internal pure returns (uint32) {\n    require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n    return uint32(value);\n  }\n\n  /**\n   * @dev Returns the downcasted uint16 from uint256, reverting on\n   * overflow (when the input is greater than largest uint16).\n   *\n   * Counterpart to Solidity's `uint16` operator.\n   *\n   * Requirements:\n   *\n   * - input must fit into 16 bits\n   */\n  function toUint16(uint256 value) internal pure returns (uint16) {\n    require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n    return uint16(value);\n  }\n\n  /**\n   * @dev Returns the downcasted uint8 from uint256, reverting on\n   * overflow (when the input is greater than largest uint8).\n   *\n   * Counterpart to Solidity's `uint8` operator.\n   *\n   * Requirements:\n   *\n   * - input must fit into 8 bits.\n   */\n  function toUint8(uint256 value) internal pure returns (uint8) {\n    require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n    return uint8(value);\n  }\n\n  /**\n   * @dev Converts a signed int256 into an unsigned uint256.\n   *\n   * Requirements:\n   *\n   * - input must be greater than or equal to 0.\n   */\n  function toUint256(int256 value) internal pure returns (uint256) {\n    require(value >= 0, 'SafeCast: value must be positive');\n    return uint256(value);\n  }\n\n  /**\n   * @dev Returns the downcasted int128 from int256, reverting on\n   * overflow (when the input is less than smallest int128 or\n   * greater than largest int128).\n   *\n   * Counterpart to Solidity's `int128` operator.\n   *\n   * Requirements:\n   *\n   * - input must fit into 128 bits\n   *\n   * _Available since v3.1._\n   */\n  function toInt128(int256 value) internal pure returns (int128) {\n    require(\n      value >= type(int128).min && value <= type(int128).max,\n      \"SafeCast: value doesn't fit in 128 bits\"\n    );\n    return int128(value);\n  }\n\n  /**\n   * @dev Returns the downcasted int64 from int256, reverting on\n   * overflow (when the input is less than smallest int64 or\n   * greater than largest int64).\n   *\n   * Counterpart to Solidity's `int64` operator.\n   *\n   * Requirements:\n   *\n   * - input must fit into 64 bits\n   *\n   * _Available since v3.1._\n   */\n  function toInt64(int256 value) internal pure returns (int64) {\n    require(\n      value >= type(int64).min && value <= type(int64).max,\n      \"SafeCast: value doesn't fit in 64 bits\"\n    );\n    return int64(value);\n  }\n\n  /**\n   * @dev Returns the downcasted int32 from int256, reverting on\n   * overflow (when the input is less than smallest int32 or\n   * greater than largest int32).\n   *\n   * Counterpart to Solidity's `int32` operator.\n   *\n   * Requirements:\n   *\n   * - input must fit into 32 bits\n   *\n   * _Available since v3.1._\n   */\n  function toInt32(int256 value) internal pure returns (int32) {\n    require(\n      value >= type(int32).min && value <= type(int32).max,\n      \"SafeCast: value doesn't fit in 32 bits\"\n    );\n    return int32(value);\n  }\n\n  /**\n   * @dev Returns the downcasted int16 from int256, reverting on\n   * overflow (when the input is less than smallest int16 or\n   * greater than largest int16).\n   *\n   * Counterpart to Solidity's `int16` operator.\n   *\n   * Requirements:\n   *\n   * - input must fit into 16 bits\n   *\n   * _Available since v3.1._\n   */\n  function toInt16(int256 value) internal pure returns (int16) {\n    require(\n      value >= type(int16).min && value <= type(int16).max,\n      \"SafeCast: value doesn't fit in 16 bits\"\n    );\n    return int16(value);\n  }\n\n  /**\n   * @dev Returns the downcasted int8 from int256, reverting on\n   * overflow (when the input is less than smallest int8 or\n   * greater than largest int8).\n   *\n   * Counterpart to Solidity's `int8` operator.\n   *\n   * Requirements:\n   *\n   * - input must fit into 8 bits.\n   *\n   * _Available since v3.1._\n   */\n  function toInt8(int256 value) internal pure returns (int8) {\n    require(\n      value >= type(int8).min && value <= type(int8).max,\n      \"SafeCast: value doesn't fit in 8 bits\"\n    );\n    return int8(value);\n  }\n\n  /**\n   * @dev Converts an unsigned uint256 into a signed int256.\n   *\n   * Requirements:\n   *\n   * - input must be less than or equal to maxInt256.\n   */\n  function toInt256(uint256 value) internal pure returns (int256) {\n    // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n    require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n    return int256(value);\n  }\n}\n"
      },
      "node_modules/@aave/core-v3/contracts/interfaces/IScaledBalanceToken.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0\npragma solidity ^0.8.0;\n\n/**\n * @title IScaledBalanceToken\n * @author Aave\n * @notice Defines the basic interface for a scaledbalance token.\n **/\ninterface IScaledBalanceToken {\n  /**\n   * @dev Emitted after the mint action\n   * @param caller The address performing the mint\n   * @param onBehalfOf The address of the user that will receive the minted scaled balance tokens\n   * @param value The amount being minted (user entered amount + balance increase from interest)\n   * @param balanceIncrease The increase in balance since the last action of the user\n   * @param index The next liquidity index of the reserve\n   **/\n  event Mint(\n    address indexed caller,\n    address indexed onBehalfOf,\n    uint256 value,\n    uint256 balanceIncrease,\n    uint256 index\n  );\n\n  /**\n   * @dev Emitted after scaled balance tokens are burned\n   * @param from The address from which the scaled tokens will be burned\n   * @param target The address that will receive the underlying, if any\n   * @param value The amount being burned (user entered amount - balance increase from interest)\n   * @param balanceIncrease The increase in balance since the last action of the user\n   * @param index The next liquidity index of the reserve\n   **/\n  event Burn(\n    address indexed from,\n    address indexed target,\n    uint256 value,\n    uint256 balanceIncrease,\n    uint256 index\n  );\n\n  /**\n   * @notice Returns the scaled balance of the user.\n   * @dev The scaled balance is the sum of all the updated stored balance divided by the reserve's liquidity index\n   * at the moment of the update\n   * @param user The user whose balance is calculated\n   * @return The scaled balance of the user\n   **/\n  function scaledBalanceOf(address user) external view returns (uint256);\n\n  /**\n   * @notice Returns the scaled balance of the user and the scaled total supply.\n   * @param user The address of the user\n   * @return The scaled balance of the user\n   * @return The scaled total supply\n   **/\n  function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256);\n\n  /**\n   * @notice Returns the scaled total supply of the scaled balance token. Represents sum(debt/index)\n   * @return The scaled total supply\n   **/\n  function scaledTotalSupply() external view returns (uint256);\n\n  /**\n   * @notice Returns last index interest was accrued to the user's balance\n   * @param user The address of the user\n   * @return The last index interest was accrued to the user's balance, expressed in ray\n   **/\n  function getPreviousIndex(address user) external view returns (uint256);\n}\n"
      },
      "src/periphery/rewards/RewardsDistributor.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.10;\n\nimport {IScaledBalanceToken} from '@aave/core-v3/contracts/interfaces/IScaledBalanceToken.sol';\nimport {IERC20Detailed} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20Detailed.sol';\nimport {SafeCast} from '@aave/core-v3/contracts/dependencies/openzeppelin/contracts/SafeCast.sol';\nimport {IRewardsDistributor} from './interfaces/IRewardsDistributor.sol';\nimport {RewardsDataTypes} from './libraries/RewardsDataTypes.sol';\n\n/**\n * @title RewardsDistributor\n * @notice Accounting contract to manage multiple staking distributions with multiple rewards\n * @author Aave\n **/\nabstract contract RewardsDistributor is IRewardsDistributor {\n  using SafeCast for uint256;\n\n  // Manager of incentives\n  address public immutable EMISSION_MANAGER;\n  // Deprecated: This storage slot is kept for backwards compatibility purposes.\n  address internal _emissionManager;\n\n  // Map of rewarded asset addresses and their data (assetAddress => assetData)\n  mapping(address => RewardsDataTypes.AssetData) internal _assets;\n\n  // Map of reward assets (rewardAddress => enabled)\n  mapping(address => bool) internal _isRewardEnabled;\n\n  // Rewards list\n  address[] internal _rewardsList;\n\n  // Assets list\n  address[] internal _assetsList;\n\n  modifier onlyEmissionManager() {\n    require(msg.sender == EMISSION_MANAGER, 'ONLY_EMISSION_MANAGER');\n    _;\n  }\n\n  constructor(address emissionManager) {\n    EMISSION_MANAGER = emissionManager;\n  }\n\n  /// @inheritdoc IRewardsDistributor\n  function getRewardsData(address asset, address reward)\n    public\n    view\n    override\n    returns (\n      uint256,\n      uint256,\n      uint256,\n      uint256\n    )\n  {\n    return (\n      _assets[asset].rewards[reward].index,\n      _assets[asset].rewards[reward].emissionPerSecond,\n      _assets[asset].rewards[reward].lastUpdateTimestamp,\n      _assets[asset].rewards[reward].distributionEnd\n    );\n  }\n\n  /// @inheritdoc IRewardsDistributor\n  function getAssetIndex(address asset, address reward)\n    external\n    view\n    override\n    returns (uint256, uint256)\n  {\n    RewardsDataTypes.RewardData storage rewardData = _assets[asset].rewards[reward];\n    return\n      _getAssetIndex(\n        rewardData,\n        IScaledBalanceToken(asset).scaledTotalSupply(),\n        10**_assets[asset].decimals\n      );\n  }\n\n  /// @inheritdoc IRewardsDistributor\n  function getDistributionEnd(address asset, address reward)\n    external\n    view\n    override\n    returns (uint256)\n  {\n    return _assets[asset].rewards[reward].distributionEnd;\n  }\n\n  /// @inheritdoc IRewardsDistributor\n  function getRewardsByAsset(address asset) external view override returns (address[] memory) {\n    uint128 rewardsCount = _assets[asset].availableRewardsCount;\n    address[] memory availableRewards = new address[](rewardsCount);\n\n    for (uint128 i = 0; i < rewardsCount; i++) {\n      availableRewards[i] = _assets[asset].availableRewards[i];\n    }\n    return availableRewards;\n  }\n\n  /// @inheritdoc IRewardsDistributor\n  function getRewardsList() external view override returns (address[] memory) {\n    return _rewardsList;\n  }\n\n  /// @inheritdoc IRewardsDistributor\n  function getUserAssetIndex(\n    address user,\n    address asset,\n    address reward\n  ) public view override returns (uint256) {\n    return _assets[asset].rewards[reward].usersData[user].index;\n  }\n\n  /// @inheritdoc IRewardsDistributor\n  function getUserAccruedRewards(address user, address reward)\n    external\n    view\n    override\n    returns (uint256)\n  {\n    uint256 totalAccrued;\n    for (uint256 i = 0; i < _assetsList.length; i++) {\n      totalAccrued += _assets[_assetsList[i]].rewards[reward].usersData[user].accrued;\n    }\n\n    return totalAccrued;\n  }\n\n  /// @inheritdoc IRewardsDistributor\n  function getUserRewards(\n    address[] calldata assets,\n    address user,\n    address reward\n  ) external view override returns (uint256) {\n    return _getUserReward(user, reward, _getUserAssetBalances(assets, user));\n  }\n\n  /// @inheritdoc IRewardsDistributor\n  function getAllUserRewards(address[] calldata assets, address user)\n    external\n    view\n    override\n    returns (address[] memory rewardsList, uint256[] memory unclaimedAmounts)\n  {\n    RewardsDataTypes.UserAssetBalance[] memory userAssetBalances = _getUserAssetBalances(\n      assets,\n      user\n    );\n    rewardsList = new address[](_rewardsList.length);\n    unclaimedAmounts = new uint256[](rewardsList.length);\n\n    // Add unrealized rewards from user to unclaimedRewards\n    for (uint256 i = 0; i < userAssetBalances.length; i++) {\n      for (uint256 r = 0; r < rewardsList.length; r++) {\n        rewardsList[r] = _rewardsList[r];\n        unclaimedAmounts[r] += _assets[userAssetBalances[i].asset]\n          .rewards[rewardsList[r]]\n          .usersData[user]\n          .accrued;\n\n        if (userAssetBalances[i].userBalance == 0) {\n          continue;\n        }\n        unclaimedAmounts[r] += _getPendingRewards(user, rewardsList[r], userAssetBalances[i]);\n      }\n    }\n    return (rewardsList, unclaimedAmounts);\n  }\n\n  /// @inheritdoc IRewardsDistributor\n  function setDistributionEnd(\n    address asset,\n    address reward,\n    uint32 newDistributionEnd\n  ) external override onlyEmissionManager {\n    uint256 oldDistributionEnd = _assets[asset].rewards[reward].distributionEnd;\n    _assets[asset].rewards[reward].distributionEnd = newDistributionEnd;\n\n    emit AssetConfigUpdated(\n      asset,\n      reward,\n      _assets[asset].rewards[reward].emissionPerSecond,\n      _assets[asset].rewards[reward].emissionPerSecond,\n      oldDistributionEnd,\n      newDistributionEnd,\n      _assets[asset].rewards[reward].index\n    );\n  }\n\n  /// @inheritdoc IRewardsDistributor\n  function setEmissionPerSecond(\n    address asset,\n    address[] calldata rewards,\n    uint88[] calldata newEmissionsPerSecond\n  ) external override onlyEmissionManager {\n    require(rewards.length == newEmissionsPerSecond.length, 'INVALID_INPUT');\n    for (uint256 i = 0; i < rewards.length; i++) {\n      RewardsDataTypes.AssetData storage assetConfig = _assets[asset];\n      RewardsDataTypes.RewardData storage rewardConfig = _assets[asset].rewards[rewards[i]];\n      uint256 decimals = assetConfig.decimals;\n      require(\n        decimals != 0 && rewardConfig.lastUpdateTimestamp != 0,\n        'DISTRIBUTION_DOES_NOT_EXIST'\n      );\n\n      (uint256 newIndex, ) = _updateRewardData(\n        rewardConfig,\n        IScaledBalanceToken(asset).scaledTotalSupply(),\n        10**decimals\n      );\n\n      uint256 oldEmissionPerSecond = rewardConfig.emissionPerSecond;\n      rewardConfig.emissionPerSecond = newEmissionsPerSecond[i];\n\n      emit AssetConfigUpdated(\n        asset,\n        rewards[i],\n        oldEmissionPerSecond,\n        newEmissionsPerSecond[i],\n        rewardConfig.distributionEnd,\n        rewardConfig.distributionEnd,\n        newIndex\n      );\n    }\n  }\n\n  /**\n   * @dev Configure the _assets for a specific emission\n   * @param rewardsInput The array of each asset configuration\n   **/\n  function _configureAssets(RewardsDataTypes.RewardsConfigInput[] memory rewardsInput) internal {\n    for (uint256 i = 0; i < rewardsInput.length; i++) {\n      if (_assets[rewardsInput[i].asset].decimals == 0) {\n        //never initialized before, adding to the list of assets\n        _assetsList.push(rewardsInput[i].asset);\n      }\n\n      uint256 decimals = _assets[rewardsInput[i].asset].decimals = IERC20Detailed(\n        rewardsInput[i].asset\n      ).decimals();\n\n      RewardsDataTypes.RewardData storage rewardConfig = _assets[rewardsInput[i].asset].rewards[\n        rewardsInput[i].reward\n      ];\n\n      // Add reward address to asset available rewards if latestUpdateTimestamp is zero\n      if (rewardConfig.lastUpdateTimestamp == 0) {\n        _assets[rewardsInput[i].asset].availableRewards[\n          _assets[rewardsInput[i].asset].availableRewardsCount\n        ] = rewardsInput[i].reward;\n        _assets[rewardsInput[i].asset].availableRewardsCount++;\n      }\n\n      // Add reward address to global rewards list if still not enabled\n      if (_isRewardEnabled[rewardsInput[i].reward] == false) {\n        _isRewardEnabled[rewardsInput[i].reward] = true;\n        _rewardsList.push(rewardsInput[i].reward);\n      }\n\n      // Due emissions is still zero, updates only latestUpdateTimestamp\n      (uint256 newIndex, ) = _updateRewardData(\n        rewardConfig,\n        rewardsInput[i].totalSupply,\n        10**decimals\n      );\n\n      // Configure emission and distribution end of the reward per asset\n      uint88 oldEmissionsPerSecond = rewardConfig.emissionPerSecond;\n      uint32 oldDistributionEnd = rewardConfig.distributionEnd;\n      rewardConfig.emissionPerSecond = rewardsInput[i].emissionPerSecond;\n      rewardConfig.distributionEnd = rewardsInput[i].distributionEnd;\n\n      emit AssetConfigUpdated(\n        rewardsInput[i].asset,\n        rewardsInput[i].reward,\n        oldEmissionsPerSecond,\n        rewardsInput[i].emissionPerSecond,\n        oldDistributionEnd,\n        rewardsInput[i].distributionEnd,\n        newIndex\n      );\n    }\n  }\n\n  /**\n   * @dev Updates the state of the distribution for the specified reward\n   * @param rewardData Storage pointer to the distribution reward config\n   * @param totalSupply Current total of underlying assets for this distribution\n   * @param assetUnit One unit of asset (10**decimals)\n   * @return The new distribution index\n   * @return True if the index was updated, false otherwise\n   **/\n  function _updateRewardData(\n    RewardsDataTypes.RewardData storage rewardData,\n    uint256 totalSupply,\n    uint256 assetUnit\n  ) internal returns (uint256, bool) {\n    (uint256 oldIndex, uint256 newIndex) = _getAssetIndex(rewardData, totalSupply, assetUnit);\n    bool indexUpdated;\n    if (newIndex != oldIndex) {\n      require(newIndex <= type(uint104).max, 'INDEX_OVERFLOW');\n      indexUpdated = true;\n\n      //optimization: storing one after another saves one SSTORE\n      rewardData.index = uint104(newIndex);\n      rewardData.lastUpdateTimestamp = block.timestamp.toUint32();\n    } else {\n      rewardData.lastUpdateTimestamp = block.timestamp.toUint32();\n    }\n\n    return (newIndex, indexUpdated);\n  }\n\n  /**\n   * @dev Updates the state of the distribution for the specific user\n   * @param rewardData Storage pointer to the distribution reward config\n   * @param user The address of the user\n   * @param userBalance The user balance of the asset\n   * @param newAssetIndex The new index of the asset distribution\n   * @param assetUnit One unit of asset (10**decimals)\n   * @return The rewards accrued since the last update\n   **/\n  function _updateUserData(\n    RewardsDataTypes.RewardData storage rewardData,\n    address user,\n    uint256 userBalance,\n    uint256 newAssetIndex,\n    uint256 assetUnit\n  ) internal returns (uint256, bool) {\n    uint256 userIndex = rewardData.usersData[user].index;\n    uint256 rewardsAccrued;\n    bool dataUpdated;\n    if ((dataUpdated = userIndex != newAssetIndex)) {\n      // already checked for overflow in _updateRewardData\n      rewardData.usersData[user].index = uint104(newAssetIndex);\n      if (userBalance != 0) {\n        rewardsAccrued = _getRewards(userBalance, newAssetIndex, userIndex, assetUnit);\n\n        rewardData.usersData[user].accrued += rewardsAccrued.toUint128();\n      }\n    }\n    return (rewardsAccrued, dataUpdated);\n  }\n\n  /**\n   * @dev Iterates and accrues all the rewards for asset of the specific user\n   * @param asset The address of the reference asset of the distribution\n   * @param user The user address\n   * @param userBalance The current user asset balance\n   * @param totalSupply Total supply of the asset\n   **/\n  function _updateData(\n    address asset,\n    address user,\n    uint256 userBalance,\n    uint256 totalSupply\n  ) internal {\n    uint256 assetUnit;\n    uint256 numAvailableRewards = _assets[asset].availableRewardsCount;\n    unchecked {\n      assetUnit = 10**_assets[asset].decimals;\n    }\n\n    if (numAvailableRewards == 0) {\n      return;\n    }\n    unchecked {\n      for (uint128 r = 0; r < numAvailableRewards; r++) {\n        address reward = _assets[asset].availableRewards[r];\n        RewardsDataTypes.RewardData storage rewardData = _assets[asset].rewards[reward];\n\n        (uint256 newAssetIndex, bool rewardDataUpdated) = _updateRewardData(\n          rewardData,\n          totalSupply,\n          assetUnit\n        );\n\n        (uint256 rewardsAccrued, bool userDataUpdated) = _updateUserData(\n          rewardData,\n          user,\n          userBalance,\n          newAssetIndex,\n          assetUnit\n        );\n\n        if (rewardDataUpdated || userDataUpdated) {\n          emit Accrued(asset, reward, user, newAssetIndex, newAssetIndex, rewardsAccrued);\n        }\n      }\n    }\n  }\n\n  /**\n   * @dev Accrues all the rewards of the assets specified in the userAssetBalances list\n   * @param user The address of the user\n   * @param userAssetBalances List of structs with the user balance and total supply of a set of assets\n   **/\n  function _updateDataMultiple(\n    address user,\n    RewardsDataTypes.UserAssetBalance[] memory userAssetBalances\n  ) internal {\n    for (uint256 i = 0; i < userAssetBalances.length; i++) {\n      _updateData(\n        userAssetBalances[i].asset,\n        user,\n        userAssetBalances[i].userBalance,\n        userAssetBalances[i].totalSupply\n      );\n    }\n  }\n\n  /**\n   * @dev Return the accrued unclaimed amount of a reward from a user over a list of distribution\n   * @param user The address of the user\n   * @param reward The address of the reward token\n   * @param userAssetBalances List of structs with the user balance and total supply of a set of assets\n   * @return unclaimedRewards The accrued rewards for the user until the moment\n   **/\n  function _getUserReward(\n    address user,\n    address reward,\n    RewardsDataTypes.UserAssetBalance[] memory userAssetBalances\n  ) internal view returns (uint256 unclaimedRewards) {\n    // Add unrealized rewards\n    for (uint256 i = 0; i < userAssetBalances.length; i++) {\n      if (userAssetBalances[i].userBalance == 0) {\n        unclaimedRewards += _assets[userAssetBalances[i].asset]\n          .rewards[reward]\n          .usersData[user]\n          .accrued;\n      } else {\n        unclaimedRewards +=\n          _getPendingRewards(user, reward, userAssetBalances[i]) +\n          _assets[userAssetBalances[i].asset].rewards[reward].usersData[user].accrued;\n      }\n    }\n\n    return unclaimedRewards;\n  }\n\n  /**\n   * @dev Calculates the pending (not yet accrued) rewards since the last user action\n   * @param user The address of the user\n   * @param reward The address of the reward token\n   * @param userAssetBalance struct with the user balance and total supply of the incentivized asset\n   * @return The pending rewards for the user since the last user action\n   **/\n  function _getPendingRewards(\n    address user,\n    address reward,\n    RewardsDataTypes.UserAssetBalance memory userAssetBalance\n  ) internal view returns (uint256) {\n    RewardsDataTypes.RewardData storage rewardData = _assets[userAssetBalance.asset].rewards[\n      reward\n    ];\n    uint256 assetUnit = 10**_assets[userAssetBalance.asset].decimals;\n    (, uint256 nextIndex) = _getAssetIndex(rewardData, userAssetBalance.totalSupply, assetUnit);\n\n    return\n      _getRewards(\n        userAssetBalance.userBalance,\n        nextIndex,\n        rewardData.usersData[user].index,\n        assetUnit\n      );\n  }\n\n  /**\n   * @dev Internal function for the calculation of user's rewards on a distribution\n   * @param userBalance Balance of the user asset on a distribution\n   * @param reserveIndex Current index of the distribution\n   * @param userIndex Index stored for the user, representation his staking moment\n   * @param assetUnit One unit of asset (10**decimals)\n   * @return The rewards\n   **/\n  function _getRewards(\n    uint256 userBalance,\n    uint256 reserveIndex,\n    uint256 userIndex,\n    uint256 assetUnit\n  ) internal pure returns (uint256) {\n    uint256 result = userBalance * (reserveIndex - userIndex);\n    assembly {\n      result := div(result, assetUnit)\n    }\n    return result;\n  }\n\n  /**\n   * @dev Calculates the next value of an specific distribution index, with validations\n   * @param rewardData Storage pointer to the distribution reward config\n   * @param totalSupply of the asset being rewarded\n   * @param assetUnit One unit of asset (10**decimals)\n   * @return The new index.\n   **/\n  function _getAssetIndex(\n    RewardsDataTypes.RewardData storage rewardData,\n    uint256 totalSupply,\n    uint256 assetUnit\n  ) internal view returns (uint256, uint256) {\n    uint256 oldIndex = rewardData.index;\n    uint256 distributionEnd = rewardData.distributionEnd;\n    uint256 emissionPerSecond = rewardData.emissionPerSecond;\n    uint256 lastUpdateTimestamp = rewardData.lastUpdateTimestamp;\n\n    if (\n      emissionPerSecond == 0 ||\n      totalSupply == 0 ||\n      lastUpdateTimestamp == block.timestamp ||\n      lastUpdateTimestamp >= distributionEnd\n    ) {\n      return (oldIndex, oldIndex);\n    }\n\n    uint256 currentTimestamp = block.timestamp > distributionEnd\n      ? distributionEnd\n      : block.timestamp;\n    uint256 timeDelta = currentTimestamp - lastUpdateTimestamp;\n    uint256 firstTerm = emissionPerSecond * timeDelta * assetUnit;\n    assembly {\n      firstTerm := div(firstTerm, totalSupply)\n    }\n    return (oldIndex, (firstTerm + oldIndex));\n  }\n\n  /**\n   * @dev Get user balances and total supply of all the assets specified by the assets parameter\n   * @param assets List of assets to retrieve user balance and total supply\n   * @param user Address of the user\n   * @return userAssetBalances contains a list of structs with user balance and total supply of the given assets\n   */\n  function _getUserAssetBalances(address[] calldata assets, address user)\n    internal\n    view\n    virtual\n    returns (RewardsDataTypes.UserAssetBalance[] memory userAssetBalances);\n\n  /// @inheritdoc IRewardsDistributor\n  function getAssetDecimals(address asset) external view returns (uint8) {\n    return _assets[asset].decimals;\n  }\n\n  /// @inheritdoc IRewardsDistributor\n  function getEmissionManager() external view returns (address) {\n    return EMISSION_MANAGER;\n  }\n}\n"
      },
      "src/periphery/rewards/interfaces/IRewardsController.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0\npragma solidity ^0.8.10;\n\nimport {IRewardsDistributor} from './IRewardsDistributor.sol';\nimport {ITransferStrategyBase} from './ITransferStrategyBase.sol';\nimport {IEACAggregatorProxy} from '../../misc/interfaces/IEACAggregatorProxy.sol';\nimport {RewardsDataTypes} from '../libraries/RewardsDataTypes.sol';\n\n/**\n * @title IRewardsController\n * @author Aave\n * @notice Defines the basic interface for a Rewards Controller.\n */\ninterface IRewardsController is IRewardsDistributor {\n  /**\n   * @dev Emitted when a new address is whitelisted as claimer of rewards on behalf of a user\n   * @param user The address of the user\n   * @param claimer The address of the claimer\n   */\n  event ClaimerSet(address indexed user, address indexed claimer);\n\n  /**\n   * @dev Emitted when rewards are claimed\n   * @param user The address of the user rewards has been claimed on behalf of\n   * @param reward The address of the token reward is claimed\n   * @param to The address of the receiver of the rewards\n   * @param claimer The address of the claimer\n   * @param amount The amount of rewards claimed\n   */\n  event RewardsClaimed(\n    address indexed user,\n    address indexed reward,\n    address indexed to,\n    address claimer,\n    uint256 amount\n  );\n\n  /**\n   * @dev Emitted when a transfer strategy is installed for the reward distribution\n   * @param reward The address of the token reward\n   * @param transferStrategy The address of TransferStrategy contract\n   */\n  event TransferStrategyInstalled(address indexed reward, address indexed transferStrategy);\n\n  /**\n   * @dev Emitted when the reward oracle is updated\n   * @param reward The address of the token reward\n   * @param rewardOracle The address of oracle\n   */\n  event RewardOracleUpdated(address indexed reward, address indexed rewardOracle);\n\n  /**\n   * @dev Whitelists an address to claim the rewards on behalf of another address\n   * @param user The address of the user\n   * @param claimer The address of the claimer\n   */\n  function setClaimer(address user, address claimer) external;\n\n  /**\n   * @dev Sets a TransferStrategy logic contract that determines the logic of the rewards transfer\n   * @param reward The address of the reward token\n   * @param transferStrategy The address of the TransferStrategy logic contract\n   */\n  function setTransferStrategy(address reward, ITransferStrategyBase transferStrategy) external;\n\n  /**\n   * @dev Sets an Aave Oracle contract to enforce rewards with a source of value.\n   * @notice At the moment of reward configuration, the Incentives Controller performs\n   * a check to see if the reward asset oracle is compatible with IEACAggregator proxy.\n   * This check is enforced for integrators to be able to show incentives at\n   * the current Aave UI without the need to setup an external price registry\n   * @param reward The address of the reward to set the price aggregator\n   * @param rewardOracle The address of price aggregator that follows IEACAggregatorProxy interface\n   */\n  function setRewardOracle(address reward, IEACAggregatorProxy rewardOracle) external;\n\n  /**\n   * @dev Get the price aggregator oracle address\n   * @param reward The address of the reward\n   * @return The price oracle of the reward\n   */\n  function getRewardOracle(address reward) external view returns (address);\n\n  /**\n   * @dev Returns the whitelisted claimer for a certain address (0x0 if not set)\n   * @param user The address of the user\n   * @return The claimer address\n   */\n  function getClaimer(address user) external view returns (address);\n\n  /**\n   * @dev Returns the Transfer Strategy implementation contract address being used for a reward address\n   * @param reward The address of the reward\n   * @return The address of the TransferStrategy contract\n   */\n  function getTransferStrategy(address reward) external view returns (address);\n\n  /**\n   * @dev Configure assets to incentivize with an emission of rewards per second until the end of distribution.\n   * @param config The assets configuration input, the list of structs contains the following fields:\n   *   uint104 emissionPerSecond: The emission per second following rewards unit decimals.\n   *   uint256 totalSupply: The total supply of the asset to incentivize\n   *   uint40 distributionEnd: The end of the distribution of the incentives for an asset\n   *   address asset: The asset address to incentivize\n   *   address reward: The reward token address\n   *   ITransferStrategy transferStrategy: The TransferStrategy address with the install hook and claim logic.\n   *   IEACAggregatorProxy rewardOracle: The Price Oracle of a reward to visualize the incentives at the UI Frontend.\n   *                                     Must follow Chainlink Aggregator IEACAggregatorProxy interface to be compatible.\n   */\n  function configureAssets(RewardsDataTypes.RewardsConfigInput[] memory config) external;\n\n  /**\n   * @dev Called by the corresponding asset on transfer hook in order to update the rewards distribution.\n   * @dev The units of `totalSupply` and `userBalance` should be the same.\n   * @param user The address of the user whose asset balance has changed\n   * @param totalSupply The total supply of the asset prior to user balance change\n   * @param userBalance The previous user balance prior to balance change\n   **/\n  function handleAction(\n    address user,\n    uint256 totalSupply,\n    uint256 userBalance\n  ) external;\n\n  /**\n   * @dev Claims reward for a user to the desired address, on all the assets of the pool, accumulating the pending rewards\n   * @param assets List of assets to check eligible distributions before claiming rewards\n   * @param amount The amount of rewards to claim\n   * @param to The address that will be receiving the rewards\n   * @param reward The address of the reward token\n   * @return The amount of rewards claimed\n   **/\n  function claimRewards(\n    address[] calldata assets,\n    uint256 amount,\n    address to,\n    address reward\n  ) external returns (uint256);\n\n  /**\n   * @dev Claims reward for a user on behalf, on all the assets of the pool, accumulating the pending rewards. The\n   * caller must be whitelisted via \"allowClaimOnBehalf\" function by the RewardsAdmin role manager\n   * @param assets The list of assets to check eligible distributions before claiming rewards\n   * @param amount The amount of rewards to claim\n   * @param user The address to check and claim rewards\n   * @param to The address that will be receiving the rewards\n   * @param reward The address of the reward token\n   * @return The amount of rewards claimed\n   **/\n  function claimRewardsOnBehalf(\n    address[] calldata assets,\n    uint256 amount,\n    address user,\n    address to,\n    address reward\n  ) external returns (uint256);\n\n  /**\n   * @dev Claims reward for msg.sender, on all the assets of the pool, accumulating the pending rewards\n   * @param assets The list of assets to check eligible distributions before claiming rewards\n   * @param amount The amount of rewards to claim\n   * @param reward The address of the reward token\n   * @return The amount of rewards claimed\n   **/\n  function claimRewardsToSelf(\n    address[] calldata assets,\n    uint256 amount,\n    address reward\n  ) external returns (uint256);\n\n  /**\n   * @dev Claims all rewards for a user to the desired address, on all the assets of the pool, accumulating the pending rewards\n   * @param assets The list of assets to check eligible distributions before claiming rewards\n   * @param to The address that will be receiving the rewards\n   * @return rewardsList List of addresses of the reward tokens\n   * @return claimedAmounts List that contains the claimed amount per reward, following same order as \"rewardList\"\n   **/\n  function claimAllRewards(address[] calldata assets, address to)\n    external\n    returns (address[] memory rewardsList, uint256[] memory claimedAmounts);\n\n  /**\n   * @dev Claims all rewards for a user on behalf, on all the assets of the pool, accumulating the pending rewards. The caller must\n   * be whitelisted via \"allowClaimOnBehalf\" function by the RewardsAdmin role manager\n   * @param assets The list of assets to check eligible distributions before claiming rewards\n   * @param user The address to check and claim rewards\n   * @param to The address that will be receiving the rewards\n   * @return rewardsList List of addresses of the reward tokens\n   * @return claimedAmounts List that contains the claimed amount per reward, following same order as \"rewardsList\"\n   **/\n  function claimAllRewardsOnBehalf(\n    address[] calldata assets,\n    address user,\n    address to\n  ) external returns (address[] memory rewardsList, uint256[] memory claimedAmounts);\n\n  /**\n   * @dev Claims all reward for msg.sender, on all the assets of the pool, accumulating the pending rewards\n   * @param assets The list of assets to check eligible distributions before claiming rewards\n   * @return rewardsList List of addresses of the reward tokens\n   * @return claimedAmounts List that contains the claimed amount per reward, following same order as \"rewardsList\"\n   **/\n  function claimAllRewardsToSelf(address[] calldata assets)\n    external\n    returns (address[] memory rewardsList, uint256[] memory claimedAmounts);\n}\n"
      },
      "src/periphery/rewards/interfaces/ITransferStrategyBase.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0\npragma solidity ^0.8.10;\n\ninterface ITransferStrategyBase {\n  event EmergencyWithdrawal(\n    address indexed caller,\n    address indexed token,\n    address indexed to,\n    uint256 amount\n  );\n\n  /**\n   * @dev Perform custom transfer logic via delegate call from source contract to a TransferStrategy implementation\n   * @param to Account to transfer rewards\n   * @param reward Address of the reward token\n   * @param amount Amount to transfer to the \"to\" address parameter\n   * @return Returns true bool if transfer logic succeeds\n   */\n  function performTransfer(\n    address to,\n    address reward,\n    uint256 amount\n  ) external returns (bool);\n\n  /**\n   * @return Returns the address of the Incentives Controller\n   */\n  function getIncentivesController() external view returns (address);\n\n  /**\n   * @return Returns the address of the Rewards admin\n   */\n  function getRewardsAdmin() external view returns (address);\n\n  /**\n   * @dev Perform an emergency token withdrawal only callable by the Rewards admin\n   * @param token Address of the token to withdraw funds from this contract\n   * @param to Address of the recipient of the withdrawal\n   * @param amount Amount of the withdrawal\n   */\n  function emergencyWithdrawal(\n    address token,\n    address to,\n    uint256 amount\n  ) external;\n}\n"
      },
      "src/periphery/rewards/libraries/RewardsDataTypes.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0\npragma solidity ^0.8.10;\n\nimport {ITransferStrategyBase} from '../interfaces/ITransferStrategyBase.sol';\nimport {IEACAggregatorProxy} from '../../misc/interfaces/IEACAggregatorProxy.sol';\n\nlibrary RewardsDataTypes {\n  struct RewardsConfigInput {\n    uint88 emissionPerSecond;\n    uint256 totalSupply;\n    uint32 distributionEnd;\n    address asset;\n    address reward;\n    ITransferStrategyBase transferStrategy;\n    IEACAggregatorProxy rewardOracle;\n  }\n\n  struct UserAssetBalance {\n    address asset;\n    uint256 userBalance;\n    uint256 totalSupply;\n  }\n\n  struct UserData {\n    // Liquidity index of the reward distribution for the user\n    uint104 index;\n    // Amount of accrued rewards for the user since last user index update\n    uint128 accrued;\n  }\n\n  struct RewardData {\n    // Liquidity index of the reward distribution\n    uint104 index;\n    // Amount of reward tokens distributed per second\n    uint88 emissionPerSecond;\n    // Timestamp of the last reward index update\n    uint32 lastUpdateTimestamp;\n    // The end of the distribution of rewards (in seconds)\n    uint32 distributionEnd;\n    // Map of user addresses and their rewards data (userAddress => userData)\n    mapping(address => UserData) usersData;\n  }\n\n  struct AssetData {\n    // Map of reward token addresses and their data (rewardTokenAddress => rewardData)\n    mapping(address => RewardData) rewards;\n    // List of reward token addresses for the asset\n    mapping(uint128 => address) availableRewards;\n    // Count of reward tokens for the asset\n    uint128 availableRewardsCount;\n    // Number of decimals of the asset\n    uint8 decimals;\n  }\n}\n"
      },
      "src/periphery/misc/interfaces/IEACAggregatorProxy.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0\npragma solidity ^0.8.10;\n\ninterface IEACAggregatorProxy {\n  function decimals() external view returns (uint8);\n\n  function latestAnswer() external view returns (int256);\n\n  function latestTimestamp() external view returns (uint256);\n\n  function latestRound() external view returns (uint256);\n\n  function getAnswer(uint256 roundId) external view returns (int256);\n\n  function getTimestamp(uint256 roundId) external view returns (uint256);\n\n  function aggregator() external view returns (address);\n\n  function getSubTokens() external view returns(address[] memory);\n\n  function getTokenType() external view returns(uint256);\n\n  event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 timestamp);\n  event NewRound(uint256 indexed roundId, address indexed startedBy);\n}\n"
      },
      "node_modules/@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20Detailed.sol": {
        "content": "// SPDX-License-Identifier: agpl-3.0\npragma solidity 0.8.10;\n\nimport {IERC20} from './IERC20.sol';\n\ninterface IERC20Detailed is IERC20 {\n  function name() external view returns (string memory);\n\n  function symbol() external view returns (string memory);\n\n  function decimals() external view returns (uint8);\n}\n"
      },
      "src/periphery/rewards/interfaces/IRewardsDistributor.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0\npragma solidity ^0.8.10;\n\n/**\n * @title IRewardsDistributor\n * @author Aave\n * @notice Defines the basic interface for a Rewards Distributor.\n */\ninterface IRewardsDistributor {\n  /**\n   * @dev Emitted when the configuration of the rewards of an asset is updated.\n   * @param asset The address of the incentivized asset\n   * @param reward The address of the reward token\n   * @param oldEmission The old emissions per second value of the reward distribution\n   * @param newEmission The new emissions per second value of the reward distribution\n   * @param oldDistributionEnd The old end timestamp of the reward distribution\n   * @param newDistributionEnd The new end timestamp of the reward distribution\n   * @param assetIndex The index of the asset distribution\n   */\n  event AssetConfigUpdated(\n    address indexed asset,\n    address indexed reward,\n    uint256 oldEmission,\n    uint256 newEmission,\n    uint256 oldDistributionEnd,\n    uint256 newDistributionEnd,\n    uint256 assetIndex\n  );\n\n  /**\n   * @dev Emitted when rewards of an asset are accrued on behalf of a user.\n   * @param asset The address of the incentivized asset\n   * @param reward The address of the reward token\n   * @param user The address of the user that rewards are accrued on behalf of\n   * @param assetIndex The index of the asset distribution\n   * @param userIndex The index of the asset distribution on behalf of the user\n   * @param rewardsAccrued The amount of rewards accrued\n   */\n  event Accrued(\n    address indexed asset,\n    address indexed reward,\n    address indexed user,\n    uint256 assetIndex,\n    uint256 userIndex,\n    uint256 rewardsAccrued\n  );\n\n  /**\n   * @dev Sets the end date for the distribution\n   * @param asset The asset to incentivize\n   * @param reward The reward token that incentives the asset\n   * @param newDistributionEnd The end date of the incentivization, in unix time format\n   **/\n  function setDistributionEnd(\n    address asset,\n    address reward,\n    uint32 newDistributionEnd\n  ) external;\n\n  /**\n   * @dev Sets the emission per second of a set of reward distributions\n   * @param asset The asset is being incentivized\n   * @param rewards List of reward addresses are being distributed\n   * @param newEmissionsPerSecond List of new reward emissions per second\n   */\n  function setEmissionPerSecond(\n    address asset,\n    address[] calldata rewards,\n    uint88[] calldata newEmissionsPerSecond\n  ) external;\n\n  /**\n   * @dev Gets the end date for the distribution\n   * @param asset The incentivized asset\n   * @param reward The reward token of the incentivized asset\n   * @return The timestamp with the end of the distribution, in unix time format\n   **/\n  function getDistributionEnd(address asset, address reward) external view returns (uint256);\n\n  /**\n   * @dev Returns the index of a user on a reward distribution\n   * @param user Address of the user\n   * @param asset The incentivized asset\n   * @param reward The reward token of the incentivized asset\n   * @return The current user asset index, not including new distributions\n   **/\n  function getUserAssetIndex(\n    address user,\n    address asset,\n    address reward\n  ) external view returns (uint256);\n\n  /**\n   * @dev Returns the configuration of the distribution reward for a certain asset\n   * @param asset The incentivized asset\n   * @param reward The reward token of the incentivized asset\n   * @return The index of the asset distribution\n   * @return The emission per second of the reward distribution\n   * @return The timestamp of the last update of the index\n   * @return The timestamp of the distribution end\n   **/\n  function getRewardsData(address asset, address reward)\n    external\n    view\n    returns (\n      uint256,\n      uint256,\n      uint256,\n      uint256\n    );\n\n  /**\n   * @dev Calculates the next value of an specific distribution index, with validations.\n   * @param asset The incentivized asset\n   * @param reward The reward token of the incentivized asset\n   * @return The old index of the asset distribution\n   * @return The new index of the asset distribution\n   **/\n  function getAssetIndex(address asset, address reward) external view returns (uint256, uint256);\n\n  /**\n   * @dev Returns the list of available reward token addresses of an incentivized asset\n   * @param asset The incentivized asset\n   * @return List of rewards addresses of the input asset\n   **/\n  function getRewardsByAsset(address asset) external view returns (address[] memory);\n\n  /**\n   * @dev Returns the list of available reward addresses\n   * @return List of rewards supported in this contract\n   **/\n  function getRewardsList() external view returns (address[] memory);\n\n  /**\n   * @dev Returns the accrued rewards balance of a user, not including virtually accrued rewards since last distribution.\n   * @param user The address of the user\n   * @param reward The address of the reward token\n   * @return Unclaimed rewards, not including new distributions\n   **/\n  function getUserAccruedRewards(address user, address reward) external view returns (uint256);\n\n  /**\n   * @dev Returns a single rewards balance of a user, including virtually accrued and unrealized claimable rewards.\n   * @param assets List of incentivized assets to check eligible distributions\n   * @param user The address of the user\n   * @param reward The address of the reward token\n   * @return The rewards amount\n   **/\n  function getUserRewards(\n    address[] calldata assets,\n    address user,\n    address reward\n  ) external view returns (uint256);\n\n  /**\n   * @dev Returns a list all rewards of a user, including already accrued and unrealized claimable rewards\n   * @param assets List of incentivized assets to check eligible distributions\n   * @param user The address of the user\n   * @return The list of reward addresses\n   * @return The list of unclaimed amount of rewards\n   **/\n  function getAllUserRewards(address[] calldata assets, address user)\n    external\n    view\n    returns (address[] memory, uint256[] memory);\n\n  /**\n   * @dev Returns the decimals of an asset to calculate the distribution delta\n   * @param asset The address to retrieve decimals\n   * @return The decimals of an underlying asset\n   */\n  function getAssetDecimals(address asset) external view returns (uint8);\n\n  /**\n   * @dev Returns the address of the emission manager\n   * @return The address of the EmissionManager\n   */\n  function EMISSION_MANAGER() external view returns (address);\n\n  /**\n   * @dev Returns the address of the emission manager.\n   * Deprecated: This getter is maintained for compatibility purposes. Use the `EMISSION_MANAGER()` function instead.\n   * @return The address of the EmissionManager\n   */\n  function getEmissionManager() external view returns (address);\n}\n"
      },
      "node_modules/@aave/core-v3/contracts/dependencies/openzeppelin/contracts/IERC20.sol": {
        "content": "// SPDX-License-Identifier: agpl-3.0\npragma solidity 0.8.10;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n  /**\n   * @dev Returns the amount of tokens in existence.\n   */\n  function totalSupply() external view returns (uint256);\n\n  /**\n   * @dev Returns the amount of tokens owned by `account`.\n   */\n  function balanceOf(address account) external view returns (uint256);\n\n  /**\n   * @dev Moves `amount` tokens from the caller's account to `recipient`.\n   *\n   * Returns a boolean value indicating whether the operation succeeded.\n   *\n   * Emits a {Transfer} event.\n   */\n  function transfer(address recipient, uint256 amount) external returns (bool);\n\n  /**\n   * @dev Returns the remaining number of tokens that `spender` will be\n   * allowed to spend on behalf of `owner` through {transferFrom}. This is\n   * zero by default.\n   *\n   * This value changes when {approve} or {transferFrom} are called.\n   */\n  function allowance(address owner, address spender) external view returns (uint256);\n\n  /**\n   * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n   *\n   * Returns a boolean value indicating whether the operation succeeded.\n   *\n   * IMPORTANT: Beware that changing an allowance with this method brings the risk\n   * that someone may use both the old and the new allowance by unfortunate\n   * transaction ordering. One possible solution to mitigate this race\n   * condition is to first reduce the spender's allowance to 0 and set the\n   * desired value afterwards:\n   * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n   *\n   * Emits an {Approval} event.\n   */\n  function approve(address spender, uint256 amount) external returns (bool);\n\n  /**\n   * @dev Moves `amount` tokens from `sender` to `recipient` using the\n   * allowance mechanism. `amount` is then deducted from the caller's\n   * allowance.\n   *\n   * Returns a boolean value indicating whether the operation succeeded.\n   *\n   * Emits a {Transfer} event.\n   */\n  function transferFrom(\n    address sender,\n    address recipient,\n    uint256 amount\n  ) external returns (bool);\n\n  /**\n   * @dev Emitted when `value` tokens are moved from one account (`from`) to\n   * another (`to`).\n   *\n   * Note that `value` may be zero.\n   */\n  event Transfer(address indexed from, address indexed to, uint256 value);\n\n  /**\n   * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n   * a call to {approve}. `value` is the new allowance.\n   */\n  event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "forge-std/=lib/forge-std/src/",
        "test/=test/",
        "@openzeppelin/=lib/openzeppelin-contracts/contracts/",
        "@aave/=node_modules/@aave/",
        "eth-gas-reporter/=node_modules/eth-gas-reporter/",
        "hardhat-deploy/=node_modules/hardhat-deploy/",
        "hardhat/=node_modules/hardhat/",
        "src/=src/",
        "@ensdomains/=node_modules/@ensdomains/",
        "@siddomains/=node_modules/@siddomains/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "openzeppelin/=lib/openzeppelin-contracts/contracts/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs"
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "london",
      "libraries": {
        "src/core/protocol/libraries/logic/BorrowLogic.sol": {
          "BorrowLogic": "0xb2a2C005B57Ba13d2f6730ABc05FB1086dE75c94"
        },
        "src/core/protocol/libraries/logic/BridgeLogic.sol": {
          "BridgeLogic": "0xd0209F725637631153F1fCB3a2d869acA9afdF88"
        },
        "src/core/protocol/libraries/logic/ConfiguratorLogic.sol": {
          "ConfiguratorLogic": "0xD74d4495936b066218Eb9bf20995BFF93574bC8D"
        },
        "src/core/protocol/libraries/logic/EModeLogic.sol": {
          "EModeLogic": "0x4e68bCD17c6e47Cd7C80D66770f80161296C4273"
        },
        "src/core/protocol/libraries/logic/FlashLoanLogic.sol": {
          "FlashLoanLogic": "0x9F3de000b98A7227348869D40E6Cf739989b8B4D"
        },
        "src/core/protocol/libraries/logic/LiquidationLogic.sol": {
          "LiquidationLogic": "0xE6F87565576785693Ab8eD298dFAbb99eFBcA163"
        },
        "src/core/protocol/libraries/logic/PoolLogic.sol": {
          "PoolLogic": "0x5d9991711eBC3e8F69B1e2cf99B8Cade98792C2B"
        },
        "src/core/protocol/libraries/logic/SupplyLogic.sol": {
          "SupplyLogic": "0xC981354BDCA1829Ac6D40aDE968898703b2e0Cb1"
        }
      }
    }
  }}