Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x61010060 | 22973156 | 153 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
VariableDebtTokenInstance
Compiler Version
v0.8.27+commit.40a35a09
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {VersionedInitializable} from '../misc/aave-upgradeability/VersionedInitializable.sol';
import {VariableDebtToken, IPool, IInitializableDebtToken, Errors} from '../protocol/tokenization/VariableDebtToken.sol';
/**
* @title Aave ERC20 VariableDebtToken Instance
* @author BGD Labs
* @notice Instance of the variable debt token for the Aave protocol
*/
contract VariableDebtTokenInstance is VariableDebtToken {
uint256 public constant DEBT_TOKEN_REVISION = 4;
constructor(IPool pool, address rewardsController) VariableDebtToken(pool, rewardsController) {}
/// @inheritdoc VersionedInitializable
function getRevision() internal pure virtual override returns (uint256) {
return DEBT_TOKEN_REVISION;
}
/// @inheritdoc IInitializableDebtToken
function initialize(
IPool initializingPool,
address underlyingAsset,
uint8 debtTokenDecimals,
string memory debtTokenName,
string memory debtTokenSymbol,
bytes calldata params
) external override initializer {
require(initializingPool == POOL, Errors.PoolAddressesDoNotMatch());
_setName(debtTokenName);
_setSymbol(debtTokenSymbol);
_setDecimals(debtTokenDecimals);
_underlyingAsset = underlyingAsset;
_domainSeparator = _calculateDomainSeparator();
emit Initialized(
underlyingAsset,
address(POOL),
address(REWARDS_CONTROLLER),
debtTokenDecimals,
debtTokenName,
debtTokenSymbol,
params
);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
/**
* @title VersionedInitializable
* @author Aave, inspired by the OpenZeppelin Initializable contract
* @notice Helper contract to implement initializer functions. To use it, replace
* the constructor with a function that has the `initializer` modifier.
* @dev 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.
*/
abstract contract VersionedInitializable {
/**
* @dev Initializes the implementation contract at the current revision.
* In practice this breaks further initialization of the implementation.
*/
constructor() {
// break the initialize
lastInitializedRevision = getRevision();
}
/**
* @dev Indicates that the contract has been initialized.
*/
uint256 private lastInitializedRevision = 0;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private initializing;
/**
* @dev Modifier to use in the initializer function of a contract.
*/
modifier initializer() {
uint256 revision = getRevision();
require(
initializing || isConstructor() || revision > lastInitializedRevision,
'Contract instance has already been initialized'
);
bool isTopLevelCall = !initializing;
if (isTopLevelCall) {
initializing = true;
lastInitializedRevision = revision;
}
_;
if (isTopLevelCall) {
initializing = false;
}
}
/**
* @notice Returns the revision number of the contract
* @dev Needs to be defined in the inherited class as a constant.
* @return The revision number
*/
function getRevision() internal pure virtual returns (uint256);
/**
* @notice Returns true if and only if the function is running in the constructor
* @return True if the function is running in the constructor
*/
function isConstructor() private view returns (bool) {
// extcodesize checks the size of the code stored in an address, and
// address returns the current address. Since the code is still not
// deployed when running a constructor, any checks on its code size will
// yield zero, making it an effective way to detect if a contract is
// under construction or not.
uint256 cs;
//solium-disable-next-line
assembly {
cs := extcodesize(address())
}
return cs == 0;
}
// Reserved storage space to allow for layout changes in the future.
uint256[50] private ______gap;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.10;
import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';
import {SafeCast} from 'openzeppelin-contracts/contracts/utils/math/SafeCast.sol';
import {Errors} from '../libraries/helpers/Errors.sol';
import {IPool} from '../../interfaces/IPool.sol';
import {IInitializableDebtToken} from '../../interfaces/IInitializableDebtToken.sol';
import {IVariableDebtToken} from '../../interfaces/IVariableDebtToken.sol';
import {EIP712Base} from './base/EIP712Base.sol';
import {DebtTokenBase} from './base/DebtTokenBase.sol';
import {ScaledBalanceTokenBase} from './base/ScaledBalanceTokenBase.sol';
import {TokenMath} from '../libraries/helpers/TokenMath.sol';
/**
* @title VariableDebtToken
* @author Aave
* @notice Implements a variable debt token to track the borrowing positions of users
* at variable rate mode
* @dev Transfer and approve functionalities are disabled since its a non-transferable token
*/
abstract contract VariableDebtToken is DebtTokenBase, ScaledBalanceTokenBase, IVariableDebtToken {
using TokenMath for uint256;
using SafeCast for uint256;
// @note This gap is made only to add the `__DEPRECATED_AND_NEVER_TO_BE_REUSED` variable
// The length of this gap can be decreased in order to add new variables
uint256[3] private __unusedGap;
// @note deprecated in v3.4.0 upgrade in the GHO vToken.
// This storage slot can't be used in all vTokens, because the GHO vToken
// had a mapping here (before v3.4.0) and right now has some non-zero mapping values in this slot.
// old version: mapping(address => GhoUserState) internal _ghoUserState
// This storage slot MUST NOT be reused to avoid storage layout conflicts.
bytes32 private __DEPRECATED_AND_NEVER_TO_BE_REUSED;
/**
* @dev Constructor.
* @param pool The address of the Pool contract
* @param rewardsController The address of the rewards controller contract
*/
constructor(
IPool pool,
address rewardsController
)
DebtTokenBase()
ScaledBalanceTokenBase(
pool,
'VARIABLE_DEBT_TOKEN_IMPL',
'VARIABLE_DEBT_TOKEN_IMPL',
0,
rewardsController
)
{
// Intentionally left blank
}
/// @inheritdoc IInitializableDebtToken
function initialize(
IPool initializingPool,
address underlyingAsset,
uint8 debtTokenDecimals,
string memory debtTokenName,
string memory debtTokenSymbol,
bytes calldata params
) external virtual;
/// @inheritdoc IERC20
function balanceOf(address user) public view virtual override returns (uint256) {
return
super.balanceOf(user).getVTokenBalance(
POOL.getReserveNormalizedVariableDebt(_underlyingAsset)
);
}
/// @inheritdoc IVariableDebtToken
function mint(
address user,
address onBehalfOf,
uint256 amount,
uint256 scaledAmount,
uint256 index
) external virtual override onlyPool returns (uint256) {
uint256 scaledBalanceOfUser = super.balanceOf(user);
if (user != onBehalfOf) {
// This comment explains the logic behind the borrow allowance spent calculation.
//
// Problem:
// Simply decreasing the allowance by the input `amount` is not ideal for scaled-balance tokens.
// Due to rounding, the actual increase in the user's debt (`debt_increase`) can be slightly
// larger than the input `amount`.
//
// Definitions:
// - `amount`: The unscaled amount to be borrowed, passed as the `amount` argument.
// - `debt_increase`: The actual unscaled debt increase for the user.
// - `allowance_spent`: The unscaled amount deducted from the delegatee's borrow allowance. Equivalent to `debt_increase`.
//
// Solution:
// To handle this, `allowance_spent` must be exactly equal to `debt_increase`.
// We calculate `debt_increase` precisely by simulating the effect of the borrow on the user's balance.
// By passing `debt_increase` to `_decreaseBorrowAllowance`, we ensure `allowance_spent` is as close as possible to `debt_increase`.
//
// Backward Compatibility & Guarantees:
// This implementation is backward-compatible and secure. The `_decreaseBorrowAllowance` function has a critical feature:
// 1. It REQUIRES the borrow allowance to be >= `amount` (the user's requested borrow amount).
// 2. The amount consumed from the allowance is `debt_increase`, but it is capped at the `currentAllowance`.
// This means if a user has a borrow allowance of 100 wei and `borrow` is called with an `amount` of 100, the call will succeed
// even if the calculated `debt_increase` is 101 wei. In that specific scenario, the allowance consumed will be 100 wei (since that is the `currentAllowance`),
// and the transaction will not revert. But if the allowance is 101 wei, then the allowance consumed will be 101 wei.
//
// uint256 debt_increase = balanceAfter - balanceBefore = (scaledBalanceOfUser + scaledAmount).getVTokenBalance(index) - scaledBalanceOfUser.getVTokenBalance(index);
// Due to limitations of the solidity compiler, the calculation is inlined for gas efficiency.
_decreaseBorrowAllowance(
onBehalfOf,
user,
amount,
(scaledBalanceOfUser + scaledAmount).getVTokenBalance(index) -
scaledBalanceOfUser.getVTokenBalance(index)
);
}
_mintScaled({
caller: user,
onBehalfOf: onBehalfOf,
amountScaled: scaledAmount,
index: index,
getTokenBalance: TokenMath.getVTokenBalance
});
return scaledTotalSupply();
}
/// @inheritdoc IVariableDebtToken
function burn(
address from,
uint256 scaledAmount,
uint256 index
) external virtual override onlyPool returns (bool, uint256) {
return (
_burnScaled({
user: from,
target: address(0),
amountScaled: scaledAmount,
index: index,
getTokenBalance: TokenMath.getVTokenBalance
}),
scaledTotalSupply()
);
}
/// @inheritdoc IERC20
function totalSupply() public view virtual override returns (uint256) {
return
super.totalSupply().getVTokenBalance(POOL.getReserveNormalizedVariableDebt(_underlyingAsset));
}
/// @inheritdoc EIP712Base
function _EIP712BaseId() internal view override returns (string memory) {
return name();
}
/**
* @dev Being non transferrable, the debt token does not implement any of the
* standard ERC20 functions for transfer and allowance.
*/
function transfer(address, uint256) external virtual override returns (bool) {
revert Errors.OperationNotSupported();
}
function allowance(address, address) external view virtual override returns (uint256) {
revert Errors.OperationNotSupported();
}
function approve(address, uint256) external virtual override returns (bool) {
revert Errors.OperationNotSupported();
}
function transferFrom(address, address, uint256) external virtual override returns (bool) {
revert Errors.OperationNotSupported();
}
function increaseAllowance(address, uint256) external virtual override returns (bool) {
revert Errors.OperationNotSupported();
}
function decreaseAllowance(address, uint256) external virtual override returns (bool) {
revert Errors.OperationNotSupported();
}
/// @inheritdoc IVariableDebtToken
function UNDERLYING_ASSET_ADDRESS() external view override returns (address) {
return _underlyingAsset;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @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 `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, uint256 amount) external returns (bool);
/**
* @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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.20;
/**
* @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeCast {
/**
* @dev Value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
/**
* @dev An int value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedIntToUint(int256 value);
/**
* @dev Value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
/**
* @dev An uint value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedUintToInt(uint256 value);
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toUint248(uint256 value) internal pure returns (uint248) {
if (value > type(uint248).max) {
revert SafeCastOverflowedUintDowncast(248, value);
}
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toUint240(uint256 value) internal pure returns (uint240) {
if (value > type(uint240).max) {
revert SafeCastOverflowedUintDowncast(240, value);
}
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toUint232(uint256 value) internal pure returns (uint232) {
if (value > type(uint232).max) {
revert SafeCastOverflowedUintDowncast(232, value);
}
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
if (value > type(uint224).max) {
revert SafeCastOverflowedUintDowncast(224, value);
}
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toUint216(uint256 value) internal pure returns (uint216) {
if (value > type(uint216).max) {
revert SafeCastOverflowedUintDowncast(216, value);
}
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toUint208(uint256 value) internal pure returns (uint208) {
if (value > type(uint208).max) {
revert SafeCastOverflowedUintDowncast(208, value);
}
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toUint200(uint256 value) internal pure returns (uint200) {
if (value > type(uint200).max) {
revert SafeCastOverflowedUintDowncast(200, value);
}
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toUint192(uint256 value) internal pure returns (uint192) {
if (value > type(uint192).max) {
revert SafeCastOverflowedUintDowncast(192, value);
}
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toUint184(uint256 value) internal pure returns (uint184) {
if (value > type(uint184).max) {
revert SafeCastOverflowedUintDowncast(184, value);
}
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toUint176(uint256 value) internal pure returns (uint176) {
if (value > type(uint176).max) {
revert SafeCastOverflowedUintDowncast(176, value);
}
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toUint168(uint256 value) internal pure returns (uint168) {
if (value > type(uint168).max) {
revert SafeCastOverflowedUintDowncast(168, value);
}
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toUint160(uint256 value) internal pure returns (uint160) {
if (value > type(uint160).max) {
revert SafeCastOverflowedUintDowncast(160, value);
}
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toUint152(uint256 value) internal pure returns (uint152) {
if (value > type(uint152).max) {
revert SafeCastOverflowedUintDowncast(152, value);
}
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toUint144(uint256 value) internal pure returns (uint144) {
if (value > type(uint144).max) {
revert SafeCastOverflowedUintDowncast(144, value);
}
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toUint136(uint256 value) internal pure returns (uint136) {
if (value > type(uint136).max) {
revert SafeCastOverflowedUintDowncast(136, value);
}
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
if (value > type(uint128).max) {
revert SafeCastOverflowedUintDowncast(128, value);
}
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toUint120(uint256 value) internal pure returns (uint120) {
if (value > type(uint120).max) {
revert SafeCastOverflowedUintDowncast(120, value);
}
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toUint112(uint256 value) internal pure returns (uint112) {
if (value > type(uint112).max) {
revert SafeCastOverflowedUintDowncast(112, value);
}
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toUint104(uint256 value) internal pure returns (uint104) {
if (value > type(uint104).max) {
revert SafeCastOverflowedUintDowncast(104, value);
}
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
if (value > type(uint96).max) {
revert SafeCastOverflowedUintDowncast(96, value);
}
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toUint88(uint256 value) internal pure returns (uint88) {
if (value > type(uint88).max) {
revert SafeCastOverflowedUintDowncast(88, value);
}
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toUint80(uint256 value) internal pure returns (uint80) {
if (value > type(uint80).max) {
revert SafeCastOverflowedUintDowncast(80, value);
}
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toUint72(uint256 value) internal pure returns (uint72) {
if (value > type(uint72).max) {
revert SafeCastOverflowedUintDowncast(72, value);
}
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
if (value > type(uint64).max) {
revert SafeCastOverflowedUintDowncast(64, value);
}
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toUint56(uint256 value) internal pure returns (uint56) {
if (value > type(uint56).max) {
revert SafeCastOverflowedUintDowncast(56, value);
}
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toUint48(uint256 value) internal pure returns (uint48) {
if (value > type(uint48).max) {
revert SafeCastOverflowedUintDowncast(48, value);
}
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toUint40(uint256 value) internal pure returns (uint40) {
if (value > type(uint40).max) {
revert SafeCastOverflowedUintDowncast(40, value);
}
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
if (value > type(uint32).max) {
revert SafeCastOverflowedUintDowncast(32, value);
}
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toUint24(uint256 value) internal pure returns (uint24) {
if (value > type(uint24).max) {
revert SafeCastOverflowedUintDowncast(24, value);
}
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
if (value > type(uint16).max) {
revert SafeCastOverflowedUintDowncast(16, value);
}
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toUint8(uint256 value) internal pure returns (uint8) {
if (value > type(uint8).max) {
revert SafeCastOverflowedUintDowncast(8, value);
}
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
if (value < 0) {
revert SafeCastOverflowedIntToUint(value);
}
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(248, value);
}
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(240, value);
}
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(232, value);
}
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(224, value);
}
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(216, value);
}
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(208, value);
}
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(200, value);
}
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(192, value);
}
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(184, value);
}
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(176, value);
}
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(168, value);
}
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(160, value);
}
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(152, value);
}
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(144, value);
}
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(136, value);
}
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(128, value);
}
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(120, value);
}
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(112, value);
}
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(104, value);
}
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(96, value);
}
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(88, value);
}
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(80, value);
}
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(72, value);
}
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(64, value);
}
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(56, value);
}
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(48, value);
}
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(40, value);
}
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(32, value);
}
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(24, value);
}
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(16, value);
}
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(8, value);
}
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
if (value > uint256(type(int256).max)) {
revert SafeCastOverflowedUintToInt(value);
}
return int256(value);
}
/**
* @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
*/
function toUint(bool b) internal pure returns (uint256 u) {
assembly ("memory-safe") {
u := iszero(iszero(b))
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title Errors library
* @author Aave
* @notice Defines the error messages emitted by the different contracts of the Aave protocol
*/
library Errors {
error CallerNotPoolAdmin(); // 'The caller of the function is not a pool admin'
error CallerNotPoolOrEmergencyAdmin(); // 'The caller of the function is not a pool or emergency admin'
error CallerNotRiskOrPoolAdmin(); // 'The caller of the function is not a risk or pool admin'
error CallerNotAssetListingOrPoolAdmin(); // 'The caller of the function is not an asset listing or pool admin'
error AddressesProviderNotRegistered(); // 'Pool addresses provider is not registered'
error InvalidAddressesProviderId(); // 'Invalid id for the pool addresses provider'
error NotContract(); // 'Address is not a contract'
error CallerNotPoolConfigurator(); // 'The caller of the function is not the pool configurator'
error CallerNotAToken(); // 'The caller of the function is not an AToken'
error InvalidAddressesProvider(); // 'The address of the pool addresses provider is invalid'
error InvalidFlashloanExecutorReturn(); // 'Invalid return value of the flashloan executor function'
error ReserveAlreadyAdded(); // 'Reserve has already been added to reserve list'
error NoMoreReservesAllowed(); // 'Maximum amount of reserves in the pool reached'
error EModeCategoryReserved(); // 'Zero eMode category is reserved for volatile heterogeneous assets'
error ReserveLiquidityNotZero(); // 'The liquidity of the reserve needs to be 0'
error FlashloanPremiumInvalid(); // 'Invalid flashloan premium'
error InvalidReserveParams(); // 'Invalid risk parameters for the reserve'
error InvalidEmodeCategoryParams(); // 'Invalid risk parameters for the eMode category'
error CallerMustBePool(); // 'The caller of this function must be a pool'
error InvalidMintAmount(); // 'Invalid amount to mint'
error InvalidBurnAmount(); // 'Invalid amount to burn'
error InvalidAmount(); // 'Amount must be greater than 0'
error ReserveInactive(); // 'Action requires an active reserve'
error ReserveFrozen(); // 'Action cannot be performed because the reserve is frozen'
error ReservePaused(); // 'Action cannot be performed because the reserve is paused'
error BorrowingNotEnabled(); // 'Borrowing is not enabled'
error NotEnoughAvailableUserBalance(); // 'User cannot withdraw more than the available balance'
error InvalidInterestRateModeSelected(); // 'Invalid interest rate mode selected'
error HealthFactorLowerThanLiquidationThreshold(); // 'Health factor is below the liquidation threshold'
error CollateralCannotCoverNewBorrow(); // 'There is not enough collateral to cover a new borrow'
error NoDebtOfSelectedType(); // 'For repayment of a specific type of debt, the user needs to have debt that type'
error NoExplicitAmountToRepayOnBehalf(); // 'To repay on behalf of a user an explicit amount to repay is needed'
error UnderlyingBalanceZero(); // 'The underlying balance needs to be greater than 0'
error HealthFactorNotBelowThreshold(); // 'Health factor is not below the threshold'
error CollateralCannotBeLiquidated(); // 'The collateral chosen cannot be liquidated'
error SpecifiedCurrencyNotBorrowedByUser(); // 'User did not borrow the specified currency'
error InconsistentFlashloanParams(); // 'Inconsistent flashloan parameters'
error BorrowCapExceeded(); // 'Borrow cap is exceeded'
error SupplyCapExceeded(); // 'Supply cap is exceeded'
error DebtCeilingExceeded(); // 'Debt ceiling is exceeded'
error UnderlyingClaimableRightsNotZero(); // 'Claimable rights over underlying not zero (aToken supply or accruedToTreasury)'
error VariableDebtSupplyNotZero(); // 'Variable debt supply is not zero'
error LtvValidationFailed(); // 'Ltv validation failed'
error InconsistentEModeCategory(); // 'Inconsistent eMode category'
error PriceOracleSentinelCheckFailed(); // 'Price oracle sentinel validation failed'
error AssetNotBorrowableInIsolation(); // 'Asset is not borrowable in isolation mode'
error ReserveAlreadyInitialized(); // 'Reserve has already been initialized'
error UserInIsolationModeOrLtvZero(); // 'User is in isolation mode or ltv is zero'
error InvalidLtv(); // 'Invalid ltv parameter for the reserve'
error InvalidLiquidationThreshold(); // 'Invalid liquidity threshold parameter for the reserve'
error InvalidLiquidationBonus(); // 'Invalid liquidity bonus parameter for the reserve'
error InvalidDecimals(); // 'Invalid decimals parameter of the underlying asset of the reserve'
error InvalidReserveFactor(); // 'Invalid reserve factor parameter for the reserve'
error InvalidBorrowCap(); // 'Invalid borrow cap for the reserve'
error InvalidSupplyCap(); // 'Invalid supply cap for the reserve'
error InvalidLiquidationProtocolFee(); // 'Invalid liquidation protocol fee for the reserve'
error InvalidDebtCeiling(); // 'Invalid debt ceiling for the reserve'
error InvalidReserveIndex(); // 'Invalid reserve index'
error AclAdminCannotBeZero(); // 'ACL admin cannot be set to the zero address'
error InconsistentParamsLength(); // 'Array parameters that should be equal length are not'
error ZeroAddressNotValid(); // 'Zero address not valid'
error InvalidExpiration(); // 'Invalid expiration'
error InvalidSignature(); // 'Invalid signature'
error OperationNotSupported(); // 'Operation not supported'
error DebtCeilingNotZero(); // 'Debt ceiling is not zero'
error AssetNotListed(); // 'Asset is not listed'
error InvalidOptimalUsageRatio(); // 'Invalid optimal usage ratio'
error UnderlyingCannotBeRescued(); // 'The underlying asset cannot be rescued'
error AddressesProviderAlreadyAdded(); // 'Reserve has already been added to reserve list'
error PoolAddressesDoNotMatch(); // 'The token implementation pool address and the pool address provided by the initializing pool do not match'
error SiloedBorrowingViolation(); // 'User is trying to borrow multiple assets including a siloed one'
error ReserveDebtNotZero(); // the total debt of the reserve needs to be 0
error FlashloanDisabled(); // FlashLoaning for this asset is disabled
error InvalidMaxRate(); // The expect maximum borrow rate is invalid
error WithdrawToAToken(); // Withdrawing to the aToken is not allowed
error SupplyToAToken(); // Supplying to the aToken is not allowed
error Slope2MustBeGteSlope1(); // Variable interest rate slope 2 can not be lower than slope 1
error CallerNotRiskOrPoolOrEmergencyAdmin(); // 'The caller of the function is not a risk, pool or emergency admin'
error LiquidationGraceSentinelCheckFailed(); // 'Liquidation grace sentinel validation failed'
error InvalidGracePeriod(); // Grace period above a valid range
error InvalidFreezeState(); // Reserve is already in the passed freeze state
error NotBorrowableInEMode(); // Asset not borrowable in eMode
error CallerNotUmbrella(); // The caller of the function is not the umbrella contract
error ReserveNotInDeficit(); // The reserve is not in deficit
error MustNotLeaveDust(); // Below a certain threshold liquidators need to take the full position
error UserCannotHaveDebt(); // Thrown when a user tries to interact with a method that requires a position without debt
error SelfLiquidation(); // Thrown when a user tries to liquidate themselves
error CallerNotPositionManager(); // Thrown when the caller has not been enabled as a position manager of the on-behalf-of user
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IPoolAddressesProvider} from './IPoolAddressesProvider.sol';
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
/**
* @title IPool
* @author Aave
* @notice Defines the basic interface for an Aave Pool.
*/
interface IPool {
/**
* @dev Emitted on supply()
* @param reserve The address of the underlying asset of the reserve
* @param user The address initiating the supply
* @param onBehalfOf The beneficiary of the supply, receiving the aTokens
* @param amount The amount supplied
* @param referralCode The referral code used
*/
event Supply(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint16 indexed referralCode
);
/**
* @dev Emitted on withdraw()
* @param reserve The address of the underlying asset being withdrawn
* @param user The address initiating the withdrawal, owner of aTokens
* @param to The address that will receive the underlying
* @param amount The amount to be withdrawn
*/
event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);
/**
* @dev Emitted on borrow() and flashLoan() when debt needs to be opened
* @param reserve The address of the underlying asset being borrowed
* @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just
* initiator of the transaction on flashLoan()
* @param onBehalfOf The address that will be getting the debt
* @param amount The amount borrowed out
* @param interestRateMode The rate mode: 2 for Variable, 1 is deprecated (changed on v3.2.0)
* @param borrowRate The numeric rate at which the user has borrowed, expressed in ray
* @param referralCode The referral code used
*/
event Borrow(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
DataTypes.InterestRateMode interestRateMode,
uint256 borrowRate,
uint16 indexed referralCode
);
/**
* @dev Emitted on repay()
* @param reserve The address of the underlying asset of the reserve
* @param user The beneficiary of the repayment, getting his debt reduced
* @param repayer The address of the user initiating the repay(), providing the funds
* @param amount The amount repaid
* @param useATokens True if the repayment is done using aTokens, `false` if done with underlying asset directly
*/
event Repay(
address indexed reserve,
address indexed user,
address indexed repayer,
uint256 amount,
bool useATokens
);
/**
* @dev Emitted on borrow(), repay() and liquidationCall() when using isolated assets
* @param asset The address of the underlying asset of the reserve
* @param totalDebt The total isolation mode debt for the reserve
*/
event IsolationModeTotalDebtUpdated(address indexed asset, uint256 totalDebt);
/**
* @dev Emitted when the user selects a certain asset category for eMode
* @param user The address of the user
* @param categoryId The category id
*/
event UserEModeSet(address indexed user, uint8 categoryId);
/**
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
*/
event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);
/**
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
*/
event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);
/**
* @dev Emitted on flashLoan()
* @param target The address of the flash loan receiver contract
* @param initiator The address initiating the flash loan
* @param asset The address of the asset being flash borrowed
* @param amount The amount flash borrowed
* @param interestRateMode The flashloan mode: 0 for regular flashloan,
* 1 for Stable (Deprecated on v3.2.0), 2 for Variable
* @param premium The fee flash borrowed
* @param referralCode The referral code used
*/
event FlashLoan(
address indexed target,
address initiator,
address indexed asset,
uint256 amount,
DataTypes.InterestRateMode interestRateMode,
uint256 premium,
uint16 indexed referralCode
);
/**
* @dev Emitted when a borrower is liquidated.
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param user The address of the borrower getting liquidated
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param liquidatedCollateralAmount The amount of collateral received by the liquidator
* @param liquidator The address of the liquidator
* @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants
* to receive the underlying collateral asset directly
*/
event LiquidationCall(
address indexed collateralAsset,
address indexed debtAsset,
address indexed user,
uint256 debtToCover,
uint256 liquidatedCollateralAmount,
address liquidator,
bool receiveAToken
);
/**
* @dev Emitted when the state of a reserve is updated.
* @param reserve The address of the underlying asset of the reserve
* @param liquidityRate The next liquidity rate
* @param stableBorrowRate The next stable borrow rate @note deprecated on v3.2.0
* @param variableBorrowRate The next variable borrow rate
* @param liquidityIndex The next liquidity index
* @param variableBorrowIndex The next variable borrow index
*/
event ReserveDataUpdated(
address indexed reserve,
uint256 liquidityRate,
uint256 stableBorrowRate,
uint256 variableBorrowRate,
uint256 liquidityIndex,
uint256 variableBorrowIndex
);
/**
* @dev Emitted when the deficit of a reserve is covered.
* @param reserve The address of the underlying asset of the reserve
* @param caller The caller that triggered the DeficitCovered event
* @param amountCovered The amount of deficit covered
*/
event DeficitCovered(address indexed reserve, address caller, uint256 amountCovered);
/**
* @dev Emitted when the protocol treasury receives minted aTokens from the accrued interest.
* @param reserve The address of the reserve
* @param amountMinted The amount minted to the treasury
*/
event MintedToTreasury(address indexed reserve, uint256 amountMinted);
/**
* @dev Emitted when deficit is realized on a liquidation.
* @param user The user address where the bad debt will be burned
* @param debtAsset The address of the underlying borrowed asset to be burned
* @param amountCreated The amount of deficit created
*/
event DeficitCreated(address indexed user, address indexed debtAsset, uint256 amountCreated);
/**
* @dev Emitted when a position manager is approved by the user.
* @param user The user address
* @param positionManager The address of the position manager
*/
event PositionManagerApproved(address indexed user, address indexed positionManager);
/**
* @dev Emitted when a position manager is revoked by the user.
* @param user The user address
* @param positionManager The address of the position manager
*/
event PositionManagerRevoked(address indexed user, address indexed positionManager);
/**
* @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
* - E.g. User supplies 100 USDC and gets in return 100 aUSDC
* @param asset The address of the underlying asset to supply
* @param amount The amount to be supplied
* @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
* wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
* is a different wallet
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
*/
function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external;
/**
* @notice Supply with transfer approval of asset to be supplied done via permit function
* see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713
* @param asset The address of the underlying asset to supply
* @param amount The amount to be supplied
* @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
* wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
* is a different wallet
* @param deadline The deadline timestamp that the permit is valid
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
* @param permitV The V parameter of ERC712 permit sig
* @param permitR The R parameter of ERC712 permit sig
* @param permitS The S parameter of ERC712 permit sig
*/
function supplyWithPermit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode,
uint256 deadline,
uint8 permitV,
bytes32 permitR,
bytes32 permitS
) external;
/**
* @notice Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned
* E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC
* @param asset The address of the underlying asset to withdraw
* @param amount The underlying amount to be withdrawn
* - Send the value type(uint256).max in order to withdraw the whole aToken balance
* @param to The address that will receive the underlying, same as msg.sender if the user
* wants to receive it on his own wallet, or a different address if the beneficiary is a
* different wallet
* @return The final amount withdrawn
*/
function withdraw(address asset, uint256 amount, address to) external returns (uint256);
/**
* @notice Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower
* already supplied enough collateral, or he was given enough allowance by a credit delegator on the VariableDebtToken
* - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet
* and 100 variable debt tokens
* @param asset The address of the underlying asset to borrow
* @param amount The amount to be borrowed
* @param interestRateMode 2 for Variable, 1 is deprecated on v3.2.0
* @param referralCode The code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
* @param onBehalfOf The address of the user who will receive the debt. Should be the address of the borrower itself
* calling the function if he wants to borrow against his own collateral, or the address of the credit delegator
* if he has been given credit delegation allowance
*/
function borrow(
address asset,
uint256 amount,
uint256 interestRateMode,
uint16 referralCode,
address onBehalfOf
) external;
/**
* @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned
* - E.g. User repays 100 USDC, burning 100 variable debt tokens of the `onBehalfOf` address
* @param asset The address of the borrowed underlying asset previously borrowed
* @param amount The amount to repay
* - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
* @param interestRateMode 2 for Variable, 1 is deprecated on v3.2.0
* @param onBehalfOf The address of the user who will get his debt reduced/removed. Should be the address of the
* user calling the function if he wants to reduce/remove his own debt, or the address of any other
* other borrower whose debt should be removed
* @return The final amount repaid
*/
function repay(
address asset,
uint256 amount,
uint256 interestRateMode,
address onBehalfOf
) external returns (uint256);
/**
* @notice Repay with transfer approval of asset to be repaid done via permit function
* see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713
* @param asset The address of the borrowed underlying asset previously borrowed
* @param amount The amount to repay
* - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
* @param interestRateMode 2 for Variable, 1 is deprecated on v3.2.0
* @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the
* user calling the function if he wants to reduce/remove his own debt, or the address of any other
* other borrower whose debt should be removed
* @param deadline The deadline timestamp that the permit is valid
* @param permitV The V parameter of ERC712 permit sig
* @param permitR The R parameter of ERC712 permit sig
* @param permitS The S parameter of ERC712 permit sig
* @return The final amount repaid
*/
function repayWithPermit(
address asset,
uint256 amount,
uint256 interestRateMode,
address onBehalfOf,
uint256 deadline,
uint8 permitV,
bytes32 permitR,
bytes32 permitS
) external returns (uint256);
/**
* @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the
* equivalent debt tokens
* - E.g. User repays 100 USDC using 100 aUSDC, burning 100 variable debt tokens
* @dev Passing uint256.max as amount will clean up any residual aToken dust balance, if the user aToken
* balance is not enough to cover the whole debt
* @param asset The address of the borrowed underlying asset previously borrowed
* @param amount The amount to repay
* - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
* @param interestRateMode DEPRECATED in v3.2.0
* @return The final amount repaid
*/
function repayWithATokens(
address asset,
uint256 amount,
uint256 interestRateMode
) external returns (uint256);
/**
* @notice Allows suppliers to enable/disable a specific supplied asset as collateral
* @param asset The address of the underlying asset supplied
* @param useAsCollateral True if the user wants to use the supply as collateral, false otherwise
*/
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;
/**
* @notice Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1
* - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives
* a proportionally amount of the `collateralAsset` plus a bonus to cover market risk
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param borrower The address of the borrower getting liquidated
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants
* to receive the underlying collateral asset directly
*/
function liquidationCall(
address collateralAsset,
address debtAsset,
address borrower,
uint256 debtToCover,
bool receiveAToken
) external;
/**
* @notice Allows smartcontracts to access the liquidity of the pool within one transaction,
* as long as the amount taken plus a fee is returned.
* @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept
* into consideration. For further details please visit https://docs.aave.com/developers/
* @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanReceiver interface
* @param assets The addresses of the assets being flash-borrowed
* @param amounts The amounts of the assets being flash-borrowed
* @param interestRateModes Types of the debt to open if the flash loan is not returned:
* 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver
* 1 -> Deprecated on v3.2.0
* 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
* @param onBehalfOf The address that will receive the debt in the case of using 2 on `modes`
* @param params Variadic packed params to pass to the receiver as extra information
* @param referralCode The code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
*/
function flashLoan(
address receiverAddress,
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata interestRateModes,
address onBehalfOf,
bytes calldata params,
uint16 referralCode
) external;
/**
* @notice Allows smartcontracts to access the liquidity of the pool within one transaction,
* as long as the amount taken plus a fee is returned.
* @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept
* into consideration. For further details please visit https://docs.aave.com/developers/
* @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanSimpleReceiver interface
* @param asset The address of the asset being flash-borrowed
* @param amount The amount of the asset being flash-borrowed
* @param params Variadic packed params to pass to the receiver as extra information
* @param referralCode The code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
*/
function flashLoanSimple(
address receiverAddress,
address asset,
uint256 amount,
bytes calldata params,
uint16 referralCode
) external;
/**
* @notice Returns the user account data across all the reserves
* @param user The address of the user
* @return totalCollateralBase The total collateral of the user in the base currency used by the price feed
* @return totalDebtBase The total debt of the user in the base currency used by the price feed
* @return availableBorrowsBase The borrowing power left of the user in the base currency used by the price feed
* @return currentLiquidationThreshold The liquidation threshold of the user
* @return ltv The loan to value of The user
* @return healthFactor The current health factor of the user
*/
function getUserAccountData(
address user
)
external
view
returns (
uint256 totalCollateralBase,
uint256 totalDebtBase,
uint256 availableBorrowsBase,
uint256 currentLiquidationThreshold,
uint256 ltv,
uint256 healthFactor
);
/**
* @notice Initializes a reserve, activating it, assigning an aToken and debt tokens
* @dev Only callable by the PoolConfigurator contract
* @param asset The address of the underlying asset of the reserve
* @param aTokenAddress The address of the aToken that will be assigned to the reserve
* @param variableDebtAddress The address of the VariableDebtToken that will be assigned to the reserve
*/
function initReserve(address asset, address aTokenAddress, address variableDebtAddress) external;
/**
* @notice Drop a reserve
* @dev Only callable by the PoolConfigurator contract
* @dev Does not reset eMode flags, which must be considered when reusing the same reserve id for a different reserve.
* @param asset The address of the underlying asset of the reserve
*/
function dropReserve(address asset) external;
/**
* @notice Accumulates interest to all indexes of the reserve
* @dev Only callable by the PoolConfigurator contract
* @dev To be used when required by the configurator, for example when updating interest rates strategy data
* @param asset The address of the underlying asset of the reserve
*/
function syncIndexesState(address asset) external;
/**
* @notice Updates interest rates on the reserve data
* @dev Only callable by the PoolConfigurator contract
* @dev To be used when required by the configurator, for example when updating interest rates strategy data
* @param asset The address of the underlying asset of the reserve
*/
function syncRatesState(address asset) external;
/**
* @notice Sets the configuration bitmap of the reserve as a whole
* @dev Only callable by the PoolConfigurator contract
* @param asset The address of the underlying asset of the reserve
* @param configuration The new configuration bitmap
*/
function setConfiguration(
address asset,
DataTypes.ReserveConfigurationMap calldata configuration
) external;
/**
* @notice Returns the configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The configuration of the reserve
*/
function getConfiguration(
address asset
) external view returns (DataTypes.ReserveConfigurationMap memory);
/**
* @notice Returns the configuration of the user across all the reserves
* @param user The user address
* @return The configuration of the user
*/
function getUserConfiguration(
address user
) external view returns (DataTypes.UserConfigurationMap memory);
/**
* @notice Returns the normalized income of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The reserve's normalized income
*/
function getReserveNormalizedIncome(address asset) external view returns (uint256);
/**
* @notice Returns the normalized variable debt per unit of asset
* @dev WARNING: This function is intended to be used primarily by the protocol itself to get a
* "dynamic" variable index based on time, current stored index and virtual rate at the current
* moment (approx. a borrower would get if opening a position). This means that is always used in
* combination with variable debt supply/balances.
* If using this function externally, consider that is possible to have an increasing normalized
* variable debt that is not equivalent to how the variable debt index would be updated in storage
* (e.g. only updates with non-zero variable debt supply)
* @param asset The address of the underlying asset of the reserve
* @return The reserve normalized variable debt
*/
function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);
/**
* @notice Returns the state and configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The state and configuration data of the reserve
*/
function getReserveData(address asset) external view returns (DataTypes.ReserveDataLegacy memory);
/**
* @notice Returns the virtual underlying balance of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The reserve virtual underlying balance
*/
function getVirtualUnderlyingBalance(address asset) external view returns (uint128);
/**
* @notice Validates and finalizes an aToken transfer
* @dev Only callable by the overlying aToken of the `asset`
* @param asset The address of the underlying asset of the aToken
* @param from The user from which the aTokens are transferred
* @param to The user receiving the aTokens
* @param scaledAmount The scaled amount being transferred/withdrawn
* @param scaledBalanceFromBefore The aToken scaled balance of the `from` user before the transfer
* @param scaledBalanceToBefore The aToken scaled balance of the `to` user before the transfer
*/
function finalizeTransfer(
address asset,
address from,
address to,
uint256 scaledAmount,
uint256 scaledBalanceFromBefore,
uint256 scaledBalanceToBefore
) external;
/**
* @notice Returns the list of the underlying assets of all the initialized reserves
* @dev It does not include dropped reserves
* @return The addresses of the underlying assets of the initialized reserves
*/
function getReservesList() external view returns (address[] memory);
/**
* @notice Returns the number of initialized reserves
* @dev It includes dropped reserves
* @return The count
*/
function getReservesCount() external view returns (uint256);
/**
* @notice Returns the address of the underlying asset of a reserve by the reserve id as stored in the DataTypes.ReserveData struct
* @param id The id of the reserve as stored in the DataTypes.ReserveData struct
* @return The address of the reserve associated with id
*/
function getReserveAddressById(uint16 id) external view returns (address);
/**
* @notice Returns the PoolAddressesProvider connected to this contract
* @return The address of the PoolAddressesProvider
*/
function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider);
/**
* @notice Returns the ReserveInterestRateStrategy connected to all the reserves
* @return The address of the ReserveInterestRateStrategy contract
*/
function RESERVE_INTEREST_RATE_STRATEGY() external view returns (address);
/**
* @notice Updates flash loan premium. All this premium is collected by the protocol treasury.
* @dev The premium is calculated on the total borrowed amount
* @dev Only callable by the PoolConfigurator contract
* @param flashLoanPremium The flash loan premium, expressed in bps
*/
function updateFlashloanPremium(uint128 flashLoanPremium) external;
/**
* @notice Configures a new or alters an existing collateral configuration of an eMode.
* @dev In eMode, the protocol allows very high borrowing power to borrow assets of the same category.
* The category 0 is reserved as it's the default for volatile assets
* @param id The id of the category
* @param config The configuration of the category
*/
function configureEModeCategory(
uint8 id,
DataTypes.EModeCategoryBaseConfiguration memory config
) external;
/**
* @notice Replaces the current eMode collateralBitmap.
* @param id The id of the category
* @param collateralBitmap The collateralBitmap of the category
*/
function configureEModeCategoryCollateralBitmap(uint8 id, uint128 collateralBitmap) external;
/**
* @notice Replaces the current eMode borrowableBitmap.
* @param id The id of the category
* @param borrowableBitmap The borrowableBitmap of the category
*/
function configureEModeCategoryBorrowableBitmap(uint8 id, uint128 borrowableBitmap) external;
/**
* @notice Returns the data of an eMode category
* @dev DEPRECATED use independent getters instead
* @param id The id of the category
* @return The configuration data of the category
*/
function getEModeCategoryData(
uint8 id
) external view returns (DataTypes.EModeCategoryLegacy memory);
/**
* @notice Returns the label of an eMode category
* @param id The id of the category
* @return The label of the category
*/
function getEModeCategoryLabel(uint8 id) external view returns (string memory);
/**
* @notice Returns the collateral config of an eMode category
* @param id The id of the category
* @return The ltv,lt,lb of the category
*/
function getEModeCategoryCollateralConfig(
uint8 id
) external view returns (DataTypes.CollateralConfig memory);
/**
* @notice Returns the collateralBitmap of an eMode category
* @param id The id of the category
* @return The collateralBitmap of the category
*/
function getEModeCategoryCollateralBitmap(uint8 id) external view returns (uint128);
/**
* @notice Returns the borrowableBitmap of an eMode category
* @param id The id of the category
* @return The borrowableBitmap of the category
*/
function getEModeCategoryBorrowableBitmap(uint8 id) external view returns (uint128);
/**
* @notice Allows a user to use the protocol in eMode
* @param categoryId The id of the category
*/
function setUserEMode(uint8 categoryId) external;
/**
* @notice Returns the eMode the user is using
* @param user The address of the user
* @return The eMode id
*/
function getUserEMode(address user) external view returns (uint256);
/**
* @notice Resets the isolation mode total debt of the given asset to zero
* @dev It requires the given asset has zero debt ceiling
* @param asset The address of the underlying asset to reset the isolationModeTotalDebt
*/
function resetIsolationModeTotalDebt(address asset) external;
/**
* @notice Sets the liquidation grace period of the given asset
* @dev To enable a liquidation grace period, a timestamp in the future should be set,
* To disable a liquidation grace period, any timestamp in the past works, like 0
* @param asset The address of the underlying asset to set the liquidationGracePeriod
* @param until Timestamp when the liquidation grace period will end
**/
function setLiquidationGracePeriod(address asset, uint40 until) external;
/**
* @notice Returns the liquidation grace period of the given asset
* @param asset The address of the underlying asset
* @return Timestamp when the liquidation grace period will end
**/
function getLiquidationGracePeriod(address asset) external view returns (uint40);
/**
* @notice Returns the total fee on flash loans.
* @dev From v3.4 all flashloan fees will be send to the treasury.
* @return The total fee on flashloans
*/
function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128);
/**
* @notice Returns the part of the flashloan fees sent to protocol
* @dev From v3.4 all flashloan fees will be send to the treasury and this value
* is always 100_00.
* @return The flashloan fee sent to the protocol treasury
*/
function FLASHLOAN_PREMIUM_TO_PROTOCOL() external view returns (uint128);
/**
* @notice Returns the maximum number of reserves supported to be listed in this Pool
* @return The maximum number of reserves supported
*/
function MAX_NUMBER_RESERVES() external view returns (uint16);
/**
* @notice Mints the assets accrued through the reserve factor to the treasury in the form of aTokens
* @param assets The list of reserves for which the minting needs to be executed
*/
function mintToTreasury(address[] calldata assets) external;
/**
* @notice Rescue and transfer tokens locked in this contract
* @param token The address of the token
* @param to The address of the recipient
* @param amount The amount of token to transfer
*/
function rescueTokens(address token, address to, uint256 amount) external;
/**
* @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
* - E.g. User supplies 100 USDC and gets in return 100 aUSDC
* @dev Deprecated: Use the `supply` function instead
* @param asset The address of the underlying asset to supply
* @param amount The amount to be supplied
* @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
* wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
* is a different wallet
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
*/
function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external;
/**
* @notice It covers the deficit of a specified reserve by burning the equivalent aToken `amount` for assets
* @dev The deficit of a reserve can occur due to situations where borrowed assets are not repaid, leading to bad debt.
* @param asset The address of the underlying asset to cover the deficit.
* @param amount The amount to be covered, in aToken
* @return The amount of tokens burned
*/
function eliminateReserveDeficit(address asset, uint256 amount) external returns (uint256);
/**
* @notice Approves or disapproves a position manager. This position manager will be able
* to call the `setUserUseReserveAsCollateralOnBehalfOf` and the
* `setUserEModeOnBehalfOf` function on behalf of the user.
* @param positionManager The address of the position manager
* @param approve True if the position manager should be approved, false otherwise
*/
function approvePositionManager(address positionManager, bool approve) external;
/**
* @notice Renounces a position manager role for a given user.
* @param user The address of the user
*/
function renouncePositionManagerRole(address user) external;
/**
* @notice Sets the use as collateral flag for the user on the specific reserve on behalf of the user.
* @param asset The address of the underlying asset of the reserve
* @param useAsCollateral True if the user wants to use the reserve as collateral, false otherwise
* @param onBehalfOf The address of the user
*/
function setUserUseReserveAsCollateralOnBehalfOf(
address asset,
bool useAsCollateral,
address onBehalfOf
) external;
/**
* @notice Sets the eMode category for the user on the specific reserve on behalf of the user.
* @param categoryId The id of the category
* @param onBehalfOf The address of the user
*/
function setUserEModeOnBehalfOf(uint8 categoryId, address onBehalfOf) external;
/*
* @notice Returns true if the `positionManager` address is approved to use the position manager role on behalf of the user.
* @param user The address of the user
* @param positionManager The address of the position manager
* @return True if the user is approved to use the position manager, false otherwise
*/
function isApprovedPositionManager(
address user,
address positionManager
) external view returns (bool);
/**
* @notice Returns the current deficit of a reserve.
* @param asset The address of the underlying asset of the reserve
* @return The current deficit of the reserve
*/
function getReserveDeficit(address asset) external view returns (uint256);
/**
* @notice Returns the aToken address of a reserve.
* @param asset The address of the underlying asset of the reserve
* @return The address of the aToken
*/
function getReserveAToken(address asset) external view returns (address);
/**
* @notice Returns the variableDebtToken address of a reserve.
* @param asset The address of the underlying asset of the reserve
* @return The address of the variableDebtToken
*/
function getReserveVariableDebtToken(address asset) external view returns (address);
/**
* @notice Gets the address of the external FlashLoanLogic
*/
function getFlashLoanLogic() external view returns (address);
/**
* @notice Gets the address of the external BorrowLogic
*/
function getBorrowLogic() external view returns (address);
/**
* @notice Gets the address of the external EModeLogic
*/
function getEModeLogic() external view returns (address);
/**
* @notice Gets the address of the external LiquidationLogic
*/
function getLiquidationLogic() external view returns (address);
/**
* @notice Gets the address of the external PoolLogic
*/
function getPoolLogic() external view returns (address);
/**
* @notice Gets the address of the external SupplyLogic
*/
function getSupplyLogic() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IAaveIncentivesController} from './IAaveIncentivesController.sol';
import {IPool} from './IPool.sol';
/**
* @title IInitializableDebtToken
* @author Aave
* @notice Interface for the initialize function common between debt tokens
*/
interface IInitializableDebtToken {
/**
* @dev Emitted when a debt token is initialized
* @param underlyingAsset The address of the underlying asset
* @param pool The address of the associated pool
* @param incentivesController The address of the incentives controller for this aToken
* @param debtTokenDecimals The decimals of the debt token
* @param debtTokenName The name of the debt token
* @param debtTokenSymbol The symbol of the debt token
* @param params A set of encoded parameters for additional initialization
*/
event Initialized(
address indexed underlyingAsset,
address indexed pool,
address incentivesController,
uint8 debtTokenDecimals,
string debtTokenName,
string debtTokenSymbol,
bytes params
);
/**
* @notice Initializes the debt token.
* @param pool The pool contract that is initializing this contract
* @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH)
* @param debtTokenDecimals The decimals of the debtToken, same as the underlying asset's
* @param debtTokenName The name of the token
* @param debtTokenSymbol The symbol of the token
* @param params A set of encoded parameters for additional initialization
*/
function initialize(
IPool pool,
address underlyingAsset,
uint8 debtTokenDecimals,
string memory debtTokenName,
string memory debtTokenSymbol,
bytes calldata params
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IScaledBalanceToken} from './IScaledBalanceToken.sol';
import {IInitializableDebtToken} from './IInitializableDebtToken.sol';
/**
* @title IVariableDebtToken
* @author Aave
* @notice Defines the basic interface for a variable debt token.
*/
interface IVariableDebtToken is IScaledBalanceToken, IInitializableDebtToken {
/**
* @notice Mints debt token to the `onBehalfOf` address.
* @dev Passing both the unscaled and scaled amounts enhances precision. The `scaledAmount` is used for precise balance updates,
* while the `amount` is used for allowance checks, preventing cumulative rounding errors.
* @param user The address receiving the borrowed underlying, being the delegatee in case
* of credit delegate, or same as `onBehalfOf` otherwise
* @param onBehalfOf The address receiving the debt tokens
* @param amount The unscaled amount of debt to be accounted for allowance
* @param scaledAmount The scaled amount of debt tokens to mint
* @param index The variable debt index of the reserve
* @return The scaled total debt of the reserve
*/
function mint(
address user,
address onBehalfOf,
uint256 amount,
uint256 scaledAmount,
uint256 index
) external returns (uint256);
/**
* @notice Burns user variable debt.
* @dev Passing the scaled amount allows for more precise calculations and avoids cumulative errors from repeated conversions.
* @dev In some instances, a burn transaction will emit a mint event if the amount to burn is less than the interest that the user accrued.
* @param from The address from which the debt will be burned
* @param scaledAmount The scaled amount of debt getting burned
* @param index The variable debt index of the reserve
* @return True if the new balance is zero
* @return The scaled total debt of the reserve
*/
function burn(address from, uint256 scaledAmount, uint256 index) external returns (bool, uint256);
/**
* @notice Returns the address of the underlying asset of this debtToken (E.g. WETH for variableDebtWETH)
* @return The address of the underlying asset
*/
function UNDERLYING_ASSET_ADDRESS() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
/**
* @title EIP712Base
* @author Aave
* @notice Base contract implementation of EIP712.
*/
abstract contract EIP712Base {
bytes public constant EIP712_REVISION = bytes('1');
bytes32 internal constant EIP712_DOMAIN =
keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)');
// Map of address nonces (address => nonce)
mapping(address => uint256) internal _nonces;
bytes32 internal _domainSeparator;
uint256 internal immutable _chainId;
/**
* @dev Constructor.
*/
constructor() {
_chainId = block.chainid;
}
/**
* @notice Get the domain separator for the token
* @dev Return cached value if chainId matches cache, otherwise recomputes separator
* @return The domain separator of the token at current chain
*/
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
if (block.chainid == _chainId) {
return _domainSeparator;
}
return _calculateDomainSeparator();
}
/**
* @notice Returns the nonce value for address specified as parameter
* @param owner The address for which the nonce is being returned
* @return The nonce value for the input address`
*/
function nonces(address owner) public view virtual returns (uint256) {
return _nonces[owner];
}
/**
* @notice Compute the current domain separator
* @return The domain separator for the token
*/
function _calculateDomainSeparator() internal view returns (bytes32) {
return
keccak256(
abi.encode(
EIP712_DOMAIN,
keccak256(bytes(_EIP712BaseId())),
keccak256(EIP712_REVISION),
block.chainid,
address(this)
)
);
}
/**
* @notice Returns the user readable name of signing domain (e.g. token name)
* @return The name of the signing domain
*/
function _EIP712BaseId() internal view virtual returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import {ECDSA} from 'openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol';
import {Context} from '../../../dependencies/openzeppelin/contracts/Context.sol';
import {Errors} from '../../libraries/helpers/Errors.sol';
import {VersionedInitializable} from '../../../misc/aave-upgradeability/VersionedInitializable.sol';
import {ICreditDelegationToken} from '../../../interfaces/ICreditDelegationToken.sol';
import {EIP712Base} from './EIP712Base.sol';
/**
* @title DebtTokenBase
* @author Aave
* @notice Base contract for different types of debt tokens, like VariableDebtToken
*/
abstract contract DebtTokenBase is
VersionedInitializable,
EIP712Base,
Context,
ICreditDelegationToken
{
// Map of borrow allowances (delegator => delegatee => borrowAllowanceAmount)
mapping(address => mapping(address => uint256)) internal _borrowAllowances;
// Credit Delegation Typehash
bytes32 public constant DELEGATION_WITH_SIG_TYPEHASH =
keccak256('DelegationWithSig(address delegatee,uint256 value,uint256 nonce,uint256 deadline)');
address internal _underlyingAsset;
/**
* @dev Constructor.
*/
constructor() EIP712Base() {
// Intentionally left blank
}
/// @inheritdoc ICreditDelegationToken
function approveDelegation(address delegatee, uint256 amount) external override {
_approveDelegation(_msgSender(), delegatee, amount);
}
/// @inheritdoc ICreditDelegationToken
function delegationWithSig(
address delegator,
address delegatee,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external {
require(delegator != address(0), Errors.ZeroAddressNotValid());
//solium-disable-next-line
require(block.timestamp <= deadline, Errors.InvalidExpiration());
uint256 currentValidNonce = _nonces[delegator];
bytes32 digest = keccak256(
abi.encodePacked(
'\x19\x01',
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(DELEGATION_WITH_SIG_TYPEHASH, delegatee, value, currentValidNonce, deadline)
)
)
);
require(delegator == ECDSA.recover(digest, v, r, s), Errors.InvalidSignature());
_nonces[delegator] = currentValidNonce + 1;
_approveDelegation(delegator, delegatee, value);
}
/// @inheritdoc ICreditDelegationToken
function borrowAllowance(
address fromUser,
address toUser
) external view override returns (uint256) {
return _borrowAllowances[fromUser][toUser];
}
/**
* @notice Updates the borrow allowance of a user on the specific debt token.
* @param delegator The address delegating the borrowing power
* @param delegatee The address receiving the delegated borrowing power
* @param amount The allowance amount being delegated.
*/
function _approveDelegation(address delegator, address delegatee, uint256 amount) internal {
_borrowAllowances[delegator][delegatee] = amount;
emit BorrowAllowanceDelegated(delegator, delegatee, _underlyingAsset, amount);
}
/**
* @notice Decreases the borrow allowance of a user on the specific debt token.
* @param delegator The address delegating the borrowing power
* @param delegatee The address receiving the delegated borrowing power
* @param amount The minimum amount to subtract from the current allowance
* @param correctedAmount The maximum amount to subtract from the current allowance
*/
function _decreaseBorrowAllowance(
address delegator,
address delegatee,
uint256 amount,
uint256 correctedAmount
) internal {
uint256 oldBorrowAllowance = _borrowAllowances[delegator][delegatee];
if (oldBorrowAllowance < amount) {
revert InsufficientBorrowAllowance(delegatee, oldBorrowAllowance, amount);
}
uint256 consumption = oldBorrowAllowance >= correctedAmount
? correctedAmount
: oldBorrowAllowance;
uint256 newAllowance = oldBorrowAllowance - consumption;
_borrowAllowances[delegator][delegatee] = newAllowance;
emit BorrowAllowanceDelegated(delegator, delegatee, _underlyingAsset, newAllowance);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import {SafeCast} from 'openzeppelin-contracts/contracts/utils/math/SafeCast.sol';
import {Errors} from '../../libraries/helpers/Errors.sol';
import {WadRayMath} from '../../libraries/math/WadRayMath.sol';
import {IPool} from '../../../interfaces/IPool.sol';
import {IScaledBalanceToken} from '../../../interfaces/IScaledBalanceToken.sol';
import {MintableIncentivizedERC20} from './MintableIncentivizedERC20.sol';
/**
* @title ScaledBalanceTokenBase
* @author Aave
* @notice Basic ERC20 implementation of scaled balance token
*/
abstract contract ScaledBalanceTokenBase is MintableIncentivizedERC20, IScaledBalanceToken {
using WadRayMath for uint256;
using SafeCast for uint256;
/**
* @dev Constructor.
* @param pool The reference to the main Pool contract
* @param name The name of the token
* @param symbol The symbol of the token
* @param decimals The number of decimals of the token
* @param rewardsController The address of the rewards controller contract
*/
constructor(
IPool pool,
string memory name,
string memory symbol,
uint8 decimals,
address rewardsController
) MintableIncentivizedERC20(pool, name, symbol, decimals, rewardsController) {
// Intentionally left blank
}
/// @inheritdoc IScaledBalanceToken
function scaledBalanceOf(address user) external view override returns (uint256) {
return super.balanceOf(user);
}
/// @inheritdoc IScaledBalanceToken
function getScaledUserBalanceAndSupply(
address user
) external view override returns (uint256, uint256) {
return (super.balanceOf(user), super.totalSupply());
}
/// @inheritdoc IScaledBalanceToken
function scaledTotalSupply() public view virtual override returns (uint256) {
return super.totalSupply();
}
/// @inheritdoc IScaledBalanceToken
function getPreviousIndex(address user) external view virtual override returns (uint256) {
return _userState[user].additionalData;
}
/**
* @notice Implements the basic logic to mint a scaled balance token.
* @param caller The address performing the mint
* @param onBehalfOf The address of the user that will receive the scaled tokens
* @param amountScaled The amountScaled of tokens getting minted
* @param index The next liquidity index of the reserve
* @param getTokenBalance The function to get the balance of the token
* @return `true` if the the previous balance of the user was 0
*/
function _mintScaled(
address caller,
address onBehalfOf,
uint256 amountScaled,
uint256 index,
function(uint256, uint256) internal pure returns (uint256) getTokenBalance
) internal returns (bool) {
require(amountScaled != 0, Errors.InvalidMintAmount());
uint256 scaledBalance = super.balanceOf(onBehalfOf);
uint256 nextBalance = getTokenBalance(amountScaled + scaledBalance, index);
uint256 previousBalance = getTokenBalance(scaledBalance, _userState[onBehalfOf].additionalData);
uint256 balanceIncrease = getTokenBalance(scaledBalance, index) - previousBalance;
_userState[onBehalfOf].additionalData = index.toUint128();
_mint(onBehalfOf, amountScaled.toUint120());
uint256 amountToMint = nextBalance - previousBalance;
emit Transfer(address(0), onBehalfOf, amountToMint);
emit Mint(caller, onBehalfOf, amountToMint, balanceIncrease, index);
return (scaledBalance == 0);
}
/**
* @notice Implements the basic logic to burn a scaled balance token.
* @dev In some instances, a burn transaction will emit a mint event
* if the amount to burn is less than the interest that the user accrued
* @param user The user which debt is burnt
* @param target The address that will receive the underlying, if any
* @param amountScaled The scaled amount getting burned
* @param index The variable debt index of the reserve
* @param getTokenBalance The function to get the balance of the token
* @return `true` if the the new balance of the user is 0
*/
function _burnScaled(
address user,
address target,
uint256 amountScaled,
uint256 index,
function(uint256, uint256) internal pure returns (uint256) getTokenBalance
) internal returns (bool) {
require(amountScaled != 0, Errors.InvalidBurnAmount());
uint256 scaledBalance = super.balanceOf(user);
uint256 nextBalance = getTokenBalance(scaledBalance - amountScaled, index);
uint256 previousBalance = getTokenBalance(scaledBalance, _userState[user].additionalData);
uint256 balanceIncrease = getTokenBalance(scaledBalance, index) - previousBalance;
_userState[user].additionalData = index.toUint128();
_burn(user, amountScaled.toUint120());
if (nextBalance > previousBalance) {
uint256 amountToMint = nextBalance - previousBalance;
emit Transfer(address(0), user, amountToMint);
emit Mint(user, user, amountToMint, balanceIncrease, index);
} else {
uint256 amountToBurn = previousBalance - nextBalance;
emit Transfer(user, address(0), amountToBurn);
emit Burn(user, target, amountToBurn, balanceIncrease, index);
}
return scaledBalance - amountScaled == 0;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {WadRayMath} from '../../libraries/math/WadRayMath.sol';
/**
* @title TokenMath
* @author BGD Labs
* @notice Provides utility functions for calculating scaled amounts and balances for aTokens and vTokens,
* applying specific rounding rules (floor/ceil) as per Aave v3.5's rounding improvements.
* The rounding behavior of the operations is in line with the ERC-4626 token standard.
* In practice, this means rounding in favor of the protocol.
*/
library TokenMath {
using WadRayMath for uint256;
/**
* @notice Calculates the scaled amount of aTokens to mint when supplying underlying assets.
* The amount is rounded down to ensure the minted aTokens are less than or equal to the supplied amount.
* @param amount The amount of underlying asset supplied.
* @param liquidityIndex The current aToken liquidityIndex.
* @return The scaled amount of aTokens to mint.
*/
function getATokenMintScaledAmount(
uint256 amount,
uint256 liquidityIndex
) internal pure returns (uint256) {
return amount.rayDivFloor(liquidityIndex);
}
/**
* @notice Calculates the scaled amount of aTokens to burn when withdrawing underlying assets.
* The scaled amount is rounded up to ensure the user's aToken balance is sufficiently reduced.
* @param amount The amount of underlying asset to withdraw.
* @param liquidityIndex The current aToken liquidityIndex.
* @return The scaled amount of aTokens to burn.
*/
function getATokenBurnScaledAmount(
uint256 amount,
uint256 liquidityIndex
) internal pure returns (uint256) {
return amount.rayDivCeil(liquidityIndex);
}
/**
* @notice Calculates the scaled amount of aTokens to transfer.
* The scaled amount is rounded up to ensure the recipient receives at least the requested amount.
* @param amount The amount of aTokens to transfer.
* @param liquidityIndex The current aToken liquidityIndex.
* @return The scaled amount of aTokens for transfer.
*/
function getATokenTransferScaledAmount(
uint256 amount,
uint256 liquidityIndex
) internal pure returns (uint256) {
return amount.rayDivCeil(liquidityIndex);
}
/**
* @notice Calculates the actual aToken balance from a scaled balance and the current liquidityIndex.
* The balance is rounded down to prevent overaccounting.
* @param scaledAmount The scaled aToken balance.
* @param liquidityIndex The current aToken liquidityIndex.
* @return The actual aToken balance.
*/
function getATokenBalance(
uint256 scaledAmount,
uint256 liquidityIndex
) internal pure returns (uint256) {
return scaledAmount.rayMulFloor(liquidityIndex);
}
/**
* @notice Calculates the scaled amount of vTokens to mint when borrowing.
* The amount is rounded up to ensure the protocol never underaccounts the user's debt.
* @param amount The amount of underlying asset borrowed.
* @param variableBorrowIndex The current vToken variableBorrowIndex.
* @return The scaled amount of vTokens to mint.
*/
function getVTokenMintScaledAmount(
uint256 amount,
uint256 variableBorrowIndex
) internal pure returns (uint256) {
return amount.rayDivCeil(variableBorrowIndex);
}
/**
* @notice Calculates the scaled amount of vTokens to burn.
* The scaled amount is rounded down to prevent over-burning of vTokens.
* @param amount The amount of underlying asset corresponding to the vTokens to burn.
* @param variableBorrowIndex The current vToken variableBorrowIndex.
* @return The scaled amount of vTokens to burn.
*/
function getVTokenBurnScaledAmount(
uint256 amount,
uint256 variableBorrowIndex
) internal pure returns (uint256) {
return amount.rayDivFloor(variableBorrowIndex);
}
/**
* @notice Calculates the actual vToken balance (debt) from a scaled balance and the current variableBorrowIndex.
* The balance is rounded up to prevent underaccounting the user's debt.
* @param scaledAmount The scaled vToken balance.
* @param variableBorrowIndex The current vToken variableBorrowIndex.
* @return The actual vToken balance (debt).
*/
function getVTokenBalance(
uint256 scaledAmount,
uint256 variableBorrowIndex
) internal pure returns (uint256) {
return scaledAmount.rayMulCeil(variableBorrowIndex);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title IPoolAddressesProvider
* @author Aave
* @notice Defines the basic interface for a Pool Addresses Provider.
*/
interface IPoolAddressesProvider {
/**
* @dev Emitted when the market identifier is updated.
* @param oldMarketId The old id of the market
* @param newMarketId The new id of the market
*/
event MarketIdSet(string indexed oldMarketId, string indexed newMarketId);
/**
* @dev Emitted when the pool is updated.
* @param oldAddress The old address of the Pool
* @param newAddress The new address of the Pool
*/
event PoolUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the pool configurator is updated.
* @param oldAddress The old address of the PoolConfigurator
* @param newAddress The new address of the PoolConfigurator
*/
event PoolConfiguratorUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the price oracle is updated.
* @param oldAddress The old address of the PriceOracle
* @param newAddress The new address of the PriceOracle
*/
event PriceOracleUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the ACL manager is updated.
* @param oldAddress The old address of the ACLManager
* @param newAddress The new address of the ACLManager
*/
event ACLManagerUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the ACL admin is updated.
* @param oldAddress The old address of the ACLAdmin
* @param newAddress The new address of the ACLAdmin
*/
event ACLAdminUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the price oracle sentinel is updated.
* @param oldAddress The old address of the PriceOracleSentinel
* @param newAddress The new address of the PriceOracleSentinel
*/
event PriceOracleSentinelUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the pool data provider is updated.
* @param oldAddress The old address of the PoolDataProvider
* @param newAddress The new address of the PoolDataProvider
*/
event PoolDataProviderUpdated(address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when a new proxy is created.
* @param id The identifier of the proxy
* @param proxyAddress The address of the created proxy contract
* @param implementationAddress The address of the implementation contract
*/
event ProxyCreated(
bytes32 indexed id,
address indexed proxyAddress,
address indexed implementationAddress
);
/**
* @dev Emitted when a new non-proxied contract address is registered.
* @param id The identifier of the contract
* @param oldAddress The address of the old contract
* @param newAddress The address of the new contract
*/
event AddressSet(bytes32 indexed id, address indexed oldAddress, address indexed newAddress);
/**
* @dev Emitted when the implementation of the proxy registered with id is updated
* @param id The identifier of the contract
* @param proxyAddress The address of the proxy contract
* @param oldImplementationAddress The address of the old implementation contract
* @param newImplementationAddress The address of the new implementation contract
*/
event AddressSetAsProxy(
bytes32 indexed id,
address indexed proxyAddress,
address oldImplementationAddress,
address indexed newImplementationAddress
);
/**
* @notice Returns the id of the Aave market to which this contract points to.
* @return The market id
*/
function getMarketId() external view returns (string memory);
/**
* @notice Associates an id with a specific PoolAddressesProvider.
* @dev This can be used to create an onchain registry of PoolAddressesProviders to
* identify and validate multiple Aave markets.
* @param newMarketId The market id
*/
function setMarketId(string calldata newMarketId) external;
/**
* @notice Returns an address by its identifier.
* @dev The returned address might be an EOA or a contract, potentially proxied
* @dev It returns ZERO if there is no registered address with the given id
* @param id The id
* @return The address of the registered for the specified id
*/
function getAddress(bytes32 id) external view returns (address);
/**
* @notice General function to update the implementation of a proxy registered with
* certain `id`. If there is no proxy registered, it will instantiate one and
* set as implementation the `newImplementationAddress`.
* @dev IMPORTANT Use this function carefully, only for ids that don't have an explicit
* setter function, in order to avoid unexpected consequences
* @param id The id
* @param newImplementationAddress The address of the new implementation
*/
function setAddressAsProxy(bytes32 id, address newImplementationAddress) external;
/**
* @notice Sets an address for an id replacing the address saved in the addresses map.
* @dev IMPORTANT Use this function carefully, as it will do a hard replacement
* @param id The id
* @param newAddress The address to set
*/
function setAddress(bytes32 id, address newAddress) external;
/**
* @notice Returns the address of the Pool proxy.
* @return The Pool proxy address
*/
function getPool() external view returns (address);
/**
* @notice Updates the implementation of the Pool, or creates a proxy
* setting the new `pool` implementation when the function is called for the first time.
* @param newPoolImpl The new Pool implementation
*/
function setPoolImpl(address newPoolImpl) external;
/**
* @notice Returns the address of the PoolConfigurator proxy.
* @return The PoolConfigurator proxy address
*/
function getPoolConfigurator() external view returns (address);
/**
* @notice Updates the implementation of the PoolConfigurator, or creates a proxy
* setting the new `PoolConfigurator` implementation when the function is called for the first time.
* @param newPoolConfiguratorImpl The new PoolConfigurator implementation
*/
function setPoolConfiguratorImpl(address newPoolConfiguratorImpl) external;
/**
* @notice Returns the address of the price oracle.
* @return The address of the PriceOracle
*/
function getPriceOracle() external view returns (address);
/**
* @notice Updates the address of the price oracle.
* @param newPriceOracle The address of the new PriceOracle
*/
function setPriceOracle(address newPriceOracle) external;
/**
* @notice Returns the address of the ACL manager.
* @return The address of the ACLManager
*/
function getACLManager() external view returns (address);
/**
* @notice Updates the address of the ACL manager.
* @param newAclManager The address of the new ACLManager
*/
function setACLManager(address newAclManager) external;
/**
* @notice Returns the address of the ACL admin.
* @return The address of the ACL admin
*/
function getACLAdmin() external view returns (address);
/**
* @notice Updates the address of the ACL admin.
* @param newAclAdmin The address of the new ACL admin
*/
function setACLAdmin(address newAclAdmin) external;
/**
* @notice Returns the address of the price oracle sentinel.
* @return The address of the PriceOracleSentinel
*/
function getPriceOracleSentinel() external view returns (address);
/**
* @notice Updates the address of the price oracle sentinel.
* @param newPriceOracleSentinel The address of the new PriceOracleSentinel
*/
function setPriceOracleSentinel(address newPriceOracleSentinel) external;
/**
* @notice Returns the address of the data provider.
* @return The address of the DataProvider
*/
function getPoolDataProvider() external view returns (address);
/**
* @notice Updates the address of the data provider.
* @param newDataProvider The address of the new DataProvider
*/
function setPoolDataProvider(address newDataProvider) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library DataTypes {
/**
* This exists specifically to maintain the `getReserveData()` interface, since the new, internal
* `ReserveData` struct includes the reserve's `virtualUnderlyingBalance`.
*/
struct ReserveDataLegacy {
//stores the reserve configuration
ReserveConfigurationMap configuration;
//the liquidity index. Expressed in ray
uint128 liquidityIndex;
//the current supply rate. Expressed in ray
uint128 currentLiquidityRate;
//variable borrow index. Expressed in ray
uint128 variableBorrowIndex;
//the current variable borrow rate. Expressed in ray
uint128 currentVariableBorrowRate;
// DEPRECATED on v3.2.0
uint128 currentStableBorrowRate;
//timestamp of last update
uint40 lastUpdateTimestamp;
//the id of the reserve. Represents the position in the list of the active reserves
uint16 id;
//aToken address
address aTokenAddress;
// DEPRECATED on v3.2.0
address stableDebtTokenAddress;
//variableDebtToken address
address variableDebtTokenAddress;
// DEPRECATED on v3.4.0, should use the `RESERVE_INTEREST_RATE_STRATEGY` variable from the Pool contract
address interestRateStrategyAddress;
//the current treasury balance, scaled
uint128 accruedToTreasury;
// DEPRECATED on v3.4.0
uint128 unbacked;
//the outstanding debt borrowed against this asset in isolation mode
uint128 isolationModeTotalDebt;
}
struct ReserveData {
//stores the reserve configuration
ReserveConfigurationMap configuration;
//the liquidity index. Expressed in ray
uint128 liquidityIndex;
//the current supply rate. Expressed in ray
uint128 currentLiquidityRate;
//variable borrow index. Expressed in ray
uint128 variableBorrowIndex;
//the current variable borrow rate. Expressed in ray
uint128 currentVariableBorrowRate;
/// @notice reused `__deprecatedStableBorrowRate` storage from pre 3.2
// the current accumulate deficit in underlying tokens
uint128 deficit;
//timestamp of last update
uint40 lastUpdateTimestamp;
//the id of the reserve. Represents the position in the list of the active reserves
uint16 id;
//timestamp until when liquidations are not allowed on the reserve, if set to past liquidations will be allowed
uint40 liquidationGracePeriodUntil;
//aToken address
address aTokenAddress;
// DEPRECATED on v3.2.0
address __deprecatedStableDebtTokenAddress;
//variableDebtToken address
address variableDebtTokenAddress;
// DEPRECATED on v3.4.0, should use the `RESERVE_INTEREST_RATE_STRATEGY` variable from the Pool contract
address __deprecatedInterestRateStrategyAddress;
//the current treasury balance, scaled
uint128 accruedToTreasury;
// In aave 3.3.0 this storage slot contained the `unbacked`
uint128 virtualUnderlyingBalance;
//the outstanding debt borrowed against this asset in isolation mode
uint128 isolationModeTotalDebt;
//the amount of underlying accounted for by the protocol
// DEPRECATED on v3.4.0. Moved into the same slot as accruedToTreasury for optimized storage access.
uint128 __deprecatedVirtualUnderlyingBalance;
}
struct ReserveConfigurationMap {
//bit 0-15: LTV
//bit 16-31: Liq. threshold
//bit 32-47: Liq. bonus
//bit 48-55: Decimals
//bit 56: reserve is active
//bit 57: reserve is frozen
//bit 58: borrowing is enabled
//bit 59: DEPRECATED: stable rate borrowing enabled
//bit 60: asset is paused
//bit 61: borrowing in isolation mode is enabled
//bit 62: siloed borrowing enabled
//bit 63: flashloaning enabled
//bit 64-79: reserve factor
//bit 80-115: borrow cap in whole tokens, borrowCap == 0 => no cap
//bit 116-151: supply cap in whole tokens, supplyCap == 0 => no cap
//bit 152-167: liquidation protocol fee
//bit 168-175: DEPRECATED: eMode category
//bit 176-211: DEPRECATED: unbacked mint cap
//bit 212-251: debt ceiling for isolation mode with (ReserveConfiguration::DEBT_CEILING_DECIMALS) decimals
//bit 252: DEPRECATED: virtual accounting is enabled for the reserve
//bit 253-255 unused
uint256 data;
}
struct UserConfigurationMap {
/**
* @dev Bitmap of the users collaterals and borrows. It is divided in pairs of bits, one pair per asset.
* The first bit indicates if an asset is used as collateral by the user, the second whether an
* asset is borrowed by the user.
*/
uint256 data;
}
// DEPRECATED: kept for backwards compatibility, might be removed in a future version
struct EModeCategoryLegacy {
// each eMode category has a custom ltv and liquidation threshold
uint16 ltv;
uint16 liquidationThreshold;
uint16 liquidationBonus;
// DEPRECATED
address priceSource;
string label;
}
struct CollateralConfig {
uint16 ltv;
uint16 liquidationThreshold;
uint16 liquidationBonus;
}
struct EModeCategoryBaseConfiguration {
uint16 ltv;
uint16 liquidationThreshold;
uint16 liquidationBonus;
string label;
}
struct EModeCategory {
// each eMode category has a custom ltv and liquidation threshold
uint16 ltv;
uint16 liquidationThreshold;
uint16 liquidationBonus;
uint128 collateralBitmap;
string label;
uint128 borrowableBitmap;
}
enum InterestRateMode {
NONE,
__DEPRECATED,
VARIABLE
}
struct ReserveCache {
uint256 currScaledVariableDebt;
uint256 nextScaledVariableDebt;
uint256 currLiquidityIndex;
uint256 nextLiquidityIndex;
uint256 currVariableBorrowIndex;
uint256 nextVariableBorrowIndex;
uint256 currLiquidityRate;
uint256 currVariableBorrowRate;
uint256 reserveFactor;
ReserveConfigurationMap reserveConfiguration;
address aTokenAddress;
address variableDebtTokenAddress;
uint40 reserveLastUpdateTimestamp;
}
struct ExecuteLiquidationCallParams {
address liquidator;
uint256 debtToCover;
address collateralAsset;
address debtAsset;
address borrower;
bool receiveAToken;
address priceOracle;
uint8 borrowerEModeCategory;
address priceOracleSentinel;
address interestRateStrategyAddress;
}
struct ExecuteSupplyParams {
address user;
address asset;
address interestRateStrategyAddress;
uint256 amount;
address onBehalfOf;
uint16 referralCode;
}
struct ExecuteBorrowParams {
address asset;
address user;
address onBehalfOf;
address interestRateStrategyAddress;
uint256 amount;
InterestRateMode interestRateMode;
uint16 referralCode;
bool releaseUnderlying;
address oracle;
uint8 userEModeCategory;
address priceOracleSentinel;
}
struct ExecuteRepayParams {
address asset;
address user;
address interestRateStrategyAddress;
uint256 amount;
InterestRateMode interestRateMode;
address onBehalfOf;
bool useATokens;
address oracle;
uint8 userEModeCategory;
}
struct ExecuteWithdrawParams {
address user;
address asset;
address interestRateStrategyAddress;
uint256 amount;
address to;
address oracle;
uint8 userEModeCategory;
}
struct ExecuteEliminateDeficitParams {
address user;
address asset;
address interestRateStrategyAddress;
uint256 amount;
}
struct FinalizeTransferParams {
address asset;
address from;
address to;
uint256 scaledAmount;
uint256 scaledBalanceFromBefore;
uint256 scaledBalanceToBefore;
address oracle;
uint8 fromEModeCategory;
}
struct FlashloanParams {
address user;
address receiverAddress;
address[] assets;
uint256[] amounts;
uint256[] interestRateModes;
address interestRateStrategyAddress;
address onBehalfOf;
bytes params;
uint16 referralCode;
uint256 flashLoanPremium;
address addressesProvider;
address pool;
uint8 userEModeCategory;
bool isAuthorizedFlashBorrower;
}
struct FlashloanSimpleParams {
address user;
address receiverAddress;
address asset;
address interestRateStrategyAddress;
uint256 amount;
bytes params;
uint16 referralCode;
uint256 flashLoanPremium;
}
struct FlashLoanRepaymentParams {
address user;
uint256 amount;
uint256 totalPremium;
address asset;
address interestRateStrategyAddress;
address receiverAddress;
uint16 referralCode;
}
struct CalculateUserAccountDataParams {
UserConfigurationMap userConfig;
address user;
address oracle;
uint8 userEModeCategory;
}
struct ValidateBorrowParams {
ReserveCache reserveCache;
UserConfigurationMap userConfig;
address asset;
address userAddress;
uint256 amountScaled;
InterestRateMode interestRateMode;
address oracle;
uint8 userEModeCategory;
address priceOracleSentinel;
}
struct ValidateLiquidationCallParams {
ReserveCache debtReserveCache;
uint256 totalDebt;
uint256 healthFactor;
address priceOracleSentinel;
address borrower;
address liquidator;
}
struct CalculateInterestRatesParams {
uint256 unbacked;
uint256 liquidityAdded;
uint256 liquidityTaken;
uint256 totalDebt;
uint256 reserveFactor;
address reserve;
// @notice DEPRECATED in 3.4, but kept for backwards compatibility
bool usingVirtualBalance;
uint256 virtualUnderlyingBalance;
}
struct InitReserveParams {
address asset;
address aTokenAddress;
address variableDebtAddress;
uint16 reservesCount;
uint16 maxNumberReserves;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title IAaveIncentivesController
* @author Aave
* @notice Defines the basic interface for an Aave Incentives Controller.
* @dev It only contains one single function, needed as a hook on aToken and debtToken transfers.
*/
interface IAaveIncentivesController {
/**
* @dev Called by the corresponding asset on transfer hook in order to update the rewards distribution.
* @dev The units of `totalSupply` and `userBalance` should be the same.
* @param user The address of the user whose asset balance has changed
* @param totalSupply The total supply of the asset prior to user balance change
* @param userBalance The previous user balance prior to balance change
*/
function handleAction(address user, uint256 totalSupply, uint256 userBalance) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title IScaledBalanceToken
* @author Aave
* @notice Defines the basic interface for a scaled-balance token.
*/
interface IScaledBalanceToken {
/**
* @dev Emitted after the mint action
* @param caller The address performing the mint
* @param onBehalfOf The address of the user that will receive the minted tokens
* @param value The scaled-up amount being minted (based on user entered amount and balance increase from interest)
* @param balanceIncrease The increase in scaled-up balance since the last action of 'onBehalfOf'
* @param index The next liquidity index of the reserve
*/
event Mint(
address indexed caller,
address indexed onBehalfOf,
uint256 value,
uint256 balanceIncrease,
uint256 index
);
/**
* @dev Emitted after the burn action
* @dev If the burn function does not involve a transfer of the underlying asset, the target defaults to zero address
* @param from The address from which the tokens will be burned
* @param target The address that will receive the underlying, if any
* @param value The scaled-up amount being burned (user entered amount - balance increase from interest)
* @param balanceIncrease The increase in scaled-up balance since the last action of 'from'
* @param index The next liquidity index of the reserve
*/
event Burn(
address indexed from,
address indexed target,
uint256 value,
uint256 balanceIncrease,
uint256 index
);
/**
* @notice Returns the scaled balance of the user.
* @dev The scaled balance is the sum of all the updated stored balance divided by the reserve's liquidity index
* at the moment of the update
* @param user The user whose balance is calculated
* @return The scaled balance of the user
*/
function scaledBalanceOf(address user) external view returns (uint256);
/**
* @notice Returns the scaled balance of the user and the scaled total supply.
* @param user The address of the user
* @return The scaled balance of the user
* @return The scaled total supply
*/
function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256);
/**
* @notice Returns the scaled total supply of the scaled balance token. Represents sum(debt/index)
* @return The scaled total supply
*/
function scaledTotalSupply() external view returns (uint256);
/**
* @notice Returns last index interest was accrued to the user's balance
* @param user The address of the user
* @return The last index interest was accrued to the user's balance, expressed in ray
*/
function getPreviousIndex(address user) external view returns (uint256);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.20;
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS
}
/**
* @dev The signature derives the `address(0)`.
*/
error ECDSAInvalidSignature();
/**
* @dev The signature has an invalid length.
*/
error ECDSAInvalidSignatureLength(uint256 length);
/**
* @dev The signature has an S value that is in the upper half order.
*/
error ECDSAInvalidSignatureS(bytes32 s);
/**
* @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
* return address(0) without also returning an error description. Errors are documented using an enum (error type)
* and a bytes32 providing additional information about the error.
*
* If no error is returned, then the address can be used for verification purposes.
*
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*/
function tryRecover(
bytes32 hash,
bytes memory signature
) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly ("memory-safe") {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures]
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
unchecked {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
// We do not check for an overflow here since the shift operation results in 0 or 1.
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*/
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS, s);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature, bytes32(0));
}
return (signer, RecoverError.NoError, bytes32(0));
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
*/
function _throwError(RecoverError error, bytes32 errorArg) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert ECDSAInvalidSignature();
} else if (error == RecoverError.InvalidSignatureLength) {
revert ECDSAInvalidSignatureLength(uint256(errorArg));
} else if (error == RecoverError.InvalidSignatureS) {
revert ECDSAInvalidSignatureS(errorArg);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
/*
* @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 {
function _msgSender() internal view virtual returns (address payable) {
return payable(msg.sender);
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title ICreditDelegationToken
* @author Aave
* @notice Defines the basic interface for a token supporting credit delegation.
*/
interface ICreditDelegationToken {
/**
* @dev Emitted on `approveDelegation` and `borrowAllowance
* @param fromUser The address of the delegator
* @param toUser The address of the delegatee
* @param asset The address of the delegated asset
* @param amount The amount being delegated
*/
event BorrowAllowanceDelegated(
address indexed fromUser,
address indexed toUser,
address indexed asset,
uint256 amount
);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in borrowing.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error InsufficientBorrowAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @notice Delegates borrowing power to a user on the specific debt token.
* Delegation will still respect the liquidation constraints (even if delegated, a
* delegatee cannot force a delegator HF to go below 1)
* @param delegatee The address receiving the delegated borrowing power
* @param amount The maximum amount being delegated.
*/
function approveDelegation(address delegatee, uint256 amount) external;
/**
* @notice Returns the borrow allowance of the user
* @param fromUser The user to giving allowance
* @param toUser The user to give allowance to
* @return The current allowance of `toUser`
*/
function borrowAllowance(address fromUser, address toUser) external view returns (uint256);
/**
* @notice Delegates borrowing power to a user on the specific debt token via ERC712 signature
* @param delegator The delegator of the credit
* @param delegatee The delegatee that can use the credit
* @param value The amount to be delegated
* @param deadline The deadline timestamp, type(uint256).max for max deadline
* @param v The V signature param
* @param s The S signature param
* @param r The R signature param
*/
function delegationWithSig(
address delegator,
address delegatee,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
/**
* @title WadRayMath library
* @author Aave
* @notice Provides functions to perform calculations with Wad and Ray units
* @dev Provides mul and div function for wads (decimal numbers with 18 digits of precision) and rays (decimal numbers
* with 27 digits of precision).
* @dev Default operations round half up (if a value is >= .5, it will be rounded up, otherwise rounded down).
* @dev For specific rounding behaviors, functions with `Floor` and `Ceil` suffixes or a `Rounding` parameter are available.
*/
library WadRayMath {
enum Rounding {
Floor,
Ceil
}
// HALF_WAD and HALF_RAY expressed with extended notation as constant with operations are not supported in Yul assembly
uint256 internal constant WAD = 1e18;
uint256 internal constant HALF_WAD = 0.5e18;
uint256 internal constant RAY = 1e27;
uint256 internal constant HALF_RAY = 0.5e27;
uint256 internal constant WAD_RAY_RATIO = 1e9;
/**
* @dev Multiplies two wad, rounding half up to the nearest wad
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
* @param a Wad
* @param b Wad
* @return c = a*b, in wad
*/
function wadMul(uint256 a, uint256 b) internal pure returns (uint256 c) {
// to avoid overflow, a <= (type(uint256).max - HALF_WAD) / b
assembly {
if iszero(or(iszero(b), iszero(gt(a, div(sub(not(0), HALF_WAD), b))))) {
revert(0, 0)
}
c := div(add(mul(a, b), HALF_WAD), WAD)
}
}
/**
* @dev Divides two wad, rounding half up to the nearest wad
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
* @param a Wad
* @param b Wad
* @return c = a/b, in wad
*/
function wadDiv(uint256 a, uint256 b) internal pure returns (uint256 c) {
// to avoid overflow, a <= (type(uint256).max - halfB) / WAD
assembly {
if or(iszero(b), iszero(iszero(gt(a, div(sub(not(0), div(b, 2)), WAD))))) {
revert(0, 0)
}
c := div(add(mul(a, WAD), div(b, 2)), b)
}
}
function rayMul(uint256 a, uint256 b) internal pure returns (uint256 c) {
assembly {
// to avoid overflow, a <= (type(uint256).max - HALF_RAY) / b
if iszero(or(iszero(b), iszero(gt(a, div(sub(not(0), HALF_RAY), b))))) {
revert(0, 0)
}
c := div(add(mul(a, b), HALF_RAY), RAY)
}
}
function rayMul(uint256 a, uint256 b, Rounding rounding) internal pure returns (uint256 c) {
if (rounding == Rounding.Floor) return rayMulFloor(a, b);
return rayMulCeil(a, b);
}
function rayMulFloor(uint256 a, uint256 b) internal pure returns (uint256 c) {
assembly {
// Overflow check: Ensure a * b does not exceed uint256 max
if iszero(or(iszero(b), iszero(gt(a, div(not(0), b))))) {
revert(0, 0)
}
c := div(mul(a, b), RAY)
}
}
function rayMulCeil(uint256 a, uint256 b) internal pure returns (uint256 c) {
assembly {
// Overflow check: Ensure a * b does not exceed uint256 max
if iszero(or(iszero(b), iszero(gt(a, div(not(0), b))))) {
revert(0, 0)
}
let product := mul(a, b)
c := add(div(product, RAY), iszero(iszero(mod(product, RAY))))
}
}
/**
* @notice Divides two ray, rounding half up to the nearest ray
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
* @param a Ray
* @param b Ray
* @return c = a raydiv b
*/
function rayDiv(uint256 a, uint256 b) internal pure returns (uint256 c) {
assembly {
// to avoid overflow, a <= (type(uint256).max - b / 2) / RAY
if or(iszero(b), iszero(iszero(gt(a, div(sub(not(0), div(b, 2)), RAY))))) {
revert(0, 0)
}
c := div(add(mul(a, RAY), div(b, 2)), b)
}
}
function rayDiv(uint256 a, uint256 b, Rounding rounding) internal pure returns (uint256 c) {
if (rounding == Rounding.Floor) return rayDivFloor(a, b);
return rayDivCeil(a, b);
}
function rayDivCeil(uint256 a, uint256 b) internal pure returns (uint256 c) {
assembly {
// Overflow check: Ensure a * RAY does not exceed uint256 max
if or(iszero(b), iszero(iszero(gt(a, div(not(0), RAY))))) {
revert(0, 0)
}
let scaled := mul(a, RAY)
c := add(div(scaled, b), iszero(iszero(mod(scaled, b))))
}
}
function rayDivFloor(uint256 a, uint256 b) internal pure returns (uint256 c) {
assembly {
// Overflow check: Ensure a * RAY does not exceed uint256 max
if or(iszero(b), iszero(iszero(gt(a, div(not(0), RAY))))) {
revert(0, 0)
}
c := div(mul(a, RAY), b)
}
}
/**
* @dev Casts ray down to wad
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
* @param a Ray
* @return b = a converted to wad, rounded half up to the nearest wad
*/
function rayToWad(uint256 a) internal pure returns (uint256 b) {
assembly {
b := div(a, WAD_RAY_RATIO)
let remainder := mod(a, WAD_RAY_RATIO)
if iszero(lt(remainder, div(WAD_RAY_RATIO, 2))) {
b := add(b, 1)
}
}
}
/**
* @dev Converts wad up to ray
* @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328
* @param a Wad
* @return b = a converted in ray
*/
function wadToRay(uint256 a) internal pure returns (uint256 b) {
// to avoid overflow, b/WAD_RAY_RATIO == a
assembly {
b := mul(a, WAD_RAY_RATIO)
if iszero(eq(div(b, WAD_RAY_RATIO), a)) {
revert(0, 0)
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import {IAaveIncentivesController} from '../../../interfaces/IAaveIncentivesController.sol';
import {IPool} from '../../../interfaces/IPool.sol';
import {IncentivizedERC20} from './IncentivizedERC20.sol';
/**
* @title MintableIncentivizedERC20
* @author Aave
* @notice Implements mint and burn functions for IncentivizedERC20
*/
abstract contract MintableIncentivizedERC20 is IncentivizedERC20 {
/**
* @dev Constructor.
* @param pool The reference to the main Pool contract
* @param name The name of the token
* @param symbol The symbol of the token
* @param decimals The number of decimals of the token
* @param rewardsController The address of the rewards controller contract
*/
constructor(
IPool pool,
string memory name,
string memory symbol,
uint8 decimals,
address rewardsController
) IncentivizedERC20(pool, name, symbol, decimals, rewardsController) {
// Intentionally left blank
}
/**
* @notice Mints tokens to an account and apply incentives if defined
* @param account The address receiving tokens
* @param amount The amount of tokens to mint
*/
function _mint(address account, uint120 amount) internal virtual {
uint256 oldTotalSupply = _totalSupply;
_totalSupply = oldTotalSupply + amount;
uint120 oldAccountBalance = _userState[account].balance;
_userState[account].balance = oldAccountBalance + amount;
if (address(REWARDS_CONTROLLER) != address(0)) {
REWARDS_CONTROLLER.handleAction(account, oldTotalSupply, oldAccountBalance);
}
}
/**
* @notice Burns tokens from an account and apply incentives if defined
* @param account The account whose tokens are burnt
* @param amount The amount of tokens to burn
*/
function _burn(address account, uint120 amount) internal virtual {
uint256 oldTotalSupply = _totalSupply;
_totalSupply = oldTotalSupply - amount;
uint120 oldAccountBalance = _userState[account].balance;
_userState[account].balance = oldAccountBalance - amount;
if (address(REWARDS_CONTROLLER) != address(0)) {
REWARDS_CONTROLLER.handleAction(account, oldTotalSupply, oldAccountBalance);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import {Context} from '../../../dependencies/openzeppelin/contracts/Context.sol';
import {IERC20} from '../../../dependencies/openzeppelin/contracts/IERC20.sol';
import {IERC20Detailed} from '../../../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
import {SafeCast} from 'openzeppelin-contracts/contracts/utils/math/SafeCast.sol';
import {WadRayMath} from '../../libraries/math/WadRayMath.sol';
import {Errors} from '../../libraries/helpers/Errors.sol';
import {IAaveIncentivesController} from '../../../interfaces/IAaveIncentivesController.sol';
import {IPoolAddressesProvider} from '../../../interfaces/IPoolAddressesProvider.sol';
import {IPool} from '../../../interfaces/IPool.sol';
import {IACLManager} from '../../../interfaces/IACLManager.sol';
import {DelegationMode} from './DelegationMode.sol';
/**
* @title IncentivizedERC20
* @author Aave, inspired by the Openzeppelin ERC20 implementation
* @notice Basic ERC20 implementation
*/
abstract contract IncentivizedERC20 is Context, IERC20Detailed {
using WadRayMath for uint256;
using SafeCast for uint256;
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Only pool admin can call functions marked by this modifier.
*/
modifier onlyPoolAdmin() {
IACLManager aclManager = IACLManager(_addressesProvider.getACLManager());
require(aclManager.isPoolAdmin(_msgSender()), Errors.CallerNotPoolAdmin());
_;
}
/**
* @dev Only pool can call functions marked by this modifier.
*/
modifier onlyPool() {
require(_msgSender() == address(POOL), Errors.CallerMustBePool());
_;
}
/**
* @dev UserState - additionalData is a flexible field.
* ATokens and VariableDebtTokens use this field store the index of the
* user's last supply/withdrawal/borrow/repayment.
*/
struct UserState {
uint120 balance;
DelegationMode delegationMode;
uint128 additionalData;
}
// Map of users address and their state data (userAddress => userStateData)
mapping(address => UserState) internal _userState;
// Map of allowances (delegator => delegatee => allowanceAmount)
mapping(address => mapping(address => uint256)) private _allowances;
uint256 internal _totalSupply;
string private _name;
string private _symbol;
uint8 private _decimals;
// @dev deprecated on v3.4.0, replaced with immutable REWARDS_CONTROLLER
IAaveIncentivesController internal __deprecated_incentivesController;
IPoolAddressesProvider internal immutable _addressesProvider;
IPool public immutable POOL;
/**
* @notice Returns the address of the Incentives Controller contract
* @return The address of the Incentives Controller
*/
IAaveIncentivesController public immutable REWARDS_CONTROLLER;
/**
* @dev Constructor.
* @param pool The reference to the main Pool contract
* @param name_ The name of the token
* @param symbol_ The symbol of the token
* @param decimals_ The number of decimals of the token
* @param rewardsController The address of the rewards controller contract
*/
constructor(
IPool pool,
string memory name_,
string memory symbol_,
uint8 decimals_,
address rewardsController
) {
_addressesProvider = pool.ADDRESSES_PROVIDER();
_name = name_;
_symbol = symbol_;
_decimals = decimals_;
POOL = pool;
REWARDS_CONTROLLER = IAaveIncentivesController(rewardsController);
}
/// @inheritdoc IERC20Detailed
function name() public view override returns (string memory) {
return _name;
}
/// @inheritdoc IERC20Detailed
function symbol() external view override returns (string memory) {
return _symbol;
}
/// @inheritdoc IERC20Detailed
function decimals() external view override returns (uint8) {
return _decimals;
}
/// @inheritdoc IERC20
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/// @inheritdoc IERC20
function balanceOf(address account) public view virtual override returns (uint256) {
return _userState[account].balance;
}
/**
* @notice Returns the address of the Incentives Controller contract
* @return The address of the Incentives Controller
*/
function getIncentivesController() external view virtual returns (IAaveIncentivesController) {
return REWARDS_CONTROLLER;
}
/// @inheritdoc IERC20
function transfer(address recipient, uint256 amount) external virtual override returns (bool) {
uint120 castAmount = amount.toUint120();
_transfer(_msgSender(), recipient, castAmount);
return true;
}
/// @inheritdoc IERC20
function allowance(
address owner,
address spender
) external view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/// @inheritdoc IERC20
function approve(address spender, uint256 amount) external virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
/// @inheritdoc IERC20
function transferFrom(
address sender,
address recipient,
uint256 amount
) external virtual override returns (bool) {
uint120 castAmount = amount.toUint120();
_approve(sender, _msgSender(), _allowances[sender][_msgSender()] - castAmount);
_transfer(sender, recipient, castAmount);
return true;
}
/**
* @notice Increases the allowance of spender to spend _msgSender() tokens
* @param spender The user allowed to spend on behalf of _msgSender()
* @param addedValue The amount being added to the allowance
* @return `true`
*/
function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
return true;
}
/**
* @notice Decreases the allowance of spender to spend _msgSender() tokens
* @param spender The user allowed to spend on behalf of _msgSender()
* @param subtractedValue The amount being subtracted to the allowance
* @return `true`
*/
function decreaseAllowance(
address spender,
uint256 subtractedValue
) external virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] - subtractedValue);
return true;
}
/**
* @dev Updates `owner`'s allowance for `spender` based on spent `value`.
*
* Revert if not enough allowance is available.
*
* @param owner The owner of the tokens
* @param spender The user allowed to spend on behalf of owner
* @param amount The minimum amount being consumed from the allowance
* @param correctedAmount The maximum amount being consumed from the allowance
*/
function _spendAllowance(
address owner,
address spender,
uint256 amount,
uint256 correctedAmount
) internal virtual {
uint256 currentAllowance = _allowances[owner][spender];
if (currentAllowance < amount) {
revert ERC20InsufficientAllowance(spender, currentAllowance, amount);
}
uint256 consumption = currentAllowance >= correctedAmount ? correctedAmount : currentAllowance;
_approve(owner, spender, currentAllowance - consumption);
}
/**
* @notice Transfers tokens between two users and apply incentives if defined.
* @param sender The source address
* @param recipient The destination address
* @param amount The amount getting transferred
*/
function _transfer(address sender, address recipient, uint120 amount) internal virtual {
uint120 oldSenderBalance = _userState[sender].balance;
_userState[sender].balance = oldSenderBalance - amount;
uint120 oldRecipientBalance = _userState[recipient].balance;
_userState[recipient].balance = oldRecipientBalance + amount;
if (address(REWARDS_CONTROLLER) != address(0)) {
uint256 currentTotalSupply = _totalSupply;
REWARDS_CONTROLLER.handleAction(sender, currentTotalSupply, oldSenderBalance);
if (sender != recipient) {
REWARDS_CONTROLLER.handleAction(recipient, currentTotalSupply, oldRecipientBalance);
}
}
}
/**
* @notice Approve `spender` to use `amount` of `owner`s balance
* @param owner The address owning the tokens
* @param spender The address approved for spending
* @param amount The amount of tokens to approve spending of
*/
function _approve(address owner, address spender, uint256 amount) internal virtual {
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @notice Update the name of the token
* @param newName The new name for the token
*/
function _setName(string memory newName) internal {
_name = newName;
}
/**
* @notice Update the symbol for the token
* @param newSymbol The new symbol for the token
*/
function _setSymbol(string memory newSymbol) internal {
_symbol = newSymbol;
}
/**
* @notice Update the number of decimals for the token
* @param newDecimals The new number of decimals for the token
*/
function _setDecimals(uint8 newDecimals) internal {
_decimals = newDecimals;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import {IERC20} from './IERC20.sol';
interface IERC20Detailed is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IPoolAddressesProvider} from './IPoolAddressesProvider.sol';
/**
* @title IACLManager
* @author Aave
* @notice Defines the basic interface for the ACL Manager
*/
interface IACLManager {
/**
* @notice Returns the contract address of the PoolAddressesProvider
* @return The address of the PoolAddressesProvider
*/
function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider);
/**
* @notice Returns the identifier of the PoolAdmin role
* @return The id of the PoolAdmin role
*/
function POOL_ADMIN_ROLE() external view returns (bytes32);
/**
* @notice Returns the identifier of the EmergencyAdmin role
* @return The id of the EmergencyAdmin role
*/
function EMERGENCY_ADMIN_ROLE() external view returns (bytes32);
/**
* @notice Returns the identifier of the RiskAdmin role
* @return The id of the RiskAdmin role
*/
function RISK_ADMIN_ROLE() external view returns (bytes32);
/**
* @notice Returns the identifier of the FlashBorrower role
* @return The id of the FlashBorrower role
*/
function FLASH_BORROWER_ROLE() external view returns (bytes32);
/**
* @notice Returns the identifier of the Bridge role
* @return The id of the Bridge role
*/
function BRIDGE_ROLE() external view returns (bytes32);
/**
* @notice Returns the identifier of the AssetListingAdmin role
* @return The id of the AssetListingAdmin role
*/
function ASSET_LISTING_ADMIN_ROLE() external view returns (bytes32);
/**
* @notice Set the role as admin of a specific role.
* @dev By default the admin role for all roles is `DEFAULT_ADMIN_ROLE`.
* @param role The role to be managed by the admin role
* @param adminRole The admin role
*/
function setRoleAdmin(bytes32 role, bytes32 adminRole) external;
/**
* @notice Adds a new admin as PoolAdmin
* @param admin The address of the new admin
*/
function addPoolAdmin(address admin) external;
/**
* @notice Removes an admin as PoolAdmin
* @param admin The address of the admin to remove
*/
function removePoolAdmin(address admin) external;
/**
* @notice Returns true if the address is PoolAdmin, false otherwise
* @param admin The address to check
* @return True if the given address is PoolAdmin, false otherwise
*/
function isPoolAdmin(address admin) external view returns (bool);
/**
* @notice Adds a new admin as EmergencyAdmin
* @param admin The address of the new admin
*/
function addEmergencyAdmin(address admin) external;
/**
* @notice Removes an admin as EmergencyAdmin
* @param admin The address of the admin to remove
*/
function removeEmergencyAdmin(address admin) external;
/**
* @notice Returns true if the address is EmergencyAdmin, false otherwise
* @param admin The address to check
* @return True if the given address is EmergencyAdmin, false otherwise
*/
function isEmergencyAdmin(address admin) external view returns (bool);
/**
* @notice Adds a new admin as RiskAdmin
* @param admin The address of the new admin
*/
function addRiskAdmin(address admin) external;
/**
* @notice Removes an admin as RiskAdmin
* @param admin The address of the admin to remove
*/
function removeRiskAdmin(address admin) external;
/**
* @notice Returns true if the address is RiskAdmin, false otherwise
* @param admin The address to check
* @return True if the given address is RiskAdmin, false otherwise
*/
function isRiskAdmin(address admin) external view returns (bool);
/**
* @notice Adds a new address as FlashBorrower
* @param borrower The address of the new FlashBorrower
*/
function addFlashBorrower(address borrower) external;
/**
* @notice Removes an address as FlashBorrower
* @param borrower The address of the FlashBorrower to remove
*/
function removeFlashBorrower(address borrower) external;
/**
* @notice Returns true if the address is FlashBorrower, false otherwise
* @param borrower The address to check
* @return True if the given address is FlashBorrower, false otherwise
*/
function isFlashBorrower(address borrower) external view returns (bool);
/**
* @notice Adds a new address as Bridge
* @param bridge The address of the new Bridge
*/
function addBridge(address bridge) external;
/**
* @notice Removes an address as Bridge
* @param bridge The address of the bridge to remove
*/
function removeBridge(address bridge) external;
/**
* @notice Returns true if the address is Bridge, false otherwise
* @param bridge The address to check
* @return True if the given address is Bridge, false otherwise
*/
function isBridge(address bridge) external view returns (bool);
/**
* @notice Adds a new admin as AssetListingAdmin
* @param admin The address of the new admin
*/
function addAssetListingAdmin(address admin) external;
/**
* @notice Removes an admin as AssetListingAdmin
* @param admin The address of the admin to remove
*/
function removeAssetListingAdmin(address admin) external;
/**
* @notice Returns true if the address is AssetListingAdmin, false otherwise
* @param admin The address to check
* @return True if the given address is AssetListingAdmin, false otherwise
*/
function isAssetListingAdmin(address admin) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
enum DelegationMode {
NO_DELEGATION,
VOTING_DELEGATED,
PROPOSITION_DELEGATED,
FULL_POWER_DELEGATED
}{
"remappings": [
"aave-address-book/=lib/aave-helpers/lib/aave-address-book/src/",
"aave-helpers/=lib/aave-helpers/",
"aave-v3-origin-tests/=lib/aave-v3-origin/tests/",
"aave-v3-origin/=lib/aave-v3-origin/src/",
"erc4626-tests/=lib/aave-helpers/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts-upgradeable/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/",
"solidity-utils/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/src/",
"lib/aave-helpers/:aave-address-book/=lib/aave-helpers/lib/aave-address-book/src/",
"lib/aave-helpers/:solidity-utils/=lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/lib/solidity-utils/src/",
"@openzeppelin/contracts-upgradeable/=lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/contracts/",
"@openzeppelin/contracts/=lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
"ds-test/=lib/aave-v3-origin/lib/forge-std/lib/ds-test/src/",
"halmos-cheatcodes/=lib/aave-v3-origin/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false,
"libraries": {
"lib/aave-v3-origin/src/contracts/protocol/libraries/logic/BorrowLogic.sol": {
"BorrowLogic": "0xFeD9871528E713B5038c4c44BbE7a315f56cAdc6"
},
"lib/aave-v3-origin/src/contracts/protocol/libraries/logic/ConfiguratorLogic.sol": {
"ConfiguratorLogic": "0x6E2aFD57a161d12f34f416c29619BFeAcAC8AA18"
},
"lib/aave-v3-origin/src/contracts/protocol/libraries/logic/EModeLogic.sol": {
"EModeLogic": "0xD1bddC05A3BB5A7907d82A1b4F1E21dBCE69c3d5"
},
"lib/aave-v3-origin/src/contracts/protocol/libraries/logic/FlashLoanLogic.sol": {
"FlashLoanLogic": "0x5e84CEe2afb7B37d2AB14722C39A7c1C26F5B0BB"
},
"lib/aave-v3-origin/src/contracts/protocol/libraries/logic/LiquidationLogic.sol": {
"LiquidationLogic": "0x36Ae486289bB807C3C79A1427b9c3D934294ef43"
},
"lib/aave-v3-origin/src/contracts/protocol/libraries/logic/PoolLogic.sol": {
"PoolLogic": "0xE51B69e5722Bf547866A4d7Bc190c6e81b626806"
},
"lib/aave-v3-origin/src/contracts/protocol/libraries/logic/SupplyLogic.sol": {
"SupplyLogic": "0x034Fd14b9Ae6bB066a1F9f85A55e990b0b25c168"
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IPool","name":"pool","type":"address"},{"internalType":"address","name":"rewardsController","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CallerMustBePool","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"InsufficientBorrowAllowance","type":"error"},{"inputs":[],"name":"InvalidBurnAmount","type":"error"},{"inputs":[],"name":"InvalidExpiration","type":"error"},{"inputs":[],"name":"InvalidMintAmount","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"OperationNotSupported","type":"error"},{"inputs":[],"name":"PoolAddressesDoNotMatch","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"inputs":[],"name":"ZeroAddressNotValid","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"fromUser","type":"address"},{"indexed":true,"internalType":"address","name":"toUser","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BorrowAllowanceDelegated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balanceIncrease","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"underlyingAsset","type":"address"},{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"address","name":"incentivesController","type":"address"},{"indexed":false,"internalType":"uint8","name":"debtTokenDecimals","type":"uint8"},{"indexed":false,"internalType":"string","name":"debtTokenName","type":"string"},{"indexed":false,"internalType":"string","name":"debtTokenSymbol","type":"string"},{"indexed":false,"internalType":"bytes","name":"params","type":"bytes"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"onBehalfOf","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balanceIncrease","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DEBT_TOKEN_REVISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DELEGATION_WITH_SIG_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EIP712_REVISION","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL","outputs":[{"internalType":"contract IPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARDS_CONTROLLER","outputs":[{"internalType":"contract IAaveIncentivesController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNDERLYING_ASSET_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approveDelegation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"fromUser","type":"address"},{"internalType":"address","name":"toUser","type":"address"}],"name":"borrowAllowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"scaledAmount","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegationWithSig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getIncentivesController","outputs":[{"internalType":"contract IAaveIncentivesController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getPreviousIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getScaledUserBalanceAndSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IPool","name":"initializingPool","type":"address"},{"internalType":"address","name":"underlyingAsset","type":"address"},{"internalType":"uint8","name":"debtTokenDecimals","type":"uint8"},{"internalType":"string","name":"debtTokenName","type":"string"},{"internalType":"string","name":"debtTokenSymbol","type":"string"},{"internalType":"bytes","name":"params","type":"bytes"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"onBehalfOf","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"scaledAmount","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"scaledBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"scaledTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6101006040525f5f55348015610013575f5ffd5b50604051611fca380380611fca833981016040819052610032916101aa565b8181816040518060400160405280601881526020017f5641524941424c455f444542545f544f4b454e5f494d504c00000000000000008152506040518060400160405280601881526020017f5641524941424c455f444542545f544f4b454e5f494d504c00000000000000008152505f84848484848484848484846100bb61018e60201b60201c565b5f554660805260408051630150a5d760e21b815290516001600160a01b03871691630542975c9160048083019260209291908290030181865afa158015610104573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061012891906101e2565b6001600160a01b031660a052603b610140858261029c565b50603c61014d848261029c565b50603d805460ff90931660ff19909316929092179091556001600160a01b0393841660c05290921660e052506103569e505050505050505050505050505050565b600490565b6001600160a01b03811681146101a7575f5ffd5b50565b5f5f604083850312156101bb575f5ffd5b82516101c681610193565b60208401519092506101d781610193565b809150509250929050565b5f602082840312156101f2575f5ffd5b81516101fd81610193565b9392505050565b634e487b7160e01b5f52604160045260245ffd5b600181811c9082168061022c57607f821691505b60208210810361024a57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561029757805f5260205f20601f840160051c810160208510156102755750805b601f840160051c820191505b81811015610294575f8155600101610281565b50505b505050565b81516001600160401b038111156102b5576102b5610204565b6102c9816102c38454610218565b84610250565b6020601f8211600181146102fb575f83156102e45750848201515b5f19600385901b1c1916600184901b178455610294565b5f84815260208120601f198516915b8281101561032a578785015182556020948501946001909201910161030a565b508482101561034757868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b60805160a05160c05160e051611bfe6103cc5f395f81816103330152818161040601528181610a23015281816114f8015261155201525f81816102f70152818161072f0152818161081801528181610932015281816109ce01528181610a8f0152610b6801525f50505f6107bc0152611bfe5ff3fe608060405234801561000f575f5ffd5b50600436106101d1575f3560e01c80637ecebe00116100fe578063b1bf962d1161009e578063dd62ed3e1161006e578063dd62ed3e14610428578063e075398614610436578063f3bfc7381461046e578063f5298aca14610495575f5ffd5b8063b1bf962d146103de578063b9a7b622146103e6578063c04a8a10146103ee578063cd086d4514610401575f5ffd5b80639ceeaca7116100d95780639ceeaca7146103ba578063a457c2d7146101f3578063a9059cbb146101f3578063b16a19de146103cd575f5ffd5b80637ecebe00146103775780637fdd585f1461039f57806395d89b41146103b2575f5ffd5b8063313ce5671161017457806370a082311161014457806370a08231146102df5780637535d246146102f257806375d26413146103315780637816037614610357575f5ffd5b8063313ce5671461028a5780633644e5151461029f57806339509351146101f35780636bd76d24146102a7575f5ffd5b80630b52d558116101af5780630b52d5581461023e57806318160ddd146102535780631da24f3e1461026957806323b872dd1461027c575f5ffd5b806306fdde03146101d5578063095ea7b3146101f35780630afbcdc914610216575b5f5ffd5b6101dd6104bf565b6040516101ea9190611622565b60405180910390f35b61020661020136600461164b565b61054f565b60405190151581526020016101ea565b610229610224366004611675565b610569565b604080519283526020830191909152016101ea565b61025161024c3660046116a5565b610580565b005b61025b610707565b6040519081526020016101ea565b61025b610277366004611675565b6107a9565b61020661020136600461170f565b603d5460405160ff90911681526020016101ea565b61025b6107b9565b61025b6102b536600461174d565b6001600160a01b039182165f90815260366020908152604080832093909416825291909152205490565b61025b6102ed366004611675565b6107f0565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101ea565b7f0000000000000000000000000000000000000000000000000000000000000000610319565b6101dd604051806040016040528060018152602001603160f81b81525081565b61025b610385366004611675565b6001600160a01b03165f9081526034602052604090205490565b6102516103ad366004611823565b61088c565b6101dd610a7c565b61025b6103c836600461191b565b610a8b565b6037546001600160a01b0316610319565b61025b610b4a565b61025b600481565b6102516103fc36600461164b565b610b54565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b61025b61020136600461174d565b61025b610444366004611675565b6001600160a01b03165f90815260386020526040902054600160801b90046001600160801b031690565b61025b7f323db0410fecc107e39e2af5908671f4c8d106123b35a51501bb805c5fa36aa081565b6104a86104a3366004611968565b610b63565b6040805192151583526020830191909152016101ea565b6060603b80546104ce9061199a565b80601f01602080910402602001604051908101604052809291908181526020018280546104fa9061199a565b80156105455780601f1061051c57610100808354040283529160200191610545565b820191905f5260205f20905b81548152906001019060200180831161052857829003601f168201915b5050505050905090565b5f6040516329a270f560e01b815260040160405180910390fd5b5f5f61057483610bd1565b603a5491509150915091565b6001600160a01b0387166105a757604051633bf95ba760e01b815260040160405180910390fd5b834211156105c857604051637d9533a960e11b815260040160405180910390fd5b6001600160a01b0387165f90815260346020526040812054906105e96107b9565b604080517f323db0410fecc107e39e2af5908671f4c8d106123b35a51501bb805c5fa36aa060208201526001600160a01b038b1691810191909152606081018990526080810184905260a0810188905260c0016040516020818303038152906040528051906020012060405160200161067992919061190160f01b81526002810192909252602282015260420190565b60405160208183030381529060405280519060200120905061069d81868686610bf4565b6001600160a01b0316896001600160a01b0316146106ce57604051638baa579f60e01b815260040160405180910390fd5b6106d98260016119e6565b6001600160a01b038a165f908152603460205260409020556106fc898989610c20565b505050505050505050565b60375460405163386497fd60e01b81526001600160a01b0391821660048201525f916107a4917f00000000000000000000000000000000000000000000000000000000000000009091169063386497fd90602401602060405180830381865afa158015610776573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061079a91906119f9565b603a545b90610c89565b905090565b5f6107b382610bd1565b92915050565b5f7f000000000000000000000000000000000000000000000000000000000000000046036107e8575060355490565b6107a4610c9b565b60375460405163386497fd60e01b81526001600160a01b0391821660048201525f916107b3917f00000000000000000000000000000000000000000000000000000000000000009091169063386497fd90602401602060405180830381865afa15801561085f573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061088391906119f9565b61079e84610bd1565b60015460049060ff168061089f5750303b155b806108aa57505f5481115b6109125760405162461bcd60e51b815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201526d195b881a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b60015460ff16158015610930576001805460ff1916811790555f8290555b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316896001600160a01b03161461098257604051634c2b89eb60e01b815260040160405180910390fd5b61098b86610d43565b61099485610d4f565b603d805460ff191660ff8916179055603780546001600160a01b0319166001600160a01b038a161790556109c6610c9b565b6035819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316886001600160a01b03167f40251fbfb6656cfa65a00d7879029fec1fad21d28fdcff2f4f68f52795b74f2c7f00000000000000000000000000000000000000000000000000000000000000008a8a8a8a8a604051610a5996959493929190611a10565b60405180910390a380156106fc576001805460ff19169055505050505050505050565b6060603c80546104ce9061199a565b5f337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610ad557604051632a59ce7160e11b815260040160405180910390fd5b5f610adf87610bd1565b9050856001600160a01b0316876001600160a01b031614610b2757610b27868887610b0a8588610c89565b610b188861079e8b896119e6565b610b229190611a85565b610d5b565b610b3687878686610c89610e4d565b50610b3f610b4a565b979650505050505050565b5f6107a4603a5490565b610b5f338383610c20565b5050565b5f80337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610bae57604051632a59ce7160e11b815260040160405180910390fd5b610bbd855f8686610c89610ff3565b610bc5610b4a565b91509150935093915050565b6001600160a01b03165f908152603860205260409020546001600160781b031690565b5f5f5f5f610c0488888888611250565b925092509250610c148282611318565b50909695505050505050565b6001600160a01b038381165f8181526036602090815260408083208786168085529083529281902086905560375490518681529416939192917fda919360433220e13b51e8c211e490d148e61a3bd53de8c097194e458b97f3e1910160405180910390a4505050565b5f610c9483836113d0565b9392505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f610cc56113ff565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b603b610b5f8282611ae4565b603c610b5f8282611ae4565b6001600160a01b038085165f9081526036602090815260408083209387168352929052205482811015610dba57604051631cb19ef360e01b81526001600160a01b03851660048201526024810182905260448101849052606401610909565b5f82821015610dc95781610dcb565b825b90505f610dd88284611a85565b6001600160a01b038089165f8181526036602090815260408083208c861680855292529182902085905560375491519495509216927fda919360433220e13b51e8c211e490d148e61a3bd53de8c097194e458b97f3e190610e3c9086815260200190565b60405180910390a450505050505050565b5f835f03610e6e5760405163199f5a0360e31b815260040160405180910390fd5b5f610e7886610bd1565b90505f610e92610e8883886119e6565b868663ffffffff16565b6001600160a01b0388165f9081526038602052604081205491925090610ecd908490600160801b90046001600160801b031663ffffffff8816565b90505f81610edf85898963ffffffff16565b610ee99190611a85565b9050610ef487611409565b6001600160a01b038a165f90815260386020526040902080546001600160801b03928316600160801b029216919091179055610f3889610f338a611440565b611473565b5f610f438385611a85565b9050896001600160a01b03165f6001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610f8a91815260200190565b60405180910390a360408051828152602081018490529081018990526001600160a01b03808c1691908d16907f458f5fa412d0f69b08dd84872b0215675cc67bc1d5b6fd93300a1c3878b861969060600160405180910390a35050911598975050505050505050565b5f835f03611014576040516302075cc160e41b815260040160405180910390fd5b5f61101e87610bd1565b90505f61102e610e888784611a85565b6001600160a01b0389165f9081526038602052604081205491925090611069908490600160801b90046001600160801b031663ffffffff8816565b90505f8161107b85898963ffffffff16565b6110859190611a85565b905061109087611409565b6001600160a01b038b165f90815260386020526040902080546001600160801b03928316600160801b0292169190911790556110d48a6110cf8a611440565b6115b0565b8183111561118a575f6110e78385611a85565b90508a6001600160a01b03165f6001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161112e91815260200190565b60405180910390a360408051828152602081018490529081018990526001600160a01b038c169081907f458f5fa412d0f69b08dd84872b0215675cc67bc1d5b6fd93300a1c3878b861969060600160405180910390a350611237565b5f6111958484611a85565b90505f6001600160a01b03168b6001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516111dc91815260200190565b60405180910390a360408051828152602081018490529081018990526001600160a01b03808c1691908d16907f4cf25bc1d991c17529c25213d3cc0cda295eeaad5f13f361969b12ea48015f909060600160405180910390a3505b6112418885611a85565b159a9950505050505050505050565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561128957505f9150600390508261130e565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156112da573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b03811661130557505f92506001915082905061130e565b92505f91508190505b9450945094915050565b5f82600381111561132b5761132b611b9f565b03611334575050565b600182600381111561134857611348611b9f565b036113665760405163f645eedf60e01b815260040160405180910390fd5b600282600381111561137a5761137a611b9f565b0361139b5760405163fce698f760e01b815260048101829052602401610909565b60038260038111156113af576113af611b9f565b03610b5f576040516335e2f38360e21b815260048101829052602401610909565b5f815f19048311158215176113e3575f5ffd5b506b033b2e3c9fd0803ce8000000910281810491900615150190565b60606107a46104bf565b5f6001600160801b0382111561143c576040516306dfcc6560e41b81526080600482015260248101839052604401610909565b5090565b5f6001600160781b0382111561143c576040516306dfcc6560e41b81526078600482015260248101839052604401610909565b603a546114896001600160781b038316826119e6565b603a556001600160a01b0383165f908152603860205260409020546001600160781b03166114b78382611bb3565b6001600160a01b038581165f90815260386020526040902080546effffffffffffffffffffffffffffff19166001600160781b0393909316929092179091557f000000000000000000000000000000000000000000000000000000000000000016156115aa576040516318c39f1760e11b81526001600160a01b038581166004830152602482018490526001600160781b03831660448301527f000000000000000000000000000000000000000000000000000000000000000016906331873e2e906064015f604051808303815f87803b158015611593575f5ffd5b505af11580156115a5573d5f5f3e3d5ffd5b505050505b50505050565b603a546115c66001600160781b03831682611a85565b603a556001600160a01b0383165f908152603860205260409020546001600160781b03166114b78382611bd2565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610c9460208301846115f4565b6001600160a01b0381168114611648575f5ffd5b50565b5f5f6040838503121561165c575f5ffd5b823561166781611634565b946020939093013593505050565b5f60208284031215611685575f5ffd5b8135610c9481611634565b803560ff811681146116a0575f5ffd5b919050565b5f5f5f5f5f5f5f60e0888a0312156116bb575f5ffd5b87356116c681611634565b965060208801356116d681611634565b955060408801359450606088013593506116f260808901611690565b9699959850939692959460a0840135945060c09093013592915050565b5f5f5f60608486031215611721575f5ffd5b833561172c81611634565b9250602084013561173c81611634565b929592945050506040919091013590565b5f5f6040838503121561175e575f5ffd5b823561176981611634565b9150602083013561177981611634565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f8301126117a7575f5ffd5b813567ffffffffffffffff8111156117c1576117c1611784565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156117f0576117f0611784565b604052818152838201602001851015611807575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f5f5f5f5f5f60c0888a031215611839575f5ffd5b873561184481611634565b9650602088013561185481611634565b955061186260408901611690565b9450606088013567ffffffffffffffff81111561187d575f5ffd5b6118898a828b01611798565b945050608088013567ffffffffffffffff8111156118a5575f5ffd5b6118b18a828b01611798565b93505060a088013567ffffffffffffffff8111156118cd575f5ffd5b8801601f81018a136118dd575f5ffd5b803567ffffffffffffffff8111156118f3575f5ffd5b8a6020828401011115611904575f5ffd5b602082019350809250505092959891949750929550565b5f5f5f5f5f60a0868803121561192f575f5ffd5b853561193a81611634565b9450602086013561194a81611634565b94979496505050506040830135926060810135926080909101359150565b5f5f5f6060848603121561197a575f5ffd5b833561198581611634565b95602085013595506040909401359392505050565b600181811c908216806119ae57607f821691505b6020821081036119cc57634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156107b3576107b36119d2565b5f60208284031215611a09575f5ffd5b5051919050565b6001600160a01b038716815260ff8616602082015260a0604082018190525f90611a3c908301876115f4565b8281036060840152611a4e81876115f4565b90508281036080840152838152838560208301375f602085830101526020601f19601f860116820101915050979650505050505050565b818103818111156107b3576107b36119d2565b601f821115611adf57805f5260205f20601f840160051c81016020851015611abd5750805b601f840160051c820191505b81811015611adc575f8155600101611ac9565b50505b505050565b815167ffffffffffffffff811115611afe57611afe611784565b611b1281611b0c845461199a565b84611a98565b6020601f821160018114611b44575f8315611b2d5750848201515b5f19600385901b1c1916600184901b178455611adc565b5f84815260208120601f198516915b82811015611b735787850151825560209485019460019092019101611b53565b5084821015611b9057868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b634e487b7160e01b5f52602160045260245ffd5b6001600160781b0381811683821601908111156107b3576107b36119d2565b6001600160781b0382811682821603908111156107b3576107b36119d256fea164736f6c634300081b000a00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e20000000000000000000000008164cc65827dcfe994ab23944cbc90e0aa80bfcb
Deployed Bytecode
0x608060405234801561000f575f5ffd5b50600436106101d1575f3560e01c80637ecebe00116100fe578063b1bf962d1161009e578063dd62ed3e1161006e578063dd62ed3e14610428578063e075398614610436578063f3bfc7381461046e578063f5298aca14610495575f5ffd5b8063b1bf962d146103de578063b9a7b622146103e6578063c04a8a10146103ee578063cd086d4514610401575f5ffd5b80639ceeaca7116100d95780639ceeaca7146103ba578063a457c2d7146101f3578063a9059cbb146101f3578063b16a19de146103cd575f5ffd5b80637ecebe00146103775780637fdd585f1461039f57806395d89b41146103b2575f5ffd5b8063313ce5671161017457806370a082311161014457806370a08231146102df5780637535d246146102f257806375d26413146103315780637816037614610357575f5ffd5b8063313ce5671461028a5780633644e5151461029f57806339509351146101f35780636bd76d24146102a7575f5ffd5b80630b52d558116101af5780630b52d5581461023e57806318160ddd146102535780631da24f3e1461026957806323b872dd1461027c575f5ffd5b806306fdde03146101d5578063095ea7b3146101f35780630afbcdc914610216575b5f5ffd5b6101dd6104bf565b6040516101ea9190611622565b60405180910390f35b61020661020136600461164b565b61054f565b60405190151581526020016101ea565b610229610224366004611675565b610569565b604080519283526020830191909152016101ea565b61025161024c3660046116a5565b610580565b005b61025b610707565b6040519081526020016101ea565b61025b610277366004611675565b6107a9565b61020661020136600461170f565b603d5460405160ff90911681526020016101ea565b61025b6107b9565b61025b6102b536600461174d565b6001600160a01b039182165f90815260366020908152604080832093909416825291909152205490565b61025b6102ed366004611675565b6107f0565b6103197f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e281565b6040516001600160a01b0390911681526020016101ea565b7f0000000000000000000000008164cc65827dcfe994ab23944cbc90e0aa80bfcb610319565b6101dd604051806040016040528060018152602001603160f81b81525081565b61025b610385366004611675565b6001600160a01b03165f9081526034602052604090205490565b6102516103ad366004611823565b61088c565b6101dd610a7c565b61025b6103c836600461191b565b610a8b565b6037546001600160a01b0316610319565b61025b610b4a565b61025b600481565b6102516103fc36600461164b565b610b54565b6103197f0000000000000000000000008164cc65827dcfe994ab23944cbc90e0aa80bfcb81565b61025b61020136600461174d565b61025b610444366004611675565b6001600160a01b03165f90815260386020526040902054600160801b90046001600160801b031690565b61025b7f323db0410fecc107e39e2af5908671f4c8d106123b35a51501bb805c5fa36aa081565b6104a86104a3366004611968565b610b63565b6040805192151583526020830191909152016101ea565b6060603b80546104ce9061199a565b80601f01602080910402602001604051908101604052809291908181526020018280546104fa9061199a565b80156105455780601f1061051c57610100808354040283529160200191610545565b820191905f5260205f20905b81548152906001019060200180831161052857829003601f168201915b5050505050905090565b5f6040516329a270f560e01b815260040160405180910390fd5b5f5f61057483610bd1565b603a5491509150915091565b6001600160a01b0387166105a757604051633bf95ba760e01b815260040160405180910390fd5b834211156105c857604051637d9533a960e11b815260040160405180910390fd5b6001600160a01b0387165f90815260346020526040812054906105e96107b9565b604080517f323db0410fecc107e39e2af5908671f4c8d106123b35a51501bb805c5fa36aa060208201526001600160a01b038b1691810191909152606081018990526080810184905260a0810188905260c0016040516020818303038152906040528051906020012060405160200161067992919061190160f01b81526002810192909252602282015260420190565b60405160208183030381529060405280519060200120905061069d81868686610bf4565b6001600160a01b0316896001600160a01b0316146106ce57604051638baa579f60e01b815260040160405180910390fd5b6106d98260016119e6565b6001600160a01b038a165f908152603460205260409020556106fc898989610c20565b505050505050505050565b60375460405163386497fd60e01b81526001600160a01b0391821660048201525f916107a4917f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e29091169063386497fd90602401602060405180830381865afa158015610776573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061079a91906119f9565b603a545b90610c89565b905090565b5f6107b382610bd1565b92915050565b5f7f000000000000000000000000000000000000000000000000000000000000000146036107e8575060355490565b6107a4610c9b565b60375460405163386497fd60e01b81526001600160a01b0391821660048201525f916107b3917f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e29091169063386497fd90602401602060405180830381865afa15801561085f573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061088391906119f9565b61079e84610bd1565b60015460049060ff168061089f5750303b155b806108aa57505f5481115b6109125760405162461bcd60e51b815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201526d195b881a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b60015460ff16158015610930576001805460ff1916811790555f8290555b7f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e26001600160a01b0316896001600160a01b03161461098257604051634c2b89eb60e01b815260040160405180910390fd5b61098b86610d43565b61099485610d4f565b603d805460ff191660ff8916179055603780546001600160a01b0319166001600160a01b038a161790556109c6610c9b565b6035819055507f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e26001600160a01b0316886001600160a01b03167f40251fbfb6656cfa65a00d7879029fec1fad21d28fdcff2f4f68f52795b74f2c7f0000000000000000000000008164cc65827dcfe994ab23944cbc90e0aa80bfcb8a8a8a8a8a604051610a5996959493929190611a10565b60405180910390a380156106fc576001805460ff19169055505050505050505050565b6060603c80546104ce9061199a565b5f337f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e26001600160a01b031614610ad557604051632a59ce7160e11b815260040160405180910390fd5b5f610adf87610bd1565b9050856001600160a01b0316876001600160a01b031614610b2757610b27868887610b0a8588610c89565b610b188861079e8b896119e6565b610b229190611a85565b610d5b565b610b3687878686610c89610e4d565b50610b3f610b4a565b979650505050505050565b5f6107a4603a5490565b610b5f338383610c20565b5050565b5f80337f00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e26001600160a01b031614610bae57604051632a59ce7160e11b815260040160405180910390fd5b610bbd855f8686610c89610ff3565b610bc5610b4a565b91509150935093915050565b6001600160a01b03165f908152603860205260409020546001600160781b031690565b5f5f5f5f610c0488888888611250565b925092509250610c148282611318565b50909695505050505050565b6001600160a01b038381165f8181526036602090815260408083208786168085529083529281902086905560375490518681529416939192917fda919360433220e13b51e8c211e490d148e61a3bd53de8c097194e458b97f3e1910160405180910390a4505050565b5f610c9483836113d0565b9392505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f610cc56113ff565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b603b610b5f8282611ae4565b603c610b5f8282611ae4565b6001600160a01b038085165f9081526036602090815260408083209387168352929052205482811015610dba57604051631cb19ef360e01b81526001600160a01b03851660048201526024810182905260448101849052606401610909565b5f82821015610dc95781610dcb565b825b90505f610dd88284611a85565b6001600160a01b038089165f8181526036602090815260408083208c861680855292529182902085905560375491519495509216927fda919360433220e13b51e8c211e490d148e61a3bd53de8c097194e458b97f3e190610e3c9086815260200190565b60405180910390a450505050505050565b5f835f03610e6e5760405163199f5a0360e31b815260040160405180910390fd5b5f610e7886610bd1565b90505f610e92610e8883886119e6565b868663ffffffff16565b6001600160a01b0388165f9081526038602052604081205491925090610ecd908490600160801b90046001600160801b031663ffffffff8816565b90505f81610edf85898963ffffffff16565b610ee99190611a85565b9050610ef487611409565b6001600160a01b038a165f90815260386020526040902080546001600160801b03928316600160801b029216919091179055610f3889610f338a611440565b611473565b5f610f438385611a85565b9050896001600160a01b03165f6001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610f8a91815260200190565b60405180910390a360408051828152602081018490529081018990526001600160a01b03808c1691908d16907f458f5fa412d0f69b08dd84872b0215675cc67bc1d5b6fd93300a1c3878b861969060600160405180910390a35050911598975050505050505050565b5f835f03611014576040516302075cc160e41b815260040160405180910390fd5b5f61101e87610bd1565b90505f61102e610e888784611a85565b6001600160a01b0389165f9081526038602052604081205491925090611069908490600160801b90046001600160801b031663ffffffff8816565b90505f8161107b85898963ffffffff16565b6110859190611a85565b905061109087611409565b6001600160a01b038b165f90815260386020526040902080546001600160801b03928316600160801b0292169190911790556110d48a6110cf8a611440565b6115b0565b8183111561118a575f6110e78385611a85565b90508a6001600160a01b03165f6001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161112e91815260200190565b60405180910390a360408051828152602081018490529081018990526001600160a01b038c169081907f458f5fa412d0f69b08dd84872b0215675cc67bc1d5b6fd93300a1c3878b861969060600160405180910390a350611237565b5f6111958484611a85565b90505f6001600160a01b03168b6001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516111dc91815260200190565b60405180910390a360408051828152602081018490529081018990526001600160a01b03808c1691908d16907f4cf25bc1d991c17529c25213d3cc0cda295eeaad5f13f361969b12ea48015f909060600160405180910390a3505b6112418885611a85565b159a9950505050505050505050565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561128957505f9150600390508261130e565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa1580156112da573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b03811661130557505f92506001915082905061130e565b92505f91508190505b9450945094915050565b5f82600381111561132b5761132b611b9f565b03611334575050565b600182600381111561134857611348611b9f565b036113665760405163f645eedf60e01b815260040160405180910390fd5b600282600381111561137a5761137a611b9f565b0361139b5760405163fce698f760e01b815260048101829052602401610909565b60038260038111156113af576113af611b9f565b03610b5f576040516335e2f38360e21b815260048101829052602401610909565b5f815f19048311158215176113e3575f5ffd5b506b033b2e3c9fd0803ce8000000910281810491900615150190565b60606107a46104bf565b5f6001600160801b0382111561143c576040516306dfcc6560e41b81526080600482015260248101839052604401610909565b5090565b5f6001600160781b0382111561143c576040516306dfcc6560e41b81526078600482015260248101839052604401610909565b603a546114896001600160781b038316826119e6565b603a556001600160a01b0383165f908152603860205260409020546001600160781b03166114b78382611bb3565b6001600160a01b038581165f90815260386020526040902080546effffffffffffffffffffffffffffff19166001600160781b0393909316929092179091557f0000000000000000000000008164cc65827dcfe994ab23944cbc90e0aa80bfcb16156115aa576040516318c39f1760e11b81526001600160a01b038581166004830152602482018490526001600160781b03831660448301527f0000000000000000000000008164cc65827dcfe994ab23944cbc90e0aa80bfcb16906331873e2e906064015f604051808303815f87803b158015611593575f5ffd5b505af11580156115a5573d5f5f3e3d5ffd5b505050505b50505050565b603a546115c66001600160781b03831682611a85565b603a556001600160a01b0383165f908152603860205260409020546001600160781b03166114b78382611bd2565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610c9460208301846115f4565b6001600160a01b0381168114611648575f5ffd5b50565b5f5f6040838503121561165c575f5ffd5b823561166781611634565b946020939093013593505050565b5f60208284031215611685575f5ffd5b8135610c9481611634565b803560ff811681146116a0575f5ffd5b919050565b5f5f5f5f5f5f5f60e0888a0312156116bb575f5ffd5b87356116c681611634565b965060208801356116d681611634565b955060408801359450606088013593506116f260808901611690565b9699959850939692959460a0840135945060c09093013592915050565b5f5f5f60608486031215611721575f5ffd5b833561172c81611634565b9250602084013561173c81611634565b929592945050506040919091013590565b5f5f6040838503121561175e575f5ffd5b823561176981611634565b9150602083013561177981611634565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f8301126117a7575f5ffd5b813567ffffffffffffffff8111156117c1576117c1611784565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156117f0576117f0611784565b604052818152838201602001851015611807575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f5f5f5f5f5f60c0888a031215611839575f5ffd5b873561184481611634565b9650602088013561185481611634565b955061186260408901611690565b9450606088013567ffffffffffffffff81111561187d575f5ffd5b6118898a828b01611798565b945050608088013567ffffffffffffffff8111156118a5575f5ffd5b6118b18a828b01611798565b93505060a088013567ffffffffffffffff8111156118cd575f5ffd5b8801601f81018a136118dd575f5ffd5b803567ffffffffffffffff8111156118f3575f5ffd5b8a6020828401011115611904575f5ffd5b602082019350809250505092959891949750929550565b5f5f5f5f5f60a0868803121561192f575f5ffd5b853561193a81611634565b9450602086013561194a81611634565b94979496505050506040830135926060810135926080909101359150565b5f5f5f6060848603121561197a575f5ffd5b833561198581611634565b95602085013595506040909401359392505050565b600181811c908216806119ae57607f821691505b6020821081036119cc57634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156107b3576107b36119d2565b5f60208284031215611a09575f5ffd5b5051919050565b6001600160a01b038716815260ff8616602082015260a0604082018190525f90611a3c908301876115f4565b8281036060840152611a4e81876115f4565b90508281036080840152838152838560208301375f602085830101526020601f19601f860116820101915050979650505050505050565b818103818111156107b3576107b36119d2565b601f821115611adf57805f5260205f20601f840160051c81016020851015611abd5750805b601f840160051c820191505b81811015611adc575f8155600101611ac9565b50505b505050565b815167ffffffffffffffff811115611afe57611afe611784565b611b1281611b0c845461199a565b84611a98565b6020601f821160018114611b44575f8315611b2d5750848201515b5f19600385901b1c1916600184901b178455611adc565b5f84815260208120601f198516915b82811015611b735787850151825560209485019460019092019101611b53565b5084821015611b9057868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b634e487b7160e01b5f52602160045260245ffd5b6001600160781b0381811683821601908111156107b3576107b36119d2565b6001600160781b0382811682821603908111156107b3576107b36119d256fea164736f6c634300081b000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e20000000000000000000000008164cc65827dcfe994ab23944cbc90e0aa80bfcb
-----Decoded View---------------
Arg [0] : pool (address): 0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2
Arg [1] : rewardsController (address): 0x8164Cc65827dcFe994AB23944CBC90e0aa80bFcb
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000087870bca3f3fd6335c3f4ce8392d69350b4fa4e2
Arg [1] : 0000000000000000000000008164cc65827dcfe994ab23944cbc90e0aa80bfcb
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.