Transaction Hash:
Block:
20248559 at Jul-06-2024 04:07:35 PM +UTC
Transaction Fee:
0.000181596532223469 ETH
$0.46
Gas Used:
51,531 Gas / 3.524024999 Gwei
Emitted Events:
217 |
InitializableImmutableAdminUpgradeabilityProxy.0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925( 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925, 0x000000000000000000000000eccb9b9c6fb7590a4d0588953b3170a1a84e3341, 0x000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3, ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x1f9090aa...8e676c326
Miner
| 2.316550425937900071 Eth | 2.316553002487900071 Eth | 0.00000257655 | ||
0x473693Ec...901FB50E8 | |||||
0xECCb9B9C...1a84E3341 |
0.420476918463059662 Eth
Nonce: 765
|
0.420295321930836193 Eth
Nonce: 766
| 0.000181596532223469 |
Execution Trace
InitializableImmutableAdminUpgradeabilityProxy.095ea7b3( )

-
AToken.approve( spender=0x000000000022D473030F116dDEE9F6B43aC78BA3, amount=115792089237316195423570985008687907853269984665640564039457584007913129639935 ) => ( True )
File 1 of 2: InitializableImmutableAdminUpgradeabilityProxy
File 2 of 2: AToken
// SPDX-License-Identifier: AGPL-3.0 AND MIT AND agpl-3.0 // File @openzeppelin/contracts/utils/[email protected] // Original license: SPDX_License_Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } // File contracts/dependencies/openzeppelin/upgradeability/Proxy.sol // Original license: SPDX_License_Identifier: agpl-3.0 pragma solidity 0.8.12; /** * @title Proxy * @dev Implements delegation of calls to other contracts, with proper * forwarding of return values and bubbling of failures. * It defines a fallback function that delegates all calls to the address * returned by the abstract _implementation() internal function. */ abstract contract Proxy { /** * @dev Fallback function. * Implemented entirely in `_fallback`. */ fallback() external payable { _fallback(); } /** * @return The Address of the implementation. */ function _implementation() internal view virtual returns (address); /** * @dev Delegates execution to an implementation contract. * This is a low level function that doesn't return to its internal call site. * It will return to the external caller whatever the implementation returns. * @param implementation Address to delegate. */ function _delegate(address implementation) internal { //solium-disable-next-line assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /** * @dev Function that is run as the first thing in the fallback function. * Can be redefined in derived contracts to add functionality. * Redefinitions must call super._willFallback(). */ function _willFallback() internal virtual {} /** * @dev fallback implementation. * Extracted to enable manual triggering. */ function _fallback() internal { _willFallback(); _delegate(_implementation()); } } // File contracts/dependencies/openzeppelin/upgradeability/BaseUpgradeabilityProxy.sol // Original license: SPDX_License_Identifier: agpl-3.0 pragma solidity 0.8.12; /** * @title BaseUpgradeabilityProxy * @dev This contract implements a proxy that allows to change the * implementation address to which it will delegate. * Such a change is called an implementation upgrade. */ contract BaseUpgradeabilityProxy is Proxy { /** * @dev Emitted when the implementation is upgraded. * @param implementation Address of the new implementation. */ event Upgraded(address indexed implementation); /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Returns the current implementation. * @return impl Address of the current implementation */ function _implementation() internal view override returns (address impl) { bytes32 slot = IMPLEMENTATION_SLOT; //solium-disable-next-line assembly { impl := sload(slot) } } /** * @dev Upgrades the proxy to a new implementation. * @param newImplementation Address of the new implementation. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Sets the implementation address of the proxy. * @param newImplementation Address of the new implementation. */ function _setImplementation(address newImplementation) internal { require(Address.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address"); bytes32 slot = IMPLEMENTATION_SLOT; //solium-disable-next-line assembly { sstore(slot, newImplementation) } } } // File contracts/dependencies/openzeppelin/upgradeability/InitializableUpgradeabilityProxy.sol // Original license: SPDX_License_Identifier: agpl-3.0 pragma solidity 0.8.12; /** * @title InitializableUpgradeabilityProxy * @dev Extends BaseUpgradeabilityProxy with an initializer for initializing * implementation and init data. */ contract InitializableUpgradeabilityProxy is BaseUpgradeabilityProxy { /** * @dev Contract initializer. * @param _logic Address of the initial implementation. * @param _data Data to send as msg.data to the implementation to initialize the proxied contract. * It should include the signature and the parameters of the function to be called, as described in * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped. */ function initialize(address _logic, bytes memory _data) public payable { require(_implementation() == address(0)); assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1)); _setImplementation(_logic); if (_data.length > 0) { (bool success, ) = _logic.delegatecall(_data); require(success); } } } // File contracts/lending/libraries/aave-upgradeability/BaseImmutableAdminUpgradeabilityProxy.sol // Original license: SPDX_License_Identifier: AGPL-3.0 pragma solidity 0.8.12; /** * @title BaseImmutableAdminUpgradeabilityProxy * @author Aave, inspired by the OpenZeppelin upgradeability proxy pattern * @dev This contract combines an upgradeability proxy with an authorization * mechanism for administrative tasks. The admin role is stored in an immutable, which * helps saving transactions costs * All external functions in this contract must be guarded by the * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity * feature proposal that would enable this to be done automatically. */ contract BaseImmutableAdminUpgradeabilityProxy is BaseUpgradeabilityProxy { address immutable ADMIN; constructor(address _admin) { ADMIN = _admin; } modifier ifAdmin() { if (msg.sender == ADMIN) { _; } else { _fallback(); } } /** * @return _address The address of the proxy admin. */ function admin() external ifAdmin returns (address _address) { return ADMIN; } /** * @return _address The address of the implementation. */ function implementation() external ifAdmin returns (address _address) { return _implementation(); } /** * @dev Upgrade the backing implementation of the proxy. * Only the admin can call this function. * @param newImplementation Address of the new implementation. */ function upgradeTo(address newImplementation) external ifAdmin { _upgradeTo(newImplementation); } /** * @dev Upgrade the backing implementation of the proxy and call a function * on the new implementation. * This is useful to initialize the proxied contract. * @param newImplementation Address of the new implementation. * @param data Data to send as msg.data in the low level call. * It should include the signature and the parameters of the function to be called, as described in * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. */ function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin { _upgradeTo(newImplementation); (bool success, ) = newImplementation.delegatecall(data); require(success); } /** * @dev Only fall back when the sender is not the admin. */ function _willFallback() internal virtual override { require(msg.sender != ADMIN, "Cannot call fallback function from the proxy admin"); super._willFallback(); } } // File contracts/lending/libraries/aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol // Original license: SPDX_License_Identifier: AGPL-3.0 pragma solidity 0.8.12; /** * @title InitializableAdminUpgradeabilityProxy * @dev Extends BaseAdminUpgradeabilityProxy with an initializer function */ contract InitializableImmutableAdminUpgradeabilityProxy is BaseImmutableAdminUpgradeabilityProxy, InitializableUpgradeabilityProxy { constructor(address admin) BaseImmutableAdminUpgradeabilityProxy(admin) {} /** * @dev Only fall back when the sender is not the admin. */ function _willFallback() internal override(BaseImmutableAdminUpgradeabilityProxy, Proxy) { BaseImmutableAdminUpgradeabilityProxy._willFallback(); } }
File 2 of 2: AToken
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); } // SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); } // SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); } // SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } } // SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } // SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } } // SPDX-License-Identifier: MIT pragma solidity 0.8.12; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { \tfunction _msgSender() internal view virtual returns (address payable) { \t\treturn payable(msg.sender); \t} \tfunction _msgData() internal view virtual returns (bytes memory) { \t\tthis; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 \t\treturn msg.data; \t} } // SPDX-License-Identifier: agpl-3.0 pragma solidity 0.8.12; pragma experimental ABIEncoderV2; interface IAaveIncentivesController { \tevent RewardsAccrued(address indexed user, uint256 amount); \tevent RewardsClaimed(address indexed user, address indexed to, uint256 amount); \tevent RewardsClaimed(address indexed user, address indexed to, address indexed claimer, uint256 amount); \tevent ClaimerSet(address indexed user, address indexed claimer); \t/* \t * @dev Returns the configuration of the distribution for a certain asset \t * @param asset The address of the reference asset of the distribution \t * @return The asset index, the emission per second and the last updated timestamp \t **/ \tfunction getAssetData(address asset) external view returns (uint256, uint256, uint256); \t/** \t * @dev Whitelists an address to claim the rewards on behalf of another address \t * @param user The address of the user \t * @param claimer The address of the claimer \t */ \tfunction setClaimer(address user, address claimer) external; \t/** \t * @dev Returns the whitelisted claimer for a certain address (0x0 if not set) \t * @param user The address of the user \t * @return The claimer address \t */ \tfunction getClaimer(address user) external view returns (address); \t/** \t * @dev Configure assets for a certain rewards emission \t * @param assets The assets to incentivize \t * @param emissionsPerSecond The emission for each asset \t */ \tfunction configureAssets(address[] calldata assets, uint256[] calldata emissionsPerSecond) external; \t/** \t * @dev Called by the corresponding asset on any update that affects the rewards distribution \t * @param user The address of the user \t **/ \tfunction handleActionBefore(address user) external; \t/** \t * @dev Called by the corresponding asset on any update that affects the rewards distribution \t * @param user The address of the user \t * @param userBalance The balance of the user of the asset in the lending pool \t * @param totalSupply The total supply of the asset in the lending pool \t **/ \tfunction handleActionAfter(address user, uint256 userBalance, uint256 totalSupply) external; \t/** \t * @dev Returns the total of rewards of an user, already accrued + not yet accrued \t * @param user The address of the user \t * @return The rewards \t **/ \tfunction getRewardsBalance(address[] calldata assets, address user) external view returns (uint256); \t/** \t * @dev Claims reward for an user, on all the assets of the lending pool, accumulating the pending rewards \t * @param amount Amount of rewards to claim \t * @param to Address that will be receiving the rewards \t * @return Rewards claimed \t **/ \tfunction claimRewards(address[] calldata assets, uint256 amount, address to) external returns (uint256); \t/** \t * @dev Claims reward for an user on behalf, on all the assets of the lending pool, accumulating the pending rewards. The caller must \t * be whitelisted via "allowClaimOnBehalf" function by the RewardsAdmin role manager \t * @param amount Amount of rewards to claim \t * @param user Address to check and claim rewards \t * @param to Address that will be receiving the rewards \t * @return Rewards claimed \t **/ \tfunction claimRewardsOnBehalf( \t\taddress[] calldata assets, \t\tuint256 amount, \t\taddress user, \t\taddress to \t) external returns (uint256); \t/** \t * @dev returns the unclaimed rewards of the user \t * @param user the address of the user \t * @return the unclaimed user rewards \t */ \tfunction getUserUnclaimedRewards(address user) external view returns (uint256); \t/** \t * @dev returns the unclaimed rewards of the user \t * @param user the address of the user \t * @param asset The asset to incentivize \t * @return the user index for the asset \t */ \tfunction getUserAssetData(address user, address asset) external view returns (uint256); \t/** \t * @dev for backward compatibility with previous implementation of the Incentives controller \t */ \tfunction REWARD_TOKEN() external view returns (address); \t/** \t * @dev for backward compatibility with previous implementation of the Incentives controller \t */ \tfunction PRECISION() external view returns (uint8); \t/** \t * @dev Gets the distribution end timestamp of the emissions \t */ \tfunction DISTRIBUTION_END() external view returns (uint256); } // SPDX-License-Identifier: agpl-3.0 pragma solidity 0.8.12; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IScaledBalanceToken} from "./IScaledBalanceToken.sol"; import {IInitializableAToken} from "./IInitializableAToken.sol"; import {IAaveIncentivesController} from "./IAaveIncentivesController.sol"; import {ILendingPool} from "./ILendingPool.sol"; interface IAToken is IERC20, IScaledBalanceToken, IInitializableAToken { \t/** \t * @dev Emitted after the mint action \t * @param from The address performing the mint \t * @param value The amount being \t * @param index The new liquidity index of the reserve \t **/ \tevent Mint(address indexed from, uint256 value, uint256 index); \t/** \t * @dev Mints `amount` aTokens to `user` \t * @param user The address receiving the minted tokens \t * @param amount The amount of tokens getting minted \t * @param index The new liquidity index of the reserve \t * @return `true` if the the previous balance of the user was 0 \t */ \tfunction mint(address user, uint256 amount, uint256 index) external returns (bool); \t/** \t * @dev Emitted after aTokens are burned \t * @param from The owner of the aTokens, getting them burned \t * @param target The address that will receive the underlying \t * @param value The amount being burned \t * @param index The new liquidity index of the reserve \t **/ \tevent Burn(address indexed from, address indexed target, uint256 value, uint256 index); \t/** \t * @dev Emitted during the transfer action \t * @param from The user whose tokens are being transferred \t * @param to The recipient \t * @param value The amount being transferred \t * @param index The new liquidity index of the reserve \t **/ \tevent BalanceTransfer(address indexed from, address indexed to, uint256 value, uint256 index); \t/** \t * @dev Burns aTokens from `user` and sends the equivalent amount of underlying to `receiverOfUnderlying` \t * @param user The owner of the aTokens, getting them burned \t * @param receiverOfUnderlying The address that will receive the underlying \t * @param amount The amount being burned \t * @param index The new liquidity index of the reserve \t **/ \tfunction burn(address user, address receiverOfUnderlying, uint256 amount, uint256 index) external; \t/** \t * @dev Mints aTokens to the reserve treasury \t * @param amount The amount of tokens getting minted \t * @param index The new liquidity index of the reserve \t */ \tfunction mintToTreasury(uint256 amount, uint256 index) external; \t/** \t * @dev Transfers aTokens in the event of a borrow being liquidated, in case the liquidators reclaims the aToken \t * @param from The address getting liquidated, current owner of the aTokens \t * @param to The recipient \t * @param value The amount of tokens getting transferred \t **/ \tfunction transferOnLiquidation(address from, address to, uint256 value) external; \t/** \t * @dev Transfers the underlying asset to `target`. Used by the LendingPool to transfer \t * assets in borrow(), withdraw() and flashLoan() \t * @param user The recipient of the underlying \t * @param amount The amount getting transferred \t * @return The amount transferred \t **/ \tfunction transferUnderlyingTo(address user, uint256 amount) external returns (uint256); \t/** \t * @dev Invoked to execute actions on the aToken side after a repayment. \t * @param user The user executing the repayment \t * @param amount The amount getting repaid \t **/ \tfunction handleRepayment(address user, uint256 amount) external; \t/** \t * @dev Updates the treasury address \t * @param treasury The new treasury address \t */ \tfunction setTreasuryAddress(address treasury) external; \t/** \t * @dev Returns the address of the incentives controller contract \t **/ \tfunction getIncentivesController() external view returns (IAaveIncentivesController); \t/** \t * @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH) \t **/ \tfunction UNDERLYING_ASSET_ADDRESS() external view returns (address); \t/** \t * @dev Returns the address of the lending pool where this aToken is used \t **/ \tfunction POOL() external view returns (ILendingPool); } // SPDX-License-Identifier: MIT pragma solidity 0.8.12; import "./LockedBalance.sol"; interface IFeeDistribution { \tstruct RewardData { \t\taddress token; \t\tuint256 amount; \t} \tfunction addReward(address rewardsToken) external; \tfunction removeReward(address _rewardToken) external; } // SPDX-License-Identifier: agpl-3.0 pragma solidity 0.8.12; import {ILendingPool} from "./ILendingPool.sol"; import {IAaveIncentivesController} from "./IAaveIncentivesController.sol"; /** * @title IInitializableAToken * @notice Interface for the initialize function on AToken * @author Aave **/ interface IInitializableAToken { \t/** \t * @dev Emitted when an aToken is initialized \t * @param underlyingAsset The address of the underlying asset \t * @param pool The address of the associated lending pool \t * @param treasury The address of the treasury \t * @param incentivesController The address of the incentives controller for this aToken \t * @param aTokenDecimals the decimals of the underlying \t * @param aTokenName the name of the aToken \t * @param aTokenSymbol the symbol of the aToken \t * @param params A set of encoded parameters for additional initialization \t **/ \tevent Initialized( \t\taddress indexed underlyingAsset, \t\taddress indexed pool, \t\taddress treasury, \t\taddress incentivesController, \t\tuint8 aTokenDecimals, \t\tstring aTokenName, \t\tstring aTokenSymbol, \t\tbytes params \t); \t/** \t * @dev Initializes the aToken \t * @param pool The address of the lending pool where this aToken will be used \t * @param treasury The address of the Aave treasury, receiving the fees on this aToken \t * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH) \t * @param incentivesController The smart contract managing potential incentives distribution \t * @param aTokenDecimals The decimals of the aToken, same as the underlying asset's \t * @param aTokenName The name of the aToken \t * @param aTokenSymbol The symbol of the aToken \t */ \tfunction initialize( \t\tILendingPool pool, \t\taddress treasury, \t\taddress underlyingAsset, \t\tIAaveIncentivesController incentivesController, \t\tuint8 aTokenDecimals, \t\tstring calldata aTokenName, \t\tstring calldata aTokenSymbol, \t\tbytes calldata params \t) external; } // SPDX-License-Identifier: agpl-3.0 pragma solidity 0.8.12; pragma experimental ABIEncoderV2; import {ILendingPoolAddressesProvider} from "./ILendingPoolAddressesProvider.sol"; import {DataTypes} from "../lending/libraries/types/DataTypes.sol"; interface ILendingPool { \t/** \t * @dev Emitted on deposit() \t * @param reserve The address of the underlying asset of the reserve \t * @param user The address initiating the deposit \t * @param onBehalfOf The beneficiary of the deposit, receiving the aTokens \t * @param amount The amount deposited \t * @param referral The referral code used \t **/ \tevent Deposit( \t\taddress indexed reserve, \t\taddress user, \t\taddress indexed onBehalfOf, \t\tuint256 amount, \t\tuint16 indexed referral \t); \t/** \t * @dev Emitted on withdraw() \t * @param reserve The address of the underlyng asset being withdrawn \t * @param user The address initiating the withdrawal, owner of aTokens \t * @param to Address that will receive the underlying \t * @param amount The amount to be withdrawn \t **/ \tevent Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount); \t/** \t * @dev Emitted on borrow() and flashLoan() when debt needs to be opened \t * @param reserve The address of the underlying asset being borrowed \t * @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just \t * initiator of the transaction on flashLoan() \t * @param onBehalfOf The address that will be getting the debt \t * @param amount The amount borrowed out \t * @param borrowRateMode The rate mode: 1 for Stable, 2 for Variable \t * @param borrowRate The numeric rate at which the user has borrowed \t * @param referral The referral code used \t **/ \tevent Borrow( \t\taddress indexed reserve, \t\taddress user, \t\taddress indexed onBehalfOf, \t\tuint256 amount, \t\tuint256 borrowRateMode, \t\tuint256 borrowRate, \t\tuint16 indexed referral \t); \t/** \t * @dev Emitted on repay() \t * @param reserve The address of the underlying asset of the reserve \t * @param user The beneficiary of the repayment, getting his debt reduced \t * @param repayer The address of the user initiating the repay(), providing the funds \t * @param amount The amount repaid \t **/ \tevent Repay(address indexed reserve, address indexed user, address indexed repayer, uint256 amount); \t/** \t * @dev Emitted on swapBorrowRateMode() \t * @param reserve The address of the underlying asset of the reserve \t * @param user The address of the user swapping his rate mode \t * @param rateMode The rate mode that the user wants to swap to \t **/ \tevent Swap(address indexed reserve, address indexed user, uint256 rateMode); \t/** \t * @dev Emitted on setUserUseReserveAsCollateral() \t * @param reserve The address of the underlying asset of the reserve \t * @param user The address of the user enabling the usage as collateral \t **/ \tevent ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user); \t/** \t * @dev Emitted on setUserUseReserveAsCollateral() \t * @param reserve The address of the underlying asset of the reserve \t * @param user The address of the user enabling the usage as collateral \t **/ \tevent ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user); \t/** \t * @dev Emitted on rebalanceStableBorrowRate() \t * @param reserve The address of the underlying asset of the reserve \t * @param user The address of the user for which the rebalance has been executed \t **/ \tevent RebalanceStableBorrowRate(address indexed reserve, address indexed user); \t/** \t * @dev Emitted on flashLoan() \t * @param target The address of the flash loan receiver contract \t * @param initiator The address initiating the flash loan \t * @param asset The address of the asset being flash borrowed \t * @param amount The amount flash borrowed \t * @param premium The fee flash borrowed \t * @param referralCode The referral code used \t **/ \tevent FlashLoan( \t\taddress indexed target, \t\taddress indexed initiator, \t\taddress indexed asset, \t\tuint256 amount, \t\tuint256 premium, \t\tuint16 referralCode \t); \t/** \t * @dev Emitted when the pause is triggered. \t */ \tevent Paused(); \t/** \t * @dev Emitted when the pause is lifted. \t */ \tevent Unpaused(); \t/** \t * @dev Emitted when a borrower is liquidated. This event is emitted by the LendingPool via \t * LendingPoolCollateral manager using a DELEGATECALL \t * This allows to have the events in the generated ABI for LendingPool. \t * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation \t * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation \t * @param user The address of the borrower getting liquidated \t * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover \t * @param liquidatedCollateralAmount The amount of collateral received by the liiquidator \t * @param liquidator The address of the liquidator \t * @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants \t * to receive the underlying collateral asset directly \t **/ \tevent LiquidationCall( \t\taddress indexed collateralAsset, \t\taddress indexed debtAsset, \t\taddress indexed user, \t\tuint256 debtToCover, \t\tuint256 liquidatedCollateralAmount, \t\taddress liquidator, \t\tbool receiveAToken \t); \t/** \t * @dev Emitted when the state of a reserve is updated. NOTE: This event is actually declared \t * in the ReserveLogic library and emitted in the updateInterestRates() function. Since the function is internal, \t * the event will actually be fired by the LendingPool contract. The event is therefore replicated here so it \t * gets added to the LendingPool ABI \t * @param reserve The address of the underlying asset of the reserve \t * @param liquidityRate The new liquidity rate \t * @param stableBorrowRate The new stable borrow rate \t * @param variableBorrowRate The new variable borrow rate \t * @param liquidityIndex The new liquidity index \t * @param variableBorrowIndex The new variable borrow index \t **/ \tevent ReserveDataUpdated( \t\taddress indexed reserve, \t\tuint256 liquidityRate, \t\tuint256 stableBorrowRate, \t\tuint256 variableBorrowRate, \t\tuint256 liquidityIndex, \t\tuint256 variableBorrowIndex \t); \tfunction initialize(ILendingPoolAddressesProvider provider) external; \t/** \t * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. \t * - E.g. User deposits 100 USDC and gets in return 100 aUSDC \t * @param asset The address of the underlying asset to deposit \t * @param amount The amount to be deposited \t * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user \t * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens \t * is a different wallet \t * @param referralCode Code used to register the integrator originating the operation, for potential rewards. \t * 0 if the action is executed directly by the user, without any middle-man \t **/ \tfunction deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external; \tfunction depositWithAutoDLP(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external; \t/** \t * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned \t * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC \t * @param asset The address of the underlying asset to withdraw \t * @param amount The underlying amount to be withdrawn \t * - Send the value type(uint256).max in order to withdraw the whole aToken balance \t * @param to Address that will receive the underlying, same as msg.sender if the user \t * wants to receive it on his own wallet, or a different address if the beneficiary is a \t * different wallet \t * @return The final amount withdrawn \t **/ \tfunction withdraw(address asset, uint256 amount, address to) external returns (uint256); \t/** \t * @dev Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower \t * already deposited enough collateral, or he was given enough allowance by a credit delegator on the \t * corresponding debt token (StableDebtToken or VariableDebtToken) \t * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet \t * and 100 stable/variable debt tokens, depending on the `interestRateMode` \t * @param asset The address of the underlying asset to borrow \t * @param amount The amount to be borrowed \t * @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable \t * @param referralCode Code used to register the integrator originating the operation, for potential rewards. \t * 0 if the action is executed directly by the user, without any middle-man \t * @param onBehalfOf Address of the user who will receive the debt. Should be the address of the borrower itself \t * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator \t * if he has been given credit delegation allowance \t **/ \tfunction borrow( \t\taddress asset, \t\tuint256 amount, \t\tuint256 interestRateMode, \t\tuint16 referralCode, \t\taddress onBehalfOf \t) external; \t/** \t * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned \t * - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address \t * @param asset The address of the borrowed underlying asset previously borrowed \t * @param amount The amount to repay \t * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` \t * @param rateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable \t * @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the \t * user calling the function if he wants to reduce/remove his own debt, or the address of any other \t * other borrower whose debt should be removed \t * @return The final amount repaid \t **/ \tfunction repay(address asset, uint256 amount, uint256 rateMode, address onBehalfOf) external returns (uint256); \t/** \t * @dev Allows a borrower to swap his debt between stable and variable mode, or viceversa \t * @param asset The address of the underlying asset borrowed \t * @param rateMode The rate mode that the user wants to swap to \t **/ \tfunction swapBorrowRateMode(address asset, uint256 rateMode) external; \t/** \t * @dev Rebalances the stable interest rate of a user to the current stable rate defined on the reserve. \t * - Users can be rebalanced if the following conditions are satisfied: \t * 1. Usage ratio is above 95% \t * 2. the current deposit APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too much has been \t * borrowed at a stable rate and depositors are not earning enough \t * @param asset The address of the underlying asset borrowed \t * @param user The address of the user to be rebalanced \t **/ \tfunction rebalanceStableBorrowRate(address asset, address user) external; \t/** \t * @dev Allows depositors to enable/disable a specific deposited asset as collateral \t * @param asset The address of the underlying asset deposited \t * @param useAsCollateral `true` if the user wants to use the deposit as collateral, `false` otherwise \t **/ \tfunction setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external; \t/** \t * @dev Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1 \t * - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives \t * a proportionally amount of the `collateralAsset` plus a bonus to cover market risk \t * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation \t * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation \t * @param user The address of the borrower getting liquidated \t * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover \t * @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants \t * to receive the underlying collateral asset directly \t **/ \tfunction liquidationCall( \t\taddress collateralAsset, \t\taddress debtAsset, \t\taddress user, \t\tuint256 debtToCover, \t\tbool receiveAToken \t) external; \t/** \t * @dev Allows smartcontracts to access the liquidity of the pool within one transaction, \t * as long as the amount taken plus a fee is returned. \t * IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept into consideration. \t * For further details please visit https://developers.aave.com \t * @param receiverAddress The address of the contract receiving the funds, implementing the IFlashLoanReceiver interface \t * @param assets The addresses of the assets being flash-borrowed \t * @param amounts The amounts amounts being flash-borrowed \t * @param modes Types of the debt to open if the flash loan is not returned: \t * 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver \t * 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address \t * 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address \t * @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2 \t * @param params Variadic packed params to pass to the receiver as extra information \t * @param referralCode Code used to register the integrator originating the operation, for potential rewards. \t * 0 if the action is executed directly by the user, without any middle-man \t **/ \tfunction flashLoan( \t\taddress receiverAddress, \t\taddress[] calldata assets, \t\tuint256[] calldata amounts, \t\tuint256[] calldata modes, \t\taddress onBehalfOf, \t\tbytes calldata params, \t\tuint16 referralCode \t) external; \t/** \t * @dev Returns the user account data across all the reserves \t * @param user The address of the user \t * @return totalCollateral the total collateral in USD to 8 decimals of the user \t * @return totalDebt the total debt in USD to 8 decimals of the user \t * @return availableBorrows the borrowing power left of the user \t * @return currentLiquidationThreshold the liquidation threshold of the user \t * @return ltv the loan to value of the user \t * @return healthFactor the current health factor of the user \t **/ \tfunction getUserAccountData( \t\taddress user \t) \t\texternal \t\tview \t\treturns ( \t\t\tuint256 totalCollateral, \t\t\tuint256 totalDebt, \t\t\tuint256 availableBorrows, \t\t\tuint256 currentLiquidationThreshold, \t\t\tuint256 ltv, \t\t\tuint256 healthFactor \t\t); \tfunction initReserve( \t\taddress reserve, \t\taddress aTokenAddress, \t\taddress stableDebtAddress, \t\taddress variableDebtAddress, \t\taddress interestRateStrategyAddress \t) external; \tfunction setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress) external; \tfunction setConfiguration(address reserve, uint256 configuration) external; \t/** \t * @dev Returns the configuration of the reserve \t * @param asset The address of the underlying asset of the reserve \t * @return The configuration of the reserve \t **/ \tfunction getConfiguration(address asset) external view returns (DataTypes.ReserveConfigurationMap memory); \t/** \t * @dev Returns the configuration of the user across all the reserves \t * @param user The user address \t * @return The configuration of the user \t **/ \tfunction getUserConfiguration(address user) external view returns (DataTypes.UserConfigurationMap memory); \t/** \t * @dev Returns the normalized income normalized income of the reserve \t * @param asset The address of the underlying asset of the reserve \t * @return The reserve's normalized income \t */ \tfunction getReserveNormalizedIncome(address asset) external view returns (uint256); \t/** \t * @dev Returns the normalized variable debt per unit of asset \t * @param asset The address of the underlying asset of the reserve \t * @return The reserve normalized variable debt \t */ \tfunction getReserveNormalizedVariableDebt(address asset) external view returns (uint256); \t/** \t * @dev Returns the state and configuration of the reserve \t * @param asset The address of the underlying asset of the reserve \t * @return The state of the reserve \t **/ \tfunction getReserveData(address asset) external view returns (DataTypes.ReserveData memory); \tfunction finalizeTransfer( \t\taddress asset, \t\taddress from, \t\taddress to, \t\tuint256 amount, \t\tuint256 balanceFromAfter, \t\tuint256 balanceToBefore \t) external; \tfunction getReservesList() external view returns (address[] memory); \tfunction getAddressesProvider() external view returns (ILendingPoolAddressesProvider); \tfunction setPause(bool val) external; \tfunction paused() external view returns (bool); } // SPDX-License-Identifier: agpl-3.0 pragma solidity 0.8.12; /** * @title LendingPoolAddressesProvider contract * @dev Main registry of addresses part of or connected to the protocol, including permissioned roles * - Acting also as factory of proxies and admin of those, so with right to change its implementations * - Owned by the Aave Governance * @author Aave **/ interface ILendingPoolAddressesProvider { \tevent MarketIdSet(string newMarketId); \tevent LendingPoolUpdated(address indexed newAddress); \tevent ConfigurationAdminUpdated(address indexed newAddress); \tevent EmergencyAdminUpdated(address indexed newAddress); \tevent LendingPoolConfiguratorUpdated(address indexed newAddress); \tevent LendingPoolCollateralManagerUpdated(address indexed newAddress); \tevent PriceOracleUpdated(address indexed newAddress); \tevent LendingRateOracleUpdated(address indexed newAddress); \tevent ProxyCreated(bytes32 id, address indexed newAddress); \tevent AddressSet(bytes32 id, address indexed newAddress, bool hasProxy); \tfunction getMarketId() external view returns (string memory); \tfunction setMarketId(string calldata marketId) external; \tfunction setAddress(bytes32 id, address newAddress) external; \tfunction setAddressAsProxy(bytes32 id, address impl) external; \tfunction getAddress(bytes32 id) external view returns (address); \tfunction getLendingPool() external view returns (address); \tfunction setLendingPoolImpl(address pool) external; \tfunction getLendingPoolConfigurator() external view returns (address); \tfunction setLendingPoolConfiguratorImpl(address configurator) external; \tfunction getLendingPoolCollateralManager() external view returns (address); \tfunction setLendingPoolCollateralManager(address manager) external; \tfunction getPoolAdmin() external view returns (address); \tfunction setPoolAdmin(address admin) external; \tfunction getEmergencyAdmin() external view returns (address); \tfunction setEmergencyAdmin(address admin) external; \tfunction getPriceOracle() external view returns (address); \tfunction setPriceOracle(address priceOracle) external; \tfunction getLendingRateOracle() external view returns (address); \tfunction setLendingRateOracle(address lendingRateOracle) external; \tfunction getLiquidationFeeTo() external view returns (address); \tfunction setLiquidationFeeTo(address liquidationFeeTo) external; } // SPDX-License-Identifier: MIT pragma solidity 0.8.12; import "./LockedBalance.sol"; import {IFeeDistribution} from "./IMultiFeeDistribution.sol"; interface IMiddleFeeDistribution is IFeeDistribution { \tfunction forwardReward(address[] memory _rewardTokens) external; \tfunction getRdntTokenAddress() external view returns (address); \tfunction getMultiFeeDistributionAddress() external view returns (address); \tfunction operationExpenseRatio() external view returns (uint256); \tfunction operationExpenses() external view returns (address); \tfunction isRewardToken(address) external view returns (bool); } // SPDX-License-Identifier: agpl-3.0 pragma solidity 0.8.12; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IMintableToken is IERC20 { \tfunction mint(address _receiver, uint256 _amount) external returns (bool); \tfunction burn(uint256 _amount) external returns (bool); \tfunction setMinter(address _minter) external returns (bool); } // SPDX-License-Identifier: MIT pragma solidity 0.8.12; import "./LockedBalance.sol"; import "./IFeeDistribution.sol"; import "./IMintableToken.sol"; interface IMultiFeeDistribution is IFeeDistribution { \tfunction exit(bool claimRewards) external; \tfunction stake(uint256 amount, address onBehalfOf, uint256 typeIndex) external; \tfunction rdntToken() external view returns (IMintableToken); \tfunction getPriceProvider() external view returns (address); \tfunction lockInfo(address user) external view returns (LockedBalance[] memory); \tfunction autocompoundDisabled(address user) external view returns (bool); \tfunction defaultLockIndex(address _user) external view returns (uint256); \tfunction autoRelockDisabled(address user) external view returns (bool); \tfunction totalBalance(address user) external view returns (uint256); \tfunction lockedBalance(address user) external view returns (uint256); \tfunction lockedBalances( \t\taddress user \t) external view returns (uint256, uint256, uint256, uint256, LockedBalance[] memory); \tfunction getBalances(address _user) external view returns (Balances memory); \tfunction zapVestingToLp(address _address) external returns (uint256); \tfunction claimableRewards(address account) external view returns (IFeeDistribution.RewardData[] memory rewards); \tfunction setDefaultRelockTypeIndex(uint256 _index) external; \tfunction daoTreasury() external view returns (address); \tfunction stakingToken() external view returns (address); \tfunction userSlippage(address) external view returns (uint256); \tfunction claimFromConverter(address) external; \tfunction vestTokens(address user, uint256 amount, bool withPenalty) external; } interface IMFDPlus is IMultiFeeDistribution { \tfunction getLastClaimTime(address _user) external returns (uint256); \tfunction claimBounty(address _user, bool _execute) external returns (bool issueBaseBounty); \tfunction claimCompound(address _user, bool _execute, uint256 _slippage) external returns (uint256 bountyAmt); \tfunction setAutocompound(bool state, uint256 slippage) external; \tfunction setUserSlippage(uint256 slippage) external; \tfunction toggleAutocompound() external; } // SPDX-License-Identifier: agpl-3.0 pragma solidity 0.8.12; /************ @title IPriceOracle interface @notice Interface for the Aave price oracle.*/ interface IPriceOracle { \t/*********** @dev returns the asset price in ETH */ \tfunction getAssetPrice(address asset) external view returns (uint256); \t/*********** @dev sets the asset price, in wei */ \tfunction setAssetPrice(address asset, uint256 price) external; } // SPDX-License-Identifier: agpl-3.0 pragma solidity 0.8.12; interface IScaledBalanceToken { \t/** \t * @dev Returns the scaled balance of the user. The scaled balance is the sum of all the \t * updated stored balance divided by the reserve's liquidity index at the moment of the update \t * @param user The user whose balance is calculated \t * @return The scaled balance of the user \t **/ \tfunction scaledBalanceOf(address user) external view returns (uint256); \t/** \t * @dev Returns the scaled balance of the user and the scaled total supply. \t * @param user The address of the user \t * @return The scaled balance of the user \t * @return The scaled balance and the scaled total supply \t **/ \tfunction getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256); \t/** \t * @dev Returns the scaled total supply of the variable debt token. Represents sum(debt/index) \t * @return The scaled total supply \t **/ \tfunction scaledTotalSupply() external view returns (uint256); } // SPDX-License-Identifier: MIT pragma solidity 0.8.12; struct LockedBalance { \tuint256 amount; \tuint256 unlockTime; \tuint256 multiplier; \tuint256 duration; } struct EarnedBalance { \tuint256 amount; \tuint256 unlockTime; \tuint256 penalty; } struct Reward { \tuint256 periodFinish; \tuint256 rewardPerSecond; \tuint256 lastUpdateTime; \tuint256 rewardPerTokenStored; \t// tracks already-added balances to handle accrued interest in aToken rewards \t// for the stakingToken this value is unused and will always be 0 \tuint256 balance; } struct Balances { \tuint256 total; // sum of earnings and lockings; no use when LP and RDNT is different \tuint256 unlocked; // RDNT token \tuint256 locked; // LP token or RDNT token \tuint256 lockedWithMultiplier; // Multiplied locked amount \tuint256 earned; // RDNT token } // SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.12; /** * @title VersionedInitializable * * @dev Helper contract to implement initializer functions. To use it, replace * the constructor with a function that has the `initializer` modifier. * WARNING: Unlike constructors, initializer functions must be manually * invoked. This applies both to deploying an Initializable contract, as well * as extending an Initializable contract via inheritance. * WARNING: When used with inheritance, manual care must be taken to not invoke * a parent initializer twice, or ensure that all initializers are idempotent, * because this is not dealt with automatically as with constructors. * * @author Aave, inspired by the OpenZeppelin Initializable contract */ abstract contract VersionedInitializable { \t/** \t * @dev Indicates that the contract has been initialized. \t */ \tuint256 private lastInitializedRevision = 0; \t/** \t * @dev Indicates that the contract is in the process of being initialized. \t */ \tbool private initializing; \t/** \t * @dev Indicates that the contract has been initialized. \t */ \tbool private initialized; \t/** \t * @dev Modifier to use in the initializer function of a contract. \t */ \tmodifier initializer() { \t\tuint256 revision = getRevision(); \t\tbool isTopLevelCall = !initializing; \t\trequire( \t\t\tisTopLevelCall && (revision > lastInitializedRevision || !initialized), \t\t\t"Contract instance has already been initialized" \t\t); \t\tif (isTopLevelCall) { \t\t\tinitializing = true; \t\t\tinitialized = true; \t\t\tlastInitializedRevision = revision; \t\t} \t\t_; \t\tif (isTopLevelCall) { \t\t\tinitializing = false; \t\t} \t} \t/** \t * @dev returns the revision number of the contract \t * Needs to be defined in the inherited class as a constant. \t **/ \tfunction getRevision() internal pure virtual returns (uint256); \tfunction _disableInitializers() internal virtual { \t\trequire(!initializing, "Initializable: contract is initializing"); \t\tif (!initialized) { \t\t\tlastInitializedRevision = getRevision(); \t\t\tinitialized = true; \t\t} \t} \t// Reserved storage space to allow for layout changes in the future. \tuint256[50] private ______gap; } // SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.12; /** * @title Errors library * @author Aave * @notice Defines the error messages emitted by the different contracts of the Aave protocol * @dev Error messages prefix glossary: * - VL = ValidationLogic * - MATH = Math libraries * - CT = Common errors between tokens (AToken, VariableDebtToken and StableDebtToken) * - AT = AToken * - SDT = StableDebtToken * - VDT = VariableDebtToken * - LP = LendingPool * - LPAPR = LendingPoolAddressesProviderRegistry * - LPC = LendingPoolConfiguration * - RL = ReserveLogic * - LPCM = LendingPoolCollateralManager * - P = Pausable */ library Errors { \t//common errors \tstring public constant CALLER_NOT_POOL_ADMIN = "33"; // 'The caller must be the pool admin' \tstring public constant BORROW_ALLOWANCE_NOT_ENOUGH = "59"; // User borrows on behalf, but allowance are too small \t//contract specific errors \tstring public constant VL_INVALID_AMOUNT = "1"; // 'Amount must be greater than 0' \tstring public constant VL_NO_ACTIVE_RESERVE = "2"; // 'Action requires an active reserve' \tstring public constant VL_RESERVE_FROZEN = "3"; // 'Action cannot be performed because the reserve is frozen' \tstring public constant VL_CURRENT_AVAILABLE_LIQUIDITY_NOT_ENOUGH = "4"; // 'The current liquidity is not enough' \tstring public constant VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE = "5"; // 'User cannot withdraw more than the available balance' \tstring public constant VL_TRANSFER_NOT_ALLOWED = "6"; // 'Transfer cannot be allowed.' \tstring public constant VL_BORROWING_NOT_ENABLED = "7"; // 'Borrowing is not enabled' \tstring public constant VL_INVALID_INTEREST_RATE_MODE_SELECTED = "8"; // 'Invalid interest rate mode selected' \tstring public constant VL_COLLATERAL_BALANCE_IS_0 = "9"; // 'The collateral balance is 0' \tstring public constant VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD = "10"; // 'Health factor is lesser than the liquidation threshold' \tstring public constant VL_COLLATERAL_CANNOT_COVER_NEW_BORROW = "11"; // 'There is not enough collateral to cover a new borrow' \tstring public constant VL_STABLE_BORROWING_NOT_ENABLED = "12"; // stable borrowing not enabled \tstring public constant VL_COLLATERAL_SAME_AS_BORROWING_CURRENCY = "13"; // collateral is (mostly) the same currency that is being borrowed \tstring public constant VL_AMOUNT_BIGGER_THAN_MAX_LOAN_SIZE_STABLE = "14"; // 'The requested amount is greater than the max loan size in stable rate mode \tstring public constant VL_NO_DEBT_OF_SELECTED_TYPE = "15"; // 'for repayment of stable debt, the user needs to have stable debt, otherwise, he needs to have variable debt' \tstring public constant VL_NO_EXPLICIT_AMOUNT_TO_REPAY_ON_BEHALF = "16"; // 'To repay on behalf of an user an explicit amount to repay is needed' \tstring public constant VL_NO_STABLE_RATE_LOAN_IN_RESERVE = "17"; // 'User does not have a stable rate loan in progress on this reserve' \tstring public constant VL_NO_VARIABLE_RATE_LOAN_IN_RESERVE = "18"; // 'User does not have a variable rate loan in progress on this reserve' \tstring public constant VL_UNDERLYING_BALANCE_NOT_GREATER_THAN_0 = "19"; // 'The underlying balance needs to be greater than 0' \tstring public constant VL_DEPOSIT_ALREADY_IN_USE = "20"; // 'User deposit is already being used as collateral' \tstring public constant LP_NOT_ENOUGH_STABLE_BORROW_BALANCE = "21"; // 'User does not have any stable rate loan for this reserve' \tstring public constant LP_INTEREST_RATE_REBALANCE_CONDITIONS_NOT_MET = "22"; // 'Interest rate rebalance conditions were not met' \tstring public constant LP_LIQUIDATION_CALL_FAILED = "23"; // 'Liquidation call failed' \tstring public constant LP_NOT_ENOUGH_LIQUIDITY_TO_BORROW = "24"; // 'There is not enough liquidity available to borrow' \tstring public constant LP_REQUESTED_AMOUNT_TOO_SMALL = "25"; // 'The requested amount is too small for a FlashLoan.' \tstring public constant LP_INCONSISTENT_PROTOCOL_ACTUAL_BALANCE = "26"; // 'The actual balance of the protocol is inconsistent' \tstring public constant LP_CALLER_NOT_LENDING_POOL_CONFIGURATOR = "27"; // 'The caller of the function is not the lending pool configurator' \tstring public constant LP_INCONSISTENT_FLASHLOAN_PARAMS = "28"; \tstring public constant CT_CALLER_MUST_BE_LENDING_POOL = "29"; // 'The caller of this function must be a lending pool' \tstring public constant CT_CANNOT_GIVE_ALLOWANCE_TO_HIMSELF = "30"; // 'User cannot give allowance to himself' \tstring public constant CT_TRANSFER_AMOUNT_NOT_GT_0 = "31"; // 'Transferred amount needs to be greater than zero' \tstring public constant RL_RESERVE_ALREADY_INITIALIZED = "32"; // 'Reserve has already been initialized' \tstring public constant LPC_RESERVE_LIQUIDITY_NOT_0 = "34"; // 'The liquidity of the reserve needs to be 0' \tstring public constant LPC_INVALID_ATOKEN_POOL_ADDRESS = "35"; // 'The liquidity of the reserve needs to be 0' \tstring public constant LPC_INVALID_STABLE_DEBT_TOKEN_POOL_ADDRESS = "36"; // 'The liquidity of the reserve needs to be 0' \tstring public constant LPC_INVALID_VARIABLE_DEBT_TOKEN_POOL_ADDRESS = "37"; // 'The liquidity of the reserve needs to be 0' \tstring public constant LPC_INVALID_STABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = "38"; // 'The liquidity of the reserve needs to be 0' \tstring public constant LPC_INVALID_VARIABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = "39"; // 'The liquidity of the reserve needs to be 0' \tstring public constant LPC_INVALID_ADDRESSES_PROVIDER_ID = "40"; // 'The liquidity of the reserve needs to be 0' \tstring public constant LPC_INVALID_CONFIGURATION = "75"; // 'Invalid risk parameters for the reserve' \tstring public constant LPC_CALLER_NOT_EMERGENCY_ADMIN = "76"; // 'The caller must be the emergency admin' \tstring public constant LPAPR_PROVIDER_NOT_REGISTERED = "41"; // 'Provider is not registered' \tstring public constant LPCM_HEALTH_FACTOR_NOT_BELOW_THRESHOLD = "42"; // 'Health factor is not below the threshold' \tstring public constant LPCM_COLLATERAL_CANNOT_BE_LIQUIDATED = "43"; // 'The collateral chosen cannot be liquidated' \tstring public constant LPCM_SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER = "44"; // 'User did not borrow the specified currency' \tstring public constant LPCM_NOT_ENOUGH_LIQUIDITY_TO_LIQUIDATE = "45"; // "There isn't enough liquidity available to liquidate" \tstring public constant LPCM_NO_ERRORS = "46"; // 'No errors' \tstring public constant LP_INVALID_FLASHLOAN_MODE = "47"; //Invalid flashloan mode selected \tstring public constant MATH_MULTIPLICATION_OVERFLOW = "48"; \tstring public constant MATH_ADDITION_OVERFLOW = "49"; \tstring public constant MATH_DIVISION_BY_ZERO = "50"; \tstring public constant RL_LIQUIDITY_INDEX_OVERFLOW = "51"; // Liquidity index overflows uint128 \tstring public constant RL_VARIABLE_BORROW_INDEX_OVERFLOW = "52"; // Variable borrow index overflows uint128 \tstring public constant RL_LIQUIDITY_RATE_OVERFLOW = "53"; // Liquidity rate overflows uint128 \tstring public constant RL_VARIABLE_BORROW_RATE_OVERFLOW = "54"; // Variable borrow rate overflows uint128 \tstring public constant RL_STABLE_BORROW_RATE_OVERFLOW = "55"; // Stable borrow rate overflows uint128 \tstring public constant CT_INVALID_MINT_AMOUNT = "56"; //invalid amount to mint \tstring public constant LP_FAILED_REPAY_WITH_COLLATERAL = "57"; \tstring public constant CT_INVALID_BURN_AMOUNT = "58"; //invalid amount to burn \tstring public constant LP_FAILED_COLLATERAL_SWAP = "60"; \tstring public constant LP_INVALID_EQUAL_ASSETS_TO_SWAP = "61"; \tstring public constant LP_REENTRANCY_NOT_ALLOWED = "62"; \tstring public constant LP_CALLER_MUST_BE_AN_ATOKEN = "63"; \tstring public constant LP_IS_PAUSED = "64"; // 'Pool is paused' \tstring public constant LP_NO_MORE_RESERVES_ALLOWED = "65"; \tstring public constant LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN = "66"; \tstring public constant RC_INVALID_LTV = "67"; \tstring public constant RC_INVALID_LIQ_THRESHOLD = "68"; \tstring public constant RC_INVALID_LIQ_BONUS = "69"; \tstring public constant RC_INVALID_DECIMALS = "70"; \tstring public constant RC_INVALID_RESERVE_FACTOR = "71"; \tstring public constant LPAPR_INVALID_ADDRESSES_PROVIDER_ID = "72"; \tstring public constant VL_INCONSISTENT_FLASHLOAN_PARAMS = "73"; \tstring public constant LP_INCONSISTENT_PARAMS_LENGTH = "74"; \tstring public constant UL_INVALID_INDEX = "77"; \tstring public constant LP_NOT_CONTRACT = "78"; \tstring public constant SDT_STABLE_DEBT_OVERFLOW = "79"; \tstring public constant SDT_BURN_EXCEEDS_BALANCE = "80"; \t/** \t * @dev Custom Radiant codes added +200 to avoid conflicts with the AaveV2/V3 ones \t * @custom:borrow-and-supply-caps \t */ \tstring public constant INVALID_BORROW_CAP = "201"; // Invalid borrow cap value \tstring public constant INVALID_SUPPLY_CAP = "202"; // Invalid supply cap value \tstring public constant BORROW_CAP_EXCEEDED = "203"; // Borrow cap is exceeded \tstring public constant SUPPLY_CAP_EXCEEDED = "204"; // Supply cap is exceeded \tenum CollateralManagerErrors { \t\tNO_ERROR, \t\tNO_COLLATERAL_AVAILABLE, \t\tCOLLATERAL_CANNOT_BE_LIQUIDATED, \t\tCURRRENCY_NOT_BORROWED, \t\tHEALTH_FACTOR_ABOVE_THRESHOLD, \t\tNOT_ENOUGH_LIQUIDITY, \t\tNO_ACTIVE_RESERVE, \t\tHEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD, \t\tINVALID_EQUAL_ASSETS_TO_SWAP, \t\tFROZEN_RESERVE \t} } // SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.12; import {Errors} from "../helpers/Errors.sol"; /** * @title WadRayMath library * @author Aave * @dev Provides mul and div function for wads (decimal numbers with 18 digits precision) and rays (decimals with 27 digits) **/ library WadRayMath { \tuint256 internal constant WAD = 1e18; \tuint256 internal constant halfWAD = WAD / 2; \tuint256 internal constant RAY = 1e27; \tuint256 internal constant halfRAY = RAY / 2; \tuint256 internal constant WAD_RAY_RATIO = 1e9; \t/** \t * @return One ray, 1e27 \t **/ \tfunction ray() internal pure returns (uint256) { \t\treturn RAY; \t} \t/** \t * @return One wad, 1e18 \t **/ \tfunction wad() internal pure returns (uint256) { \t\treturn WAD; \t} \t/** \t * @return Half ray, 1e27/2 \t **/ \tfunction halfRay() internal pure returns (uint256) { \t\treturn halfRAY; \t} \t/** \t * @return Half ray, 1e18/2 \t **/ \tfunction halfWad() internal pure returns (uint256) { \t\treturn halfWAD; \t} \t/** \t * @dev Multiplies two wad, rounding half up to the nearest wad \t * @param a Wad \t * @param b Wad \t * @return The result of a*b, in wad \t **/ \tfunction wadMul(uint256 a, uint256 b) internal pure returns (uint256) { \t\tif (a == 0 || b == 0) { \t\t\treturn 0; \t\t} \t\trequire(a <= (type(uint256).max - halfWAD) / b, Errors.MATH_MULTIPLICATION_OVERFLOW); \t\treturn (a * b + halfWAD) / WAD; \t} \t/** \t * @dev Divides two wad, rounding half up to the nearest wad \t * @param a Wad \t * @param b Wad \t * @return The result of a/b, in wad \t **/ \tfunction wadDiv(uint256 a, uint256 b) internal pure returns (uint256) { \t\trequire(b != 0, Errors.MATH_DIVISION_BY_ZERO); \t\tuint256 halfB = b / 2; \t\trequire(a <= (type(uint256).max - halfB) / WAD, Errors.MATH_MULTIPLICATION_OVERFLOW); \t\treturn (a * WAD + halfB) / b; \t} \t/** \t * @dev Multiplies two ray, rounding half up to the nearest ray \t * @param a Ray \t * @param b Ray \t * @return The result of a*b, in ray \t **/ \tfunction rayMul(uint256 a, uint256 b) internal pure returns (uint256) { \t\tif (a == 0 || b == 0) { \t\t\treturn 0; \t\t} \t\trequire(a <= (type(uint256).max - halfRAY) / b, Errors.MATH_MULTIPLICATION_OVERFLOW); \t\treturn (a * b + halfRAY) / RAY; \t} \t/** \t * @dev Divides two ray, rounding half up to the nearest ray \t * @param a Ray \t * @param b Ray \t * @return The result of a/b, in ray \t **/ \tfunction rayDiv(uint256 a, uint256 b) internal pure returns (uint256) { \t\trequire(b != 0, Errors.MATH_DIVISION_BY_ZERO); \t\tuint256 halfB = b / 2; \t\trequire(a <= (type(uint256).max - halfB) / RAY, Errors.MATH_MULTIPLICATION_OVERFLOW); \t\treturn (a * RAY + halfB) / b; \t} \t/** \t * @dev Casts ray down to wad \t * @param a Ray \t * @return a casted to wad, rounded half up to the nearest wad \t **/ \tfunction rayToWad(uint256 a) internal pure returns (uint256) { \t\tuint256 halfRatio = WAD_RAY_RATIO / 2; \t\tuint256 result = halfRatio + a; \t\trequire(result >= halfRatio, Errors.MATH_ADDITION_OVERFLOW); \t\treturn result / WAD_RAY_RATIO; \t} \t/** \t * @dev Converts wad up to ray \t * @param a Wad \t * @return a converted in ray \t **/ \tfunction wadToRay(uint256 a) internal pure returns (uint256) { \t\tuint256 result = a * WAD_RAY_RATIO; \t\trequire(result / WAD_RAY_RATIO == a, Errors.MATH_MULTIPLICATION_OVERFLOW); \t\treturn result; \t} } // SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.12; library DataTypes { \t// refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties. \tstruct ReserveData { \t\t//stores the reserve configuration \t\tReserveConfigurationMap configuration; \t\t//the liquidity index. Expressed in ray \t\tuint128 liquidityIndex; \t\t//variable borrow index. Expressed in ray \t\tuint128 variableBorrowIndex; \t\t//the current supply rate. Expressed in ray \t\tuint128 currentLiquidityRate; \t\t//the current variable borrow rate. Expressed in ray \t\tuint128 currentVariableBorrowRate; \t\t//the current stable borrow rate. Expressed in ray \t\tuint128 currentStableBorrowRate; \t\tuint40 lastUpdateTimestamp; \t\t//tokens addresses \t\taddress aTokenAddress; \t\taddress stableDebtTokenAddress; \t\taddress variableDebtTokenAddress; \t\t//address of the interest rate strategy \t\taddress interestRateStrategyAddress; \t\t//the id of the reserve. Represents the position in the list of the active reserves \t\tuint8 id; \t} \tstruct ReserveConfigurationMap { \t\t//bit 0-15: LTV \t\t//bit 16-31: Liq. threshold \t\t//bit 32-47: Liq. bonus \t\t//bit 48-55: Decimals \t\t//bit 56: Reserve is active \t\t//bit 57: reserve is frozen \t\t//bit 58: borrowing is enabled \t\t//bit 59: stable rate borrowing enabled \t\t//bit 60-63: reserved \t\t//bit 64-79: reserve factor \t\t///@custom:borrow-and-supply-caps \t\t//bit 80-115 borrow cap in whole tokens, borrowCap == 0 => no cap \t\t//bit 116-151 supply cap in whole tokens, supplyCap == 0 => no cap \t\tuint256 data; \t} \tstruct UserConfigurationMap { \t\tuint256 data; \t} \tenum InterestRateMode { \t\tNONE, \t\tSTABLE, \t\tVARIABLE \t} } // SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.12; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {ILendingPool} from "../../interfaces/ILendingPool.sol"; import {IAToken} from "../../interfaces/IAToken.sol"; import {WadRayMath} from "../libraries/math/WadRayMath.sol"; import {Errors} from "../libraries/helpers/Errors.sol"; import {VersionedInitializable} from "../libraries/aave-upgradeability/VersionedInitializable.sol"; import {IncentivizedERC20} from "./IncentivizedERC20.sol"; import {IAaveIncentivesController} from "../../interfaces/IAaveIncentivesController.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import {IMiddleFeeDistribution} from "../../interfaces/IMiddleFeeDistribution.sol"; import {ILendingPoolAddressesProvider} from "../../interfaces/ILendingPoolAddressesProvider.sol"; /** * @title Aave ERC20 AToken * @dev Implementation of the interest bearing token for the Aave protocol * @author Aave */ contract AToken is VersionedInitializable, IncentivizedERC20("ATOKEN_IMPL", "ATOKEN_IMPL", 0), IAToken { \tusing WadRayMath for uint256; \tusing SafeERC20 for IERC20; \tusing SafeMath for uint256; \tbytes public constant EIP712_REVISION = bytes("1"); \tbytes32 internal constant EIP712_DOMAIN = \t\tkeccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); \tbytes32 public constant PERMIT_TYPEHASH = \t\tkeccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); \tuint256 public constant ATOKEN_REVISION = 0x2; \t/// @dev owner => next valid nonce to submit with permit() \tmapping(address => uint256) public _nonces; \tbytes32 public DOMAIN_SEPARATOR; \taddress internal _treasury; \tIAaveIncentivesController internal _incentivesController; \terror AddressZero(); \tevent TreasuryAddressUpdated(address indexed treasury); \tmodifier onlyLendingPool() { \t\trequire(_msgSender() == address(_pool), Errors.CT_CALLER_MUST_BE_LENDING_POOL); \t\t_; \t} \tmodifier onlyPoolAdmin() { \t\tILendingPoolAddressesProvider lpAddressProvider = ILendingPoolAddressesProvider(_pool.getAddressesProvider()); \t\trequire(lpAddressProvider.getPoolAdmin() == msg.sender, Errors.LP_CALLER_NOT_LENDING_POOL_CONFIGURATOR); \t\t_; \t} \tfunction getRevision() internal pure virtual override returns (uint256) { \t\treturn ATOKEN_REVISION; \t} \tconstructor() { \t\t_disableInitializers(); \t} \t/** \t * @dev Initializes the aToken \t * @param pool The address of the lending pool where this aToken will be used \t * @param treasury The address of the Aave treasury, receiving the fees on this aToken \t * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH) \t * @param incentivesController The smart contract managing potential incentives distribution \t * @param aTokenDecimals The decimals of the aToken, same as the underlying asset's \t * @param aTokenName The name of the aToken \t * @param aTokenSymbol The symbol of the aToken \t */ \tfunction initialize( \t\tILendingPool pool, \t\taddress treasury, \t\taddress underlyingAsset, \t\tIAaveIncentivesController incentivesController, \t\tuint8 aTokenDecimals, \t\tstring calldata aTokenName, \t\tstring calldata aTokenSymbol, \t\tbytes calldata params \t) external override initializer { \t\tuint256 chainId; \t\t//solium-disable-next-line \t\tassembly { \t\t\tchainId := chainid() \t\t} \t\tDOMAIN_SEPARATOR = keccak256( \t\t\tabi.encode(EIP712_DOMAIN, keccak256(bytes(aTokenName)), keccak256(EIP712_REVISION), chainId, address(this)) \t\t); \t\t_setName(aTokenName); \t\t_setSymbol(aTokenSymbol); \t\t_setDecimals(aTokenDecimals); \t\t_pool = pool; \t\t_treasury = treasury; \t\t_underlyingAsset = underlyingAsset; \t\t_incentivesController = incentivesController; \t\temit Initialized( \t\t\tunderlyingAsset, \t\t\taddress(pool), \t\t\ttreasury, \t\t\taddress(incentivesController), \t\t\taTokenDecimals, \t\t\taTokenName, \t\t\taTokenSymbol, \t\t\tparams \t\t); \t} \t/** \t * @dev Burns aTokens from `user` and sends the equivalent amount of underlying to `receiverOfUnderlying` \t * - Only callable by the LendingPool, as extra state updates there need to be managed \t * @param user The owner of the aTokens, getting them burned \t * @param receiverOfUnderlying The address that will receive the underlying \t * @param amount The amount being burned \t * @param index The new liquidity index of the reserve \t **/ \tfunction burn( \t\taddress user, \t\taddress receiverOfUnderlying, \t\tuint256 amount, \t\tuint256 index \t) external override onlyLendingPool { \t\tuint256 amountScaled = amount.rayDiv(index); \t\trequire(amountScaled != 0, Errors.CT_INVALID_BURN_AMOUNT); \t\t_burn(user, amountScaled); \t\tIERC20(_underlyingAsset).safeTransfer(receiverOfUnderlying, amount); \t\temit Transfer(user, address(0), amount); \t\temit Burn(user, receiverOfUnderlying, amount, index); \t} \t/** \t * @dev Mints `amount` aTokens to `user` \t * - Only callable by the LendingPool, as extra state updates there need to be managed \t * @param user The address receiving the minted tokens \t * @param amount The amount of tokens getting minted \t * @param index The new liquidity index of the reserve \t * @return `true` if the the previous balance of the user was 0 \t */ \tfunction mint(address user, uint256 amount, uint256 index) external override onlyLendingPool returns (bool) { \t\tuint256 previousBalance = super.balanceOf(user); \t\tuint256 amountScaled = amount.rayDiv(index); \t\trequire(amountScaled != 0, Errors.CT_INVALID_MINT_AMOUNT); \t\t_mint(user, amountScaled); \t\temit Transfer(address(0), user, amount); \t\temit Mint(user, amount, index); \t\treturn previousBalance == 0; \t} \t/** \t * @dev Mints aTokens to the reserve treasury \t * - Only callable by the LendingPool \t * @param amount The amount of tokens getting minted \t * @param index The new liquidity index of the reserve \t */ \tfunction mintToTreasury(uint256 amount, uint256 index) external override onlyLendingPool { \t\tif (amount == 0) { \t\t\treturn; \t\t} \t\taddress treasury = _treasury; \t\t// Compared to the normal mint, we don't check for rounding errors. \t\t// The amount to mint can easily be very small since it is a fraction of the interest ccrued. \t\t// In that case, the treasury will experience a (very small) loss, but it \t\t// wont cause potentially valid transactions to fail. \t\t_mint(treasury, amount.rayDiv(index)); \t\temit Transfer(address(0), treasury, amount); \t\temit Mint(treasury, amount, index); \t} \t/** \t * @dev Transfers aTokens in the event of a borrow being liquidated, in case the liquidators reclaims the aToken \t * - Only callable by the LendingPool \t * @param from The address getting liquidated, current owner of the aTokens \t * @param to The recipient \t * @param value The amount of tokens getting transferred \t **/ \tfunction transferOnLiquidation(address from, address to, uint256 value) external override onlyLendingPool { \t\t// Being a normal transfer, the Transfer() and BalanceTransfer() are emitted \t\t// so no need to emit a specific event here \t\t_transfer(from, to, value, false); \t\temit Transfer(from, to, value); \t} \t/** \t * @dev Calculates the balance of the user: principal balance + interest generated by the principal \t * @param user The user whose balance is calculated \t * @return The balance of the user \t **/ \tfunction balanceOf(address user) public view override(IncentivizedERC20, IERC20) returns (uint256) { \t\treturn super.balanceOf(user).rayMul(_pool.getReserveNormalizedIncome(_underlyingAsset)); \t} \t/** \t * @dev Returns the scaled balance of the user. The scaled balance is the sum of all the \t * updated stored balance divided by the reserve's liquidity index at the moment of the update \t * @param user The user whose balance is calculated \t * @return The scaled balance of the user \t **/ \tfunction scaledBalanceOf(address user) external view override returns (uint256) { \t\treturn super.balanceOf(user); \t} \t/** \t * @dev Returns the scaled balance of the user and the scaled total supply. \t * @param user The address of the user \t * @return The scaled balance of the user \t * @return The scaled balance and the scaled total supply \t **/ \tfunction getScaledUserBalanceAndSupply(address user) external view override returns (uint256, uint256) { \t\treturn (super.balanceOf(user), super.totalSupply()); \t} \t/** \t * @dev calculates the total supply of the specific aToken \t * since the balance of every single user increases over time, the total supply \t * does that too. \t * @return the current total supply \t **/ \tfunction totalSupply() public view override(IncentivizedERC20, IERC20) returns (uint256) { \t\tuint256 currentSupplyScaled = super.totalSupply(); \t\tif (currentSupplyScaled == 0) { \t\t\treturn 0; \t\t} \t\treturn currentSupplyScaled.rayMul(_pool.getReserveNormalizedIncome(_underlyingAsset)); \t} \t/** \t * @dev Returns the scaled total supply of the variable debt token. Represents sum(debt/index) \t * @return the scaled total supply \t **/ \tfunction scaledTotalSupply() public view virtual override returns (uint256) { \t\treturn super.totalSupply(); \t} \t/** \t * @dev Returns the address of the Aave treasury, receiving the fees on this aToken \t **/ \tfunction RESERVE_TREASURY_ADDRESS() public view returns (address) { \t\treturn _treasury; \t} \t/** \t * @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH) \t **/ \tfunction UNDERLYING_ASSET_ADDRESS() public view override returns (address) { \t\treturn _underlyingAsset; \t} \t/** \t * @dev Returns the address of the lending pool where this aToken is used \t **/ \tfunction POOL() public view returns (ILendingPool) { \t\treturn _pool; \t} \t/** \t * @dev For internal usage in the logic of the parent contract IncentivizedERC20 \t **/ \tfunction _getIncentivesController() internal view override returns (IAaveIncentivesController) { \t\treturn _incentivesController; \t} \t/** \t * @dev Returns the address of the incentives controller contract \t **/ \tfunction getIncentivesController() external view override returns (IAaveIncentivesController) { \t\treturn _getIncentivesController(); \t} \t/** \t * @dev Updates the treasury address \t * @param treasury The new treasury address \t */ \tfunction setTreasuryAddress(address treasury) external onlyPoolAdmin { \t\tif (treasury == address(0)) revert AddressZero(); \t\t_treasury = treasury; \t\temit TreasuryAddressUpdated(treasury); \t} \t/** \t * @dev Transfers the underlying asset to `target`. Used by the LendingPool to transfer \t * assets in borrow(), withdraw() and flashLoan() \t * @param target The recipient of the aTokens \t * @param amount The amount getting transferred \t * @return The amount transferred \t **/ \tfunction transferUnderlyingTo(address target, uint256 amount) external override onlyLendingPool returns (uint256) { \t\tIERC20(_underlyingAsset).safeTransfer(target, amount); \t\treturn amount; \t} \t/** \t * @dev Invoked to execute actions on the aToken side after a repayment. \t * @param user The user executing the repayment \t * @param amount The amount getting repaid \t **/ \tfunction handleRepayment(address user, uint256 amount) external override onlyLendingPool {} \t/** \t * @dev implements the permit function as for \t * https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md \t * @param owner The owner of the funds \t * @param spender The spender \t * @param value The amount \t * @param deadline The deadline timestamp, type(uint256).max for max deadline \t * @param v Signature param \t * @param s Signature param \t * @param r Signature param \t */ \tfunction permit( \t\taddress owner, \t\taddress spender, \t\tuint256 value, \t\tuint256 deadline, \t\tuint8 v, \t\tbytes32 r, \t\tbytes32 s \t) external { \t\trequire(owner != address(0), "INVALID_OWNER"); \t\t//solium-disable-next-line \t\trequire(block.timestamp <= deadline, "INVALID_EXPIRATION"); \t\tuint256 currentValidNonce = _nonces[owner]; \t\tbytes32 digest = keccak256( \t\t\tabi.encodePacked( \t\t\t\t"\\x19\\x01", \t\t\t\tDOMAIN_SEPARATOR, \t\t\t\tkeccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, currentValidNonce, deadline)) \t\t\t) \t\t); \t\trequire(owner == ecrecover(digest, v, r, s), "INVALID_SIGNATURE"); \t\t_nonces[owner] = currentValidNonce.add(1); \t\t_approve(owner, spender, value); \t} \t/** \t * @dev Transfers the aTokens between two users. Validates the transfer \t * (ie checks for valid HF after the transfer) if required \t * @param from The source address \t * @param to The destination address \t * @param amount The amount getting transferred \t * @param validate `true` if the transfer needs to be validated \t **/ \tfunction _transfer(address from, address to, uint256 amount, bool validate) internal { \t\taddress underlyingAsset = _underlyingAsset; \t\tILendingPool pool = _pool; \t\tuint256 index = pool.getReserveNormalizedIncome(underlyingAsset); \t\tuint256 fromBalanceBefore = super.balanceOf(from).rayMul(index); \t\tuint256 toBalanceBefore = super.balanceOf(to).rayMul(index); \t\tsuper._transfer(from, to, amount.rayDiv(index)); \t\tif (validate) { \t\t\tpool.finalizeTransfer(underlyingAsset, from, to, amount, fromBalanceBefore, toBalanceBefore); \t\t} \t\temit BalanceTransfer(from, to, amount, index); \t} \t/** \t * @dev Overrides the parent _transfer to force validated transfer() and transferFrom() \t * @param from The source address \t * @param to The destination address \t * @param amount The amount getting transferred \t **/ \tfunction _transfer(address from, address to, uint256 amount) internal override { \t\t_transfer(from, to, amount, true); \t} } // SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.12; import {Context} from "../../dependencies/openzeppelin/contracts/Context.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import {IAaveIncentivesController} from "../../interfaces/IAaveIncentivesController.sol"; import {ILendingPoolAddressesProvider} from "../../interfaces/ILendingPoolAddressesProvider.sol"; import {IPriceOracle} from "../../interfaces/IPriceOracle.sol"; import {ILendingPool} from "../../interfaces/ILendingPool.sol"; /** * @title ERC20 * @notice Basic ERC20 implementation * @author Aave, inspired by the Openzeppelin ERC20 implementation **/ abstract contract IncentivizedERC20 is Context, IERC20, IERC20Metadata { \tusing SafeMath for uint256; \tmapping(address => uint256) internal _balances; \tmapping(address => mapping(address => uint256)) private _allowances; \tuint256 internal _totalSupply; \tstring private _name; \tstring private _symbol; \tuint8 private _decimals; \tILendingPool internal _pool; \taddress internal _underlyingAsset; \tconstructor(string memory name_, string memory symbol_, uint8 decimals_) { \t\t_name = name_; \t\t_symbol = symbol_; \t\t_decimals = decimals_; \t} \t/** \t * @return The name of the token \t **/ \tfunction name() public view returns (string memory) { \t\treturn _name; \t} \t/** \t * @return The symbol of the token \t **/ \tfunction symbol() public view returns (string memory) { \t\treturn _symbol; \t} \t/** \t * @return The decimals of the token \t **/ \tfunction decimals() public view returns (uint8) { \t\treturn _decimals; \t} \t/** \t * @return The total supply of the token \t **/ \tfunction totalSupply() public view virtual returns (uint256) { \t\treturn _totalSupply; \t} \t/** \t * @return The balance of the token \t **/ \tfunction balanceOf(address account) public view virtual returns (uint256) { \t\treturn _balances[account]; \t} \t/** \t * @return Abstract function implemented by the child aToken/debtToken. \t * Done this way in order to not break compatibility with previous versions of aTokens/debtTokens \t **/ \tfunction _getIncentivesController() internal view virtual returns (IAaveIncentivesController); \t/** \t * @dev Executes a transfer of tokens from _msgSender() to recipient \t * @param recipient The recipient of the tokens \t * @param amount The amount of tokens being transferred \t * @return `true` if the transfer succeeds, `false` otherwise \t **/ \tfunction transfer(address recipient, uint256 amount) public virtual returns (bool) { \t\t_transfer(_msgSender(), recipient, amount); \t\temit Transfer(_msgSender(), recipient, amount); \t\treturn true; \t} \t/** \t * @dev Returns the allowance of spender on the tokens owned by owner \t * @param owner The owner of the tokens \t * @param spender The user allowed to spend the owner's tokens \t * @return The amount of owner's tokens spender is allowed to spend \t **/ \tfunction allowance(address owner, address spender) public view virtual returns (uint256) { \t\treturn _allowances[owner][spender]; \t} \t/** \t * @dev Allows `spender` to spend the tokens owned by _msgSender() \t * @param spender The user allowed to spend _msgSender() tokens \t * @return `true` \t **/ \tfunction approve(address spender, uint256 amount) public virtual returns (bool) { \t\t_approve(_msgSender(), spender, amount); \t\treturn true; \t} \t/** \t * @dev Executes a transfer of token from sender to recipient, if _msgSender() is allowed to do so \t * @param sender The owner of the tokens \t * @param recipient The recipient of the tokens \t * @param amount The amount of tokens being transferred \t * @return `true` if the transfer succeeds, `false` otherwise \t **/ \tfunction transferFrom(address sender, address recipient, uint256 amount) public virtual returns (bool) { \t\t_transfer(sender, recipient, amount); \t\t_approve( \t\t\tsender, \t\t\t_msgSender(), \t\t\t_allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance") \t\t); \t\temit Transfer(sender, recipient, amount); \t\treturn true; \t} \t/** \t * @dev Increases the allowance of spender to spend _msgSender() tokens \t * @param spender The user allowed to spend on behalf of _msgSender() \t * @param addedValue The amount being added to the allowance \t * @return `true` \t **/ \tfunction increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { \t\t_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); \t\treturn true; \t} \t/** \t * @dev Decreases the allowance of spender to spend _msgSender() tokens \t * @param spender The user allowed to spend on behalf of _msgSender() \t * @param subtractedValue The amount being subtracted to the allowance \t * @return `true` \t **/ \tfunction decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { \t\t_approve( \t\t\t_msgSender(), \t\t\tspender, \t\t\t_allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero") \t\t); \t\treturn true; \t} \tfunction _transfer(address sender, address recipient, uint256 amount) internal virtual { \t\trequire(sender != address(0), "ERC20: transfer from the zero address"); \t\trequire(recipient != address(0), "ERC20: transfer to the zero address"); \t\t_beforeTokenTransfer(sender, recipient, amount); \t\tuint256 senderBalance = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); \t\tif (address(_getIncentivesController()) != address(0)) { \t\t\t// uint256 currentTotalSupply = _totalSupply; \t\t\t_getIncentivesController().handleActionBefore(sender); \t\t\tif (sender != recipient) { \t\t\t\t_getIncentivesController().handleActionBefore(recipient); \t\t\t} \t\t} \t\t_balances[sender] = senderBalance; \t\tuint256 recipientBalance = _balances[recipient].add(amount); \t\t_balances[recipient] = recipientBalance; \t\tif (address(_getIncentivesController()) != address(0)) { \t\t\tuint256 currentTotalSupply = _totalSupply; \t\t\t_getIncentivesController().handleActionAfter(sender, _balances[sender], currentTotalSupply); \t\t\tif (sender != recipient) { \t\t\t\t_getIncentivesController().handleActionAfter(recipient, _balances[recipient], currentTotalSupply); \t\t\t} \t\t} \t} \tfunction _mint(address account, uint256 amount) internal virtual { \t\trequire(account != address(0), "ERC20: mint to the zero address"); \t\t_beforeTokenTransfer(address(0), account, amount); \t\tuint256 currentTotalSupply = _totalSupply.add(amount); \t\tuint256 accountBalance = _balances[account].add(amount); \t\tif (address(_getIncentivesController()) != address(0)) { \t\t\t_getIncentivesController().handleActionBefore(account); \t\t} \t\t_totalSupply = currentTotalSupply; \t\t_balances[account] = accountBalance; \t\tif (address(_getIncentivesController()) != address(0)) { \t\t\t_getIncentivesController().handleActionAfter(account, accountBalance, currentTotalSupply); \t\t} \t} \tfunction _burn(address account, uint256 amount) internal virtual { \t\trequire(account != address(0), "ERC20: burn from the zero address"); \t\t_beforeTokenTransfer(account, address(0), amount); \t\tuint256 currentTotalSupply = _totalSupply.sub(amount); \t\tuint256 accountBalance = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); \t\tif (address(_getIncentivesController()) != address(0)) { \t\t\t_getIncentivesController().handleActionBefore(account); \t\t} \t\t_totalSupply = currentTotalSupply; \t\t_balances[account] = accountBalance; \t\tif (address(_getIncentivesController()) != address(0)) { \t\t\t_getIncentivesController().handleActionAfter(account, accountBalance, currentTotalSupply); \t\t} \t} \tfunction _approve(address owner, address spender, uint256 amount) internal virtual { \t\trequire(owner != address(0), "ERC20: approve from the zero address"); \t\trequire(spender != address(0), "ERC20: approve to the zero address"); \t\t_allowances[owner][spender] = amount; \t\temit Approval(owner, spender, amount); \t} \tfunction _setName(string memory newName) internal { \t\t_name = newName; \t} \tfunction _setSymbol(string memory newSymbol) internal { \t\t_symbol = newSymbol; \t} \tfunction _setDecimals(uint8 newDecimals) internal { \t\t_decimals = newDecimals; \t} \tfunction _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} \tfunction getAssetPrice() external view returns (uint256) { \t\tILendingPoolAddressesProvider provider = _pool.getAddressesProvider(); \t\taddress oracle = provider.getPriceOracle(); \t\treturn IPriceOracle(oracle).getAssetPrice(_underlyingAsset); \t} }