Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 402178117 | 65 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ATokenInstance
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 {IPool} from '../interfaces/IPool.sol';
import {IInitializableAToken} from '../interfaces/IInitializableAToken.sol';
import {Errors} from '../protocol/libraries/helpers/Errors.sol';
import {VersionedInitializable} from '../misc/aave-upgradeability/VersionedInitializable.sol';
import {AToken} from '../protocol/tokenization/AToken.sol';
/**
* @title Aave ERC20 AToken Instance
* @author BGD Labs
* @notice Instance of the interest bearing token for the Aave protocol
*/
contract ATokenInstance is AToken {
uint256 public constant ATOKEN_REVISION = 5;
constructor(
IPool pool,
address rewardsController,
address treasury
) AToken(pool, rewardsController, treasury) {}
/// @inheritdoc VersionedInitializable
function getRevision() internal pure virtual override returns (uint256) {
return ATOKEN_REVISION;
}
/// @inheritdoc IInitializableAToken
function initialize(
IPool initializingPool,
address underlyingAsset,
uint8 aTokenDecimals,
string calldata aTokenName,
string calldata aTokenSymbol,
bytes calldata params
) public virtual override initializer {
require(initializingPool == POOL, Errors.PoolAddressesDoNotMatch());
_setName(aTokenName);
_setSymbol(aTokenSymbol);
_setDecimals(aTokenDecimals);
_underlyingAsset = underlyingAsset;
_domainSeparator = _calculateDomainSeparator();
emit Initialized(
underlyingAsset,
address(POOL),
address(TREASURY),
address(REWARDS_CONTROLLER),
aTokenDecimals,
aTokenName,
aTokenSymbol,
params
);
}
}// 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
*/
function finalizeTransfer(
address asset,
address from,
address to,
uint256 scaledAmount,
uint256 scaledBalanceFromBefore
) 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 Replaces the current eMode ltvzeroBitmap.
* @param id The id of the category
* @param ltvzeroBitmap The ltvzeroBitmap of the category
*/
function configureEModeCategoryLtvzeroBitmap(uint8 id, uint128 ltvzeroBitmap) 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
* @dev This function is deprecated and will be removed in a future version.
* @custom:deprecated
* @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 Returns the ltvzero of an eMode category
* @param id The id of the category
* @return The ltvzeroBitmap of the category
*/
function getEModeCategoryLtvzeroBitmap(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 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 IInitializableAToken
* @author Aave
* @notice Interface for the initialize function on AToken
*/
interface IInitializableAToken {
/**
* @dev Emitted when an aToken is initialized
* @param underlyingAsset The address of the underlying asset
* @param pool The address of the associated pool
* @param treasury The address of the treasury
* @param incentivesController The address of the incentives controller for this aToken
* @param aTokenDecimals The decimals of the underlying
* @param aTokenName The name of the aToken
* @param aTokenSymbol The symbol of the aToken
* @param params A set of encoded parameters for additional initialization
*/
event Initialized(
address indexed underlyingAsset,
address indexed pool,
address treasury,
address incentivesController,
uint8 aTokenDecimals,
string aTokenName,
string aTokenSymbol,
bytes params
);
/**
* @notice Initializes the aToken
* @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 aTokenDecimals The decimals of the aToken, same as the underlying asset's
* @param aTokenName The name of the aToken
* @param aTokenSymbol The symbol of the aToken
* @param params A set of encoded parameters for additional initialization
*/
function initialize(
IPool pool,
address underlyingAsset,
uint8 aTokenDecimals,
string calldata aTokenName,
string calldata aTokenSymbol,
bytes calldata params
) external;
}// 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 InvalidLtvzeroState(); // Reserve is already in the passed ltvzero 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
error InvalidCollateralInEmode(address reserve, uint256 categoryId); /// Thrown when trying to enter an eMode with an invalid collateral asset
error InvalidDebtInEmode(address reserve, uint256 categoryId); /// Thrown when trying to enter an eMode with an invalid debt asset
error MustBeEmodeCollateral(address reserve, uint256 categoryId); /// Thrown when trying to configure an asset as eMode-ltvzero that is not an eMode collateral
}// 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 {SafeCast} from 'openzeppelin-contracts/contracts/utils/math/SafeCast.sol';
import {ECDSA} from 'openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol';
import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';
import {GPv2SafeERC20} from '../../dependencies/gnosis/contracts/GPv2SafeERC20.sol';
import {VersionedInitializable} from '../../misc/aave-upgradeability/VersionedInitializable.sol';
import {Errors} from '../libraries/helpers/Errors.sol';
import {IPool} from '../../interfaces/IPool.sol';
import {IAToken} from '../../interfaces/IAToken.sol';
import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol';
import {IInitializableAToken} from '../../interfaces/IInitializableAToken.sol';
import {ScaledBalanceTokenBase} from './base/ScaledBalanceTokenBase.sol';
import {IncentivizedERC20} from './base/IncentivizedERC20.sol';
import {EIP712Base} from './base/EIP712Base.sol';
import {TokenMath} from '../libraries/helpers/TokenMath.sol';
/**
* @title Aave ERC20 AToken
* @author Aave
* @notice Implementation of the interest bearing token for the Aave protocol
*/
abstract contract AToken is VersionedInitializable, ScaledBalanceTokenBase, EIP712Base, IAToken {
using TokenMath for uint256;
using SafeCast for uint256;
using GPv2SafeERC20 for IERC20;
bytes32 public constant PERMIT_TYPEHASH =
keccak256('Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)');
address public immutable TREASURY;
address internal _deprecated_treasury;
address internal _underlyingAsset;
/**
* @dev Constructor.
* @param pool The address of the Pool contract
* @param rewardsController The address of the rewards controller contract
* @param treasury The address of the treasury. This is where accrued interest is sent.
*/
constructor(
IPool pool,
address rewardsController,
address treasury
) ScaledBalanceTokenBase(pool, 'ATOKEN_IMPL', 'ATOKEN_IMPL', 0, rewardsController) EIP712Base() {
require(treasury != address(0), Errors.ZeroAddressNotValid());
TREASURY = treasury;
}
/// @inheritdoc IInitializableAToken
function initialize(
IPool initializingPool,
address underlyingAsset,
uint8 aTokenDecimals,
string calldata aTokenName,
string calldata aTokenSymbol,
bytes calldata params
) public virtual;
/// @inheritdoc IAToken
function mint(
address caller,
address onBehalfOf,
uint256 scaledAmount,
uint256 index
) external virtual override onlyPool returns (bool) {
return
_mintScaled({
caller: caller,
onBehalfOf: onBehalfOf,
amountScaled: scaledAmount,
index: index,
getTokenBalance: TokenMath.getATokenBalance
});
}
/// @inheritdoc IAToken
function burn(
address from,
address receiverOfUnderlying,
uint256 amount,
uint256 scaledAmount,
uint256 index
) external virtual override onlyPool returns (bool) {
bool zeroBalanceAfterBurn = _burnScaled({
user: from,
target: receiverOfUnderlying,
amountScaled: scaledAmount,
index: index,
getTokenBalance: TokenMath.getATokenBalance
});
if (receiverOfUnderlying != address(this)) {
IERC20(_underlyingAsset).safeTransfer(receiverOfUnderlying, amount);
}
return zeroBalanceAfterBurn;
}
/// @inheritdoc IAToken
function mintToTreasury(uint256 scaledAmount, uint256 index) external virtual override onlyPool {
if (scaledAmount == 0) {
return;
}
_mintScaled({
caller: address(POOL),
onBehalfOf: TREASURY,
amountScaled: scaledAmount,
index: index,
getTokenBalance: TokenMath.getATokenBalance
});
}
/// @inheritdoc IAToken
function transferOnLiquidation(
address from,
address to,
uint256 amount,
uint256 scaledAmount,
uint256 index
) external virtual override onlyPool {
_transfer({
sender: from,
recipient: to,
amount: amount,
scaledAmount: scaledAmount.toUint120(),
index: index
});
}
/// @inheritdoc IERC20
function balanceOf(
address user
) public view virtual override(IncentivizedERC20, IERC20) returns (uint256) {
return
super.balanceOf(user).getATokenBalance(POOL.getReserveNormalizedIncome(_underlyingAsset));
}
/// @inheritdoc IERC20
function totalSupply() public view virtual override(IncentivizedERC20, IERC20) returns (uint256) {
return super.totalSupply().getATokenBalance(POOL.getReserveNormalizedIncome(_underlyingAsset));
}
/// @inheritdoc IAToken
function RESERVE_TREASURY_ADDRESS() external view override returns (address) {
return TREASURY;
}
/// @inheritdoc IAToken
function UNDERLYING_ASSET_ADDRESS() external view override returns (address) {
return _underlyingAsset;
}
/// @inheritdoc IAToken
function transferUnderlyingTo(address target, uint256 amount) external virtual override onlyPool {
IERC20(_underlyingAsset).safeTransfer(target, amount);
}
/// @inheritdoc IAToken
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external override {
require(owner != address(0), Errors.ZeroAddressNotValid());
//solium-disable-next-line
require(block.timestamp <= deadline, Errors.InvalidExpiration());
uint256 currentValidNonce = _nonces[owner];
bytes32 digest = keccak256(
abi.encodePacked(
'\x19\x01',
DOMAIN_SEPARATOR(),
keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, currentValidNonce, deadline))
)
);
require(owner == ECDSA.recover(digest, v, r, s), Errors.InvalidSignature());
_nonces[owner] = currentValidNonce + 1;
_approve({owner: owner, spender: spender, amount: value, emitEvent: true});
}
/// @inheritdoc IERC20
function transferFrom(
address sender,
address recipient,
uint256 amount
) external virtual override(IERC20, IncentivizedERC20) returns (bool) {
uint256 index = POOL.getReserveNormalizedIncome(_underlyingAsset);
uint256 scaledBalanceOfSender = super.balanceOf(sender);
_spendAllowance(
sender,
_msgSender(),
amount,
// This comment explains the logic behind the allowance spent calculation.
//
// Problem:
// Simply decreasing the allowance by the input `amount` is not ideal for scaled-balance tokens.
// Due to rounding, the actual decrease in the sender's balance (`amount_out`) can be slightly
// larger than the input `amount`.
//
// Definitions:
// - `amount`: The unscaled amount to be transferred, passed as the `amount` argument.
// - `amount_out`: The actual unscaled amount deducted from the sender's balance.
// - `amount_in`: The actual unscaled amount added to the recipient's balance.
// - `allowance_spent`: The unscaled amount deducted from the spender's allowance. Equivalent to `amount_out`.
// - `amount_logged`: The amount logged in the `Transfer` event. Equivalent to `amount`.
//
// Solution:
// To fix this, `allowance_spent` must be exactly equal to `amount_out`.
// We calculate `amount_out` precisely by simulating the effect of the transfer on the sender's balance.
// By passing `amount_out` to `_spendAllowance`, we ensure `allowance_spent` is as close as possible to `amount_out`.
// `amount_logged` is equal to `amount`. `amount_in` is the actual balance increase for the recipient, which is >= `amount` due to rounding.
//
// Backward Compatibility & Guarantees:
// This implementation is backward-compatible and secure. The `_spendAllowance` function has a critical feature:
// 1. It REQUIRES the allowance to be >= `amount` (the user's requested transfer amount).
// 2. The amount consumed from the allowance is `amount_out`, but it is capped at the `currentAllowance`.
// This means if a user has an allowance of 100 wei and calls `transferFrom` with an `amount` of 100, the call will succeed
// even if the calculated `amount_out` 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 amount_in = amount.getATokenTransferScaledAmount(index);
// uint256 amount_out = balanceBefore - balanceAfter = scaledBalanceOfSender.getATokenBalance(index) - (scaledBalanceOfSender - amount_in).getATokenBalance(index);
// Due to limitations of the solidity compiler, the calculation is inlined for gas efficiency.
scaledBalanceOfSender.getATokenBalance(index) -
(scaledBalanceOfSender - amount.getATokenTransferScaledAmount(index)).getATokenBalance(
index
)
);
_transfer(sender, recipient, amount.toUint120());
return true;
}
/**
* @notice Overrides the parent _transfer to force validated transfer() and transferFrom()
* @param from The source address
* @param to The destination address
* @param amount The amount getting transferred
*/
function _transfer(address from, address to, uint120 amount) internal virtual override {
address underlyingAsset = _underlyingAsset;
uint256 index = POOL.getReserveNormalizedIncome(underlyingAsset);
uint256 scaledBalanceFromBefore = super.balanceOf(from);
uint256 scaledAmount = uint256(amount).getATokenTransferScaledAmount(index);
_transfer({
sender: from,
recipient: to,
amount: amount,
scaledAmount: scaledAmount.toUint120(),
index: index
});
POOL.finalizeTransfer({
asset: underlyingAsset,
from: from,
to: to,
scaledAmount: scaledAmount,
scaledBalanceFromBefore: scaledBalanceFromBefore
});
}
/**
* @notice Implements the basic logic to transfer scaled balance tokens between two users
* @dev It emits a mint event with the interest accrued per user
* @param sender The source address
* @param recipient The destination address
* @param amount The amount getting transferred
* @param scaledAmount The scaled amount getting transferred
* @param index The next liquidity index of the reserve
*/
function _transfer(
address sender,
address recipient,
uint256 amount,
uint120 scaledAmount,
uint256 index
) internal virtual {
uint256 senderScaledBalance = super.balanceOf(sender);
uint256 senderBalanceIncrease = senderScaledBalance.getATokenBalance(index) -
senderScaledBalance.getATokenBalance(_userState[sender].additionalData);
uint256 recipientScaledBalance = super.balanceOf(recipient);
uint256 recipientBalanceIncrease = recipientScaledBalance.getATokenBalance(index) -
recipientScaledBalance.getATokenBalance(_userState[recipient].additionalData);
_userState[sender].additionalData = index.toUint128();
_userState[recipient].additionalData = index.toUint128();
super._transfer(sender, recipient, scaledAmount);
if (senderBalanceIncrease > 0) {
emit Transfer(address(0), sender, senderBalanceIncrease);
emit Mint(_msgSender(), sender, senderBalanceIncrease, senderBalanceIncrease, index);
}
if (sender != recipient && recipientBalanceIncrease > 0) {
emit Transfer(address(0), recipient, recipientBalanceIncrease);
emit Mint(_msgSender(), recipient, recipientBalanceIncrease, recipientBalanceIncrease, index);
}
emit Transfer(sender, recipient, amount);
emit BalanceTransfer(sender, recipient, scaledAmount, index);
}
/**
* @dev Overrides the base function to fully implement IAToken
* @dev see `EIP712Base.DOMAIN_SEPARATOR()` for more detailed documentation
*/
function DOMAIN_SEPARATOR() public view override(IAToken, EIP712Base) returns (bytes32) {
return super.DOMAIN_SEPARATOR();
}
/**
* @dev Overrides the base function to fully implement IAToken
* @dev see `EIP712Base.nonces()` for more detailed documentation
*/
function nonces(address owner) public view override(IAToken, EIP712Base) returns (uint256) {
return super.nonces(owner);
}
/// @inheritdoc EIP712Base
function _EIP712BaseId() internal view override returns (string memory) {
return name();
}
/// @inheritdoc IAToken
function rescueTokens(address token, address to, uint256 amount) external override onlyPoolAdmin {
require(token != _underlyingAsset, Errors.UnderlyingCannotBeRescued());
IERC20(token).safeTransfer(to, amount);
}
}// 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;
uint128 ltvzeroBitmap; // if true, the asset will be treated as ltv0 and ltv0 rules apply
}
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;
uint8 supplierEModeCategory;
}
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;
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
// 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
// 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.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: LGPL-3.0-or-later
pragma solidity ^0.8.10;
import {IERC20} from '../../openzeppelin/contracts/IERC20.sol';
/// @title Gnosis Protocol v2 Safe ERC20 Transfer Library
/// @author Gnosis Developers
/// @dev Gas-efficient version of Openzeppelin's SafeERC20 contract.
library GPv2SafeERC20 {
/// @dev Wrapper around a call to the ERC20 function `transfer` that reverts
/// also when the token returns `false`.
function safeTransfer(IERC20 token, address to, uint256 value) internal {
bytes4 selector_ = token.transfer.selector;
// solhint-disable-next-line no-inline-assembly
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, selector_)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 36), value)
if iszero(call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
require(getLastTransferResult(token), 'GPv2: failed transfer');
}
/// @dev Wrapper around a call to the ERC20 function `transferFrom` that
/// reverts also when the token returns `false`.
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
bytes4 selector_ = token.transferFrom.selector;
// solhint-disable-next-line no-inline-assembly
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, selector_)
mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 68), value)
if iszero(call(gas(), token, 0, freeMemoryPointer, 100, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
require(getLastTransferResult(token), 'GPv2: failed transferFrom');
}
/// @dev Verifies that the last return was a successful `transfer*` call.
/// This is done by checking that the return data is either empty, or
/// is a valid ABI encoded boolean.
function getLastTransferResult(IERC20 token) private view returns (bool success) {
// NOTE: Inspecting previous return data requires assembly. Note that
// we write the return data to memory 0 in the case where the return
// data size is 32, this is OK since the first 64 bytes of memory are
// reserved by Solidy as a scratch space that can be used within
// assembly blocks.
// <https://docs.soliditylang.org/en/v0.7.6/internals/layout_in_memory.html>
// solhint-disable-next-line no-inline-assembly
assembly {
/// @dev Revert with an ABI encoded Solidity error with a message
/// that fits into 32-bytes.
///
/// An ABI encoded Solidity error has the following memory layout:
///
/// ------------+----------------------------------
/// byte range | value
/// ------------+----------------------------------
/// 0x00..0x04 | selector("Error(string)")
/// 0x04..0x24 | string offset (always 0x20)
/// 0x24..0x44 | string length
/// 0x44..0x64 | string value, padded to 32-bytes
function revertWithMessage(length, message) {
mstore(0x00, '\x08\xc3\x79\xa0')
mstore(0x04, 0x20)
mstore(0x24, length)
mstore(0x44, message)
revert(0x00, 0x64)
}
switch returndatasize()
// Non-standard ERC20 transfer without return.
case 0 {
// NOTE: When the return data size is 0, verify that there
// is code at the address. This is done in order to maintain
// compatibility with Solidity calling conventions.
// <https://docs.soliditylang.org/en/v0.7.6/control-structures.html#external-function-calls>
if iszero(extcodesize(token)) {
revertWithMessage(20, 'GPv2: not a contract')
}
success := 1
}
// Standard ERC20 transfer returning boolean success value.
case 32 {
returndatacopy(0, 0, returndatasize())
// NOTE: For ABI encoding v1, any non-zero value is accepted
// as `true` for a boolean. In order to stay compatible with
// OpenZeppelin's `SafeERC20` library which is known to work
// with the existing ERC20 implementation we care about,
// make sure we return success for any non-zero return value
// from the `transfer*` call.
success := iszero(iszero(mload(0)))
}
default {
revertWithMessage(31, 'GPv2: malformed transfer result')
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
import {IScaledBalanceToken} from './IScaledBalanceToken.sol';
import {IInitializableAToken} from './IInitializableAToken.sol';
/**
* @title IAToken
* @author Aave
* @notice Defines the basic interface for an AToken.
*/
interface IAToken is IERC20, IScaledBalanceToken, IInitializableAToken {
/**
* @dev Emitted during the transfer action
* @param from The user whose tokens are being transferred
* @param to The recipient
* @param value The scaled amount being transferred
* @param index The next liquidity index of the reserve
*/
event BalanceTransfer(address indexed from, address indexed to, uint256 value, uint256 index);
/**
* @notice Mints `amount` aTokens to `user`
* @param caller The address performing the mint
* @param onBehalfOf The address of the user that will receive the minted aTokens
* @param scaledAmount The scaled amount of tokens getting minted
* @param index The next liquidity index of the reserve
* @return `true` if the the previous balance of the user was 0
*/
function mint(
address caller,
address onBehalfOf,
uint256 scaledAmount,
uint256 index
) external returns (bool);
/**
* @notice Burns aTokens from `user` and sends the equivalent amount of underlying to `receiverOfUnderlying`.
* @dev Passing both the unscaled and scaled amounts enhances precision. The `scaledAmount` is used for precise balance updates,
* while the `amount` is used for the underlying asset transfer, preventing cumulative rounding errors.
* @dev In some instances, a mint event may be emitted from a burn transaction if the amount to burn is less than the interest that the user accrued.
* @param from The address from which the aTokens will be burned
* @param receiverOfUnderlying The address that will receive the underlying
* @param amount The amount of underlying to be burned (non scaled)
* @param scaledAmount The scaled amount of aTokens to be burned (scaled)
* @param index The next liquidity index of the reserve
* @return `true` if the the new balance of the user is 0
*/
function burn(
address from,
address receiverOfUnderlying,
uint256 amount,
uint256 scaledAmount,
uint256 index
) external returns (bool);
/**
* @notice Mints aTokens to the reserve treasury
* @param scaledAmount The scaled amount of tokens getting minted
* @param index The next liquidity index of the reserve
*/
function mintToTreasury(uint256 scaledAmount, uint256 index) external;
/**
* @notice Transfers aTokens in the event of a borrow being liquidated, in case the liquidator reclaims the aToken.
* @dev Passing both the unscaled and scaled amounts enhances precision. The `scaledAmount` is used for precise balance updates,
* while the `amount` is used for logging and consistency, preventing cumulative rounding errors.
* @param from The address getting liquidated, current owner of the aTokens
* @param to The recipient
* @param amount The amount of tokens getting transferred (non-scaled)
* @param scaledAmount The scaled amount of tokens getting transferred (scaled)
* @param index The next liquidity index of the reserve
*/
function transferOnLiquidation(
address from,
address to,
uint256 amount,
uint256 scaledAmount,
uint256 index
) external;
/**
* @notice Transfers the underlying asset to `target`.
* @dev Used by the Pool to transfer assets in borrow(), withdraw() and flashLoan()
* @param target The recipient of the underlying
* @param amount The amount getting transferred
*/
function transferUnderlyingTo(address target, uint256 amount) external;
/**
* @notice Allow passing a signed message to approve spending
* @dev implements the permit function as for
* https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md
* @param owner The owner of the funds
* @param spender The spender
* @param value The amount
* @param deadline The deadline timestamp, type(uint256).max for max deadline
* @param v Signature param
* @param s Signature param
* @param r Signature param
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @notice Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH)
* @return The address of the underlying asset
*/
function UNDERLYING_ASSET_ADDRESS() external view returns (address);
/**
* @notice Returns the address of the Aave treasury, receiving the fees on this aToken.
* @return Address of the Aave treasury
*/
function RESERVE_TREASURY_ADDRESS() external view returns (address);
/**
* @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() external view returns (bytes32);
/**
* @notice Returns the nonce for owner.
* @param owner The address of the owner
* @return The nonce of the owner
*/
function nonces(address owner) external view returns (uint256);
/**
* @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;
}// 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.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({owner: _msgSender(), spender: spender, amount: amount, emitEvent: true});
return true;
}
/// @inheritdoc IERC20
function transferFrom(
address sender,
address recipient,
uint256 amount
) external virtual override returns (bool) {
uint120 castAmount = amount.toUint120();
_spendAllowance({
owner: sender,
spender: _msgSender(),
amount: castAmount,
correctedAmount: castAmount
});
_transfer(sender, recipient, castAmount);
return true;
}
/**
* @notice Sets the allowance of the caller to spend `owner`'s tokens to 0.
* @param owner The address whose tokens are being renounced.
*/
function renounceAllowance(address owner) external virtual {
_approve({owner: owner, spender: _msgSender(), amount: 0, emitEvent: true});
}
/**
* @notice Increases the allowance of spender to spend _msgSender() tokens
* @dev This function is deprecated and will be removed in a future version.
* @custom:deprecated
* @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({
owner: _msgSender(),
spender: spender,
amount: _allowances[_msgSender()][spender] + addedValue,
emitEvent: true
});
return true;
}
/**
* @notice Decreases the allowance of spender to spend _msgSender() tokens
* @dev This function is deprecated and will be removed in a future version.
* @custom:deprecated
* @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) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
_approve({
owner: _msgSender(),
spender: spender,
amount: currentAllowance - subtractedValue,
emitEvent: true
});
return true;
}
/**
* @dev Updates `owner`'s allowance for `spender` based on spent `value`.
*
* Revert if not enough allowance is available.
*
* Doesn't emit the Approval event.
*
* @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);
}
if (currentAllowance == type(uint256).max) {
return;
}
uint256 consumption = currentAllowance >= correctedAmount ? correctedAmount : currentAllowance;
_approve({
owner: owner,
spender: spender,
amount: currentAllowance - consumption,
emitEvent: false
});
}
/**
* @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
* @param emitEvent Whether to emit the Approval event
*/
function _approve(
address owner,
address spender,
uint256 amount,
bool emitEvent
) internal virtual {
_allowances[owner][spender] = amount;
if (emitEvent) {
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;
/**
* @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.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 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: 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 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 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;
/*
* @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.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
}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"},{"internalType":"address","name":"treasury","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CallerMustBePool","type":"error"},{"inputs":[],"name":"CallerNotPoolAdmin","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":[],"name":"InvalidBurnAmount","type":"error"},{"inputs":[],"name":"InvalidExpiration","type":"error"},{"inputs":[],"name":"InvalidMintAmount","type":"error"},{"inputs":[],"name":"InvalidSignature","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":"UnderlyingCannotBeRescued","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":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"BalanceTransfer","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":"treasury","type":"address"},{"indexed":false,"internalType":"address","name":"incentivesController","type":"address"},{"indexed":false,"internalType":"uint8","name":"aTokenDecimals","type":"uint8"},{"indexed":false,"internalType":"string","name":"aTokenName","type":"string"},{"indexed":false,"internalType":"string","name":"aTokenSymbol","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":"ATOKEN_REVISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL","outputs":[{"internalType":"contract IPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESERVE_TREASURY_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARDS_CONTROLLER","outputs":[{"internalType":"contract IAaveIncentivesController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TREASURY","outputs":[{"internalType":"address","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":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"from","type":"address"},{"internalType":"address","name":"receiverOfUnderlying","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"scaledAmount","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","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":"aTokenDecimals","type":"uint8"},{"internalType":"string","name":"aTokenName","type":"string"},{"internalType":"string","name":"aTokenSymbol","type":"string"},{"internalType":"bytes","name":"params","type":"bytes"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"onBehalfOf","type":"address"},{"internalType":"uint256","name":"scaledAmount","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"scaledAmount","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"mintToTreasury","outputs":[],"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":"owner","type":"address"},{"internalType":"address","name":"spender","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":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"renounceAllowance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueTokens","outputs":[],"stateMutability":"nonpayable","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":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"scaledAmount","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"transferOnLiquidation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferUnderlyingTo","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6101206040525f5f55348015610013575f5ffd5b50604051612d39380380612d39833981016040819052610032916101b0565b828282826040518060400160405280600b81526020016a105513d2d15397d253541360aa1b8152506040518060400160405280600b81526020016a105513d2d15397d253541360aa1b8152505f858484848484848484848461009861019460201b60201c565b5f81905550846001600160a01b0316630542975c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100d9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100fd91906101fa565b6001600160a01b0316608052603761011585826102b4565b50603861012284826102b4565b506039805460ff191660ff93909316929092179091556001600160a01b0393841660a052831660c05250504660e0528b16995061017c9850505050505050505057604051633bf95ba760e01b815260040160405180910390fd5b6001600160a01b0316610100525061036e9350505050565b600590565b6001600160a01b03811681146101ad575f5ffd5b50565b5f5f5f606084860312156101c2575f5ffd5b83516101cd81610199565b60208501519093506101de81610199565b60408501519092506101ef81610199565b809150509250925092565b5f6020828403121561020a575f5ffd5b815161021581610199565b9392505050565b634e487b7160e01b5f52604160045260245ffd5b600181811c9082168061024457607f821691505b60208210810361026257634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156102af57805f5260205f20601f840160051c8101602085101561028d5750805b601f840160051c820191505b818110156102ac575f8155600101610299565b50505b505050565b81516001600160401b038111156102cd576102cd61021c565b6102e1816102db8454610230565b84610268565b6020601f821160018114610313575f83156102fc5750848201515b5f19600385901b1c1916600184901b1784556102ac565b5f84815260208120601f198516915b828110156103425787850151825560209485019460019092019101610322565b508482101561035f57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b60805160a05160c05160e051610100516128ed61044c5f395f81816102be0152818161046001528181610a130152610c5f01525f6116fd01525f81816103b3015281816104db01528181610c8001528181611d8f01528181611dce01528181611e6401528181611ff2015261202e01525f818161038f0152818161067a01528181610724015281816107f6015281816108a10152818161092a015281816109a1015281816109f201528181610b0401528181610c0a01528181610d5a01528181610df1015281816112fb01526113e501525f610e5201526128ed5ff3fe608060405234801561000f575f5ffd5b5060043610610208575f3560e01c8063781603761161011f578063b16a19de116100a9578063cd086d4511610079578063cd086d45146104d6578063cea9d26f146104fd578063d505accf14610510578063dd62ed3e14610523578063e07539861461055b575f5ffd5b8063b16a19de14610497578063b18d6afd146104a8578063b1bf962d146104bb578063b3f1c93d146104c3575f5ffd5b806395d89b41116100ef57806395d89b4114610430578063a457c2d714610438578063a9059cbb1461044b578063ae1673351461045e578063af5f243b14610484575f5ffd5b806378160376146103d75780637df5bd3b146103f75780637ecebe001461040a5780637fdd585f1461041d575f5ffd5b806330adf81f116101a0578063395093511161017057806339509351146103515780634efecaa51461036457806370a08231146103775780637535d2461461038a57806375d26413146103b1575f5ffd5b806330adf81f146102f8578063313ce5671461031f578063353b7b9a146103345780633644e51514610349575f5ffd5b806318160ddd116101db57806318160ddd1461028b5780631da24f3e1461029357806323b872dd146102a65780632d2c5565146102b9575f5ffd5b806306fdde031461020c578063095ea7b31461022a5780630afbcdc91461024d5780630bd7ad3b14610275575b5f5ffd5b610214610593565b6040516102219190612296565b60405180910390f35b61023d6102383660046122bc565b610623565b6040519015158152602001610221565b61026061025b3660046122e6565b61063b565b60408051928352602083019190915201610221565b61027d600581565b604051908152602001610221565b61027d610652565b61027d6102a13660046122e6565b6106f4565b61023d6102b4366004612301565b6106fe565b6102e07f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610221565b61027d7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60395460405160ff9091168152602001610221565b61034761034236600461233f565b6107f3565b005b61027d610858565b61023d61035f3660046122bc565b610861565b6103476103723660046122bc565b61089e565b61027d6103853660046122e6565b610902565b6102e07f000000000000000000000000000000000000000000000000000000000000000081565b7f00000000000000000000000000000000000000000000000000000000000000006102e0565b610214604051806040016040528060018152602001603160f81b81525081565b61034761040536600461238c565b61099e565b61027d6104183660046122e6565b610a41565b61034761042b366004612406565b610a5e565b610214610ce1565b61023d6104463660046122bc565b610cf0565b61023d6104593660046122bc565b610d2e565b7f00000000000000000000000000000000000000000000000000000000000000006102e0565b6103476104923660046122e6565b610d46565b603d546001600160a01b03166102e0565b61023d6104b636600461233f565b610d56565b61027d610de3565b61023d6104d13660046124db565b610ded565b6102e07f000000000000000000000000000000000000000000000000000000000000000081565b61034761050b366004612301565b610e4f565b61034761051e36600461251e565b610fae565b61027d610531366004612588565b6001600160a01b039182165f90815260356020908152604080832093909416825291909152205490565b61027d6105693660046122e6565b6001600160a01b03165f90815260346020526040902054600160801b90046001600160801b031690565b6060603780546105a2906125bf565b80601f01602080910402602001604051908101604052809291908181526020018280546105ce906125bf565b80156106195780601f106105f057610100808354040283529160200191610619565b820191905f5260205f20905b8154815290600101906020018083116105fc57829003601f168201915b5050505050905090565b5f6106313384846001611140565b5060015b92915050565b5f5f610646836111c0565b60365491509150915091565b603d5460405163d15e005360e01b81526001600160a01b0391821660048201525f916106ef917f00000000000000000000000000000000000000000000000000000000000000009091169063d15e005390602401602060405180830381865afa1580156106c1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106e591906125f1565b6036545b906111e3565b905090565b5f610635826111c0565b603d5460405163d15e005360e01b81526001600160a01b0391821660048201525f9182917f00000000000000000000000000000000000000000000000000000000000000009091169063d15e005390602401602060405180830381865afa15801561076b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061078f91906125f1565b90505f61079b866111c0565b90506107d48633866107bb866107b183826111f5565b6106e9908861261c565b6107c586886111e3565b6107cf919061261c565b611200565b6107e786866107e28761129d565b6112d4565b50600195945050505050565b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461083c57604051632a59ce7160e11b815260040160405180910390fd5b61085185858561084b8661129d565b85611438565b5050505050565b5f6106ef6116fa565b335f8181526035602090815260408083206001600160a01b0387168452909152812054909161063191859061089790869061262f565b6001611140565b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146108e757604051632a59ce7160e11b815260040160405180910390fd5b603d546108fe906001600160a01b03168383611731565b5050565b603d5460405163d15e005360e01b81526001600160a01b0391821660048201525f91610635917f00000000000000000000000000000000000000000000000000000000000000009091169063d15e005390602401602060405180830381865afa158015610971573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061099591906125f1565b6106e9846111c0565b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146109e757604051632a59ce7160e11b815260040160405180910390fd5b81156108fe57610a3c7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084846111e36117b9565b505050565b6001600160a01b0381165f908152603a6020526040812054610635565b60015460059060ff1680610a715750303b155b80610a7c57505f5481115b610ae45760405162461bcd60e51b815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201526d195b881a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b60015460ff16158015610b02576001805460ff1916811790555f8290555b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168b6001600160a01b031614610b5457604051634c2b89eb60e01b815260040160405180910390fd5b610b9288888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061193992505050565b610bd086868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061194592505050565b6039805460ff191660ff8b16179055603d80546001600160a01b0319166001600160a01b038c16179055610c02611951565b603b819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168a6001600160a01b03167fb19e051f8af41150ccccb3fc2c2d8d15f4a4cf434f32a559ba75fe73d6eea20b7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008d8d8d8d8d8d8d604051610cbb9998979695949392919061266a565b60405180910390a38015610cd4576001805460ff191690555b5050505050505050505050565b6060603880546105a2906125bf565b335f8181526035602090815260408083206001600160a01b03871684529091528120549091610d249085610897868561261c565b5060019392505050565b5f5f610d398361129d565b9050610d243385836112d4565b610d5381335f6001611140565b50565b5f337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610da057604051632a59ce7160e11b815260040160405180910390fd5b5f610db0878786866111e36119f9565b90506001600160a01b0386163014610dd957603d54610dd9906001600160a01b03168787611731565b9695505050505050565b5f6106ef60365490565b5f337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614610e3757604051632a59ce7160e11b815260040160405180910390fd5b610e46858585856111e36117b9565b95945050505050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663707cd7166040518163ffffffff1660e01b8152600401602060405180830381865afa158015610eac573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ed091906126d7565b90506001600160a01b038116637be53ca1336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610f24573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f4891906126f2565b610f655760405163cdd36a9760e01b815260040160405180910390fd5b603d546001600160a01b0390811690851603610f945760405163bf9cb8bb60e01b815260040160405180910390fd5b610fa86001600160a01b0385168484611731565b50505050565b6001600160a01b038716610fd557604051633bf95ba760e01b815260040160405180910390fd5b83421115610ff657604051637d9533a960e11b815260040160405180910390fd5b6001600160a01b0387165f908152603a602052604081205490611017610858565b604080517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c960208201526001600160a01b03808d1692820192909252908a1660608201526080810189905260a0810184905260c0810188905260e001604051602081830303815290604052805190602001206040516020016110b092919061190160f01b81526002810192909252602282015260420190565b6040516020818303038152906040528051906020012090506110d481868686611c1d565b6001600160a01b0316896001600160a01b03161461110557604051638baa579f60e01b815260040160405180910390fd5b61111082600161262f565b6001600160a01b038a165f908152603a60205260409020556111358989896001611140565b505050505050505050565b6001600160a01b038085165f9081526035602090815260408083209387168352929052208290558015610fa857826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516111b291815260200190565b60405180910390a350505050565b6001600160a01b03165f908152603460205260409020546001600160781b031690565b5f6111ee8383611c49565b9392505050565b5f6111ee8383611c70565b6001600160a01b038085165f908152603560209081526040808320938716835292905220548281101561125f57604051637dc7a0d960e11b81526001600160a01b03851660048201526024810182905260448101849052606401610adb565b5f19810361126d5750610fa8565b5f8282101561127c578161127e565b825b9050611295868661128f848661261c565b5f611140565b505050505050565b5f6001600160781b038211156112d0576040516306dfcc6560e41b81526078600482015260248101839052604401610adb565b5090565b603d5460405163d15e005360e01b81526001600160a01b0391821660048201819052915f917f00000000000000000000000000000000000000000000000000000000000000009091169063d15e005390602401602060405180830381865afa158015611342573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061136691906125f1565b90505f611372866111c0565b90505f6113886001600160781b038616846111f5565b90506113a88787876001600160781b03166113a28561129d565b87611438565b604051631277299360e01b81526001600160a01b0385811660048301528881166024830152878116604483015260648201839052608482018490527f0000000000000000000000000000000000000000000000000000000000000000169063127729939060a4015f604051808303815f87803b158015611426575f5ffd5b505af1158015610cd4573d5f5f3e3d5ffd5b5f611442866111c0565b6001600160a01b0387165f9081526034602052604081205491925090611479908390600160801b90046001600160801b03166111e3565b61148383856111e3565b61148d919061261c565b90505f611499876111c0565b6001600160a01b0388165f90815260346020526040812054919250906114d0908390600160801b90046001600160801b03166111e3565b6114da83876111e3565b6114e4919061261c565b90506114ef85611cb3565b6001600160a01b038a165f90815260346020526040902080546001600160801b03928316600160801b02921691909117905561152a85611cb3565b6001600160a01b0389165f90815260346020526040902080546001600160801b03928316600160801b029216919091179055611567898988611ce6565b82156115d5576040518381526001600160a01b038a16905f905f5160206128c15f395f51905f529060200160405180910390a3604080518481526020810185905280820187905290516001600160a01b038b169133915f5160206128a15f395f51905f529181900360600190a35b876001600160a01b0316896001600160a01b0316141580156115f657505f81115b15611663576040518181526001600160a01b038916905f905f5160206128c15f395f51905f529060200160405180910390a3604080518281526020810183905280820187905290516001600160a01b038a169133915f5160206128a15f395f51905f529181900360600190a35b876001600160a01b0316896001600160a01b03165f5160206128c15f395f51905f528960405161169591815260200190565b60405180910390a3604080516001600160781b0388168152602081018790526001600160a01b03808b1692908c16917f4beccb90f994c31aced7a23b5611020728a23d8ec5cddd1a3e9d97b96fda8666910160405180910390a3505050505050505050565b5f7f000000000000000000000000000000000000000000000000000000000000000046036117295750603b5490565b6106ef611951565b60405163a9059cbb60e01b8082526001600160a01b038416600483015260248201839052905f8060448382895af161176b573d5f5f3e3d5ffd5b5061177584611ed2565b610fa85760405162461bcd60e51b815260206004820152601560248201527423a83b191d103330b4b632b2103a3930b739b332b960591b6044820152606401610adb565b5f835f036117da5760405163199f5a0360e31b815260040160405180910390fd5b5f6117e4866111c0565b90505f6117fe6117f4838861262f565b868663ffffffff16565b6001600160a01b0388165f9081526034602052604081205491925090611839908490600160801b90046001600160801b031663ffffffff8816565b90505f8161184b85898963ffffffff16565b611855919061261c565b905061186087611cb3565b6001600160a01b038a165f90815260346020526040902080546001600160801b03928316600160801b0292169190911790556118a48961189f8a61129d565b611f75565b5f6118af838561261c565b9050896001600160a01b03165f6001600160a01b03165f5160206128c15f395f51905f52836040516118e391815260200190565b60405180910390a360408051828152602081018490529081018990526001600160a01b03808c1691908d16905f5160206128a15f395f51905f529060600160405180910390a35050911598975050505050505050565b60376108fe8282612769565b60386108fe8282612769565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61197b61209a565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b5f835f03611a1a576040516302075cc160e41b815260040160405180910390fd5b5f611a24876111c0565b90505f611a346117f4878461261c565b6001600160a01b0389165f9081526034602052604081205491925090611a6f908490600160801b90046001600160801b031663ffffffff8816565b90505f81611a8185898963ffffffff16565b611a8b919061261c565b9050611a9687611cb3565b6001600160a01b038b165f90815260346020526040902080546001600160801b03928316600160801b029216919091179055611ada8a611ad58a61129d565b6120a4565b81831115611b6a575f611aed838561261c565b90508a6001600160a01b03165f6001600160a01b03165f5160206128c15f395f51905f5283604051611b2191815260200190565b60405180910390a360408051828152602081018490529081018990526001600160a01b038c169081905f5160206128a15f395f51905f529060600160405180910390a350611c04565b5f611b75848461261c565b90505f6001600160a01b03168b6001600160a01b03165f5160206128c15f395f51905f5283604051611ba991815260200190565b60405180910390a360408051828152602081018490529081018990526001600160a01b03808c1691908d16907f4cf25bc1d991c17529c25213d3cc0cda295eeaad5f13f361969b12ea48015f909060600160405180910390a3505b611c0e888561261c565b159a9950505050505050505050565b5f5f5f5f611c2d888888886120e8565b925092509250611c3d82826121b0565b50909695505050505050565b5f815f1904831115821517611c5c575f5ffd5b506b033b2e3c9fd0803ce800000091020490565b5f8115744f3a68dbc8f03f243baf513267aa9a3ee524f8e02884111715611c95575f5ffd5b506b033b2e3c9fd0803ce80000009190910281810491900615150190565b5f6001600160801b038211156112d0576040516306dfcc6560e41b81526080600482015260248101839052604401610adb565b6001600160a01b0383165f908152603460205260409020546001600160781b0316611d118282612824565b6001600160a01b038581165f9081526034602052604080822080546001600160781b0319166001600160781b039586161790559186168152205416611d568382612843565b6001600160a01b038581165f90815260346020526040902080546001600160781b0319166001600160781b0393909316929092179091557f00000000000000000000000000000000000000000000000000000000000000001615610851576036546040516318c39f1760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906331873e2e90611e0790899085908890600401612862565b5f604051808303815f87803b158015611e1e575f5ffd5b505af1158015611e30573d5f5f3e3d5ffd5b50505050846001600160a01b0316866001600160a01b031614611295576040516318c39f1760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906331873e2e90611e9d90889085908790600401612862565b5f604051808303815f87803b158015611eb4575f5ffd5b505af1158015611ec6573d5f5f3e3d5ffd5b50505050505050505050565b5f611ef4565b62461bcd60e51b5f52602060045280602452508060445260645ffd5b3d8015611f335760208114611f6457611f2e7f475076323a206d616c666f726d6564207472616e7366657220726573756c7400601f611ed8565b611f6f565b823b611f5b57611f5b7311d41d8c8e881b9bdd08184818dbdb9d1c9858dd60621b6014611ed8565b60019150611f6f565b3d5f5f3e5f51151591505b50919050565b603654611f8b6001600160781b0383168261262f565b6036556001600160a01b0383165f908152603460205260409020546001600160781b0316611fb98382612843565b6001600160a01b038581165f90815260346020526040902080546001600160781b0319166001600160781b0393909316929092179091557f00000000000000000000000000000000000000000000000000000000000000001615610fa8576040516318c39f1760e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906331873e2e9061206790879086908690600401612862565b5f604051808303815f87803b15801561207e575f5ffd5b505af1158015612090573d5f5f3e3d5ffd5b5050505050505050565b60606106ef610593565b6036546120ba6001600160781b0383168261261c565b6036556001600160a01b0383165f908152603460205260409020546001600160781b0316611fb98382612824565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561212157505f915060039050826121a6565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015612172573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b03811661219d57505f9250600191508290506121a6565b92505f91508190505b9450945094915050565b5f8260038111156121c3576121c361288c565b036121cc575050565b60018260038111156121e0576121e061288c565b036121fe5760405163f645eedf60e01b815260040160405180910390fd5b60028260038111156122125761221261288c565b036122335760405163fce698f760e01b815260048101829052602401610adb565b60038260038111156122475761224761288c565b036108fe576040516335e2f38360e21b815260048101829052602401610adb565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6111ee6020830184612268565b6001600160a01b0381168114610d53575f5ffd5b5f5f604083850312156122cd575f5ffd5b82356122d8816122a8565b946020939093013593505050565b5f602082840312156122f6575f5ffd5b81356111ee816122a8565b5f5f5f60608486031215612313575f5ffd5b833561231e816122a8565b9250602084013561232e816122a8565b929592945050506040919091013590565b5f5f5f5f5f60a08688031215612353575f5ffd5b853561235e816122a8565b9450602086013561236e816122a8565b94979496505050506040830135926060810135926080909101359150565b5f5f6040838503121561239d575f5ffd5b50508035926020909101359150565b803560ff811681146123bc575f5ffd5b919050565b5f5f83601f8401126123d1575f5ffd5b50813567ffffffffffffffff8111156123e8575f5ffd5b6020830191508360208285010111156123ff575f5ffd5b9250929050565b5f5f5f5f5f5f5f5f5f60c08a8c03121561241e575f5ffd5b8935612429816122a8565b985060208a0135612439816122a8565b975061244760408b016123ac565b965060608a013567ffffffffffffffff811115612462575f5ffd5b61246e8c828d016123c1565b90975095505060808a013567ffffffffffffffff81111561248d575f5ffd5b6124998c828d016123c1565b90955093505060a08a013567ffffffffffffffff8111156124b8575f5ffd5b6124c48c828d016123c1565b915080935050809150509295985092959850929598565b5f5f5f5f608085870312156124ee575f5ffd5b84356124f9816122a8565b93506020850135612509816122a8565b93969395505050506040820135916060013590565b5f5f5f5f5f5f5f60e0888a031215612534575f5ffd5b873561253f816122a8565b9650602088013561254f816122a8565b9550604088013594506060880135935061256b608089016123ac565b9699959850939692959460a0840135945060c09093013592915050565b5f5f60408385031215612599575f5ffd5b82356125a4816122a8565b915060208301356125b4816122a8565b809150509250929050565b600181811c908216806125d357607f821691505b602082108103611f6f57634e487b7160e01b5f52602260045260245ffd5b5f60208284031215612601575f5ffd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561063557610635612608565b8082018082111561063557610635612608565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b6001600160a01b038a811682528916602082015260ff8816604082015260c0606082018190525f9061269f908301888a612642565b82810360808401526126b2818789612642565b905082810360a08401526126c7818587612642565b9c9b505050505050505050505050565b5f602082840312156126e7575f5ffd5b81516111ee816122a8565b5f60208284031215612702575f5ffd5b815180151581146111ee575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b601f821115610a3c57805f5260205f20601f840160051c8101602085101561274a5750805b601f840160051c820191505b81811015610851575f8155600101612756565b815167ffffffffffffffff81111561278357612783612711565b6127978161279184546125bf565b84612725565b6020601f8211600181146127c9575f83156127b25750848201515b5f19600385901b1c1916600184901b178455610851565b5f84815260208120601f198516915b828110156127f857878501518255602094850194600190920191016127d8565b508482101561281557868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b6001600160781b03828116828216039081111561063557610635612608565b6001600160781b03818116838216019081111561063557610635612608565b6001600160a01b0393909316835260208301919091526001600160781b0316604082015260600190565b634e487b7160e01b5f52602160045260245ffdfe458f5fa412d0f69b08dd84872b0215675cc67bc1d5b6fd93300a1c3878b86196ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa164736f6c634300081b000a000000000000000000000000794a61358d6845594f94dc1db02a252b5b4814ad000000000000000000000000929ec64c34a17401f460460d4b9390518e5b473e000000000000000000000000053d55f9b5af8694c503eb288a1b7e552f590710
Deployed Bytecode
0x608060405234801561000f575f5ffd5b5060043610610208575f3560e01c8063781603761161011f578063b16a19de116100a9578063cd086d4511610079578063cd086d45146104d6578063cea9d26f146104fd578063d505accf14610510578063dd62ed3e14610523578063e07539861461055b575f5ffd5b8063b16a19de14610497578063b18d6afd146104a8578063b1bf962d146104bb578063b3f1c93d146104c3575f5ffd5b806395d89b41116100ef57806395d89b4114610430578063a457c2d714610438578063a9059cbb1461044b578063ae1673351461045e578063af5f243b14610484575f5ffd5b806378160376146103d75780637df5bd3b146103f75780637ecebe001461040a5780637fdd585f1461041d575f5ffd5b806330adf81f116101a0578063395093511161017057806339509351146103515780634efecaa51461036457806370a08231146103775780637535d2461461038a57806375d26413146103b1575f5ffd5b806330adf81f146102f8578063313ce5671461031f578063353b7b9a146103345780633644e51514610349575f5ffd5b806318160ddd116101db57806318160ddd1461028b5780631da24f3e1461029357806323b872dd146102a65780632d2c5565146102b9575f5ffd5b806306fdde031461020c578063095ea7b31461022a5780630afbcdc91461024d5780630bd7ad3b14610275575b5f5ffd5b610214610593565b6040516102219190612296565b60405180910390f35b61023d6102383660046122bc565b610623565b6040519015158152602001610221565b61026061025b3660046122e6565b61063b565b60408051928352602083019190915201610221565b61027d600581565b604051908152602001610221565b61027d610652565b61027d6102a13660046122e6565b6106f4565b61023d6102b4366004612301565b6106fe565b6102e07f000000000000000000000000053d55f9b5af8694c503eb288a1b7e552f59071081565b6040516001600160a01b039091168152602001610221565b61027d7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60395460405160ff9091168152602001610221565b61034761034236600461233f565b6107f3565b005b61027d610858565b61023d61035f3660046122bc565b610861565b6103476103723660046122bc565b61089e565b61027d6103853660046122e6565b610902565b6102e07f000000000000000000000000794a61358d6845594f94dc1db02a252b5b4814ad81565b7f000000000000000000000000929ec64c34a17401f460460d4b9390518e5b473e6102e0565b610214604051806040016040528060018152602001603160f81b81525081565b61034761040536600461238c565b61099e565b61027d6104183660046122e6565b610a41565b61034761042b366004612406565b610a5e565b610214610ce1565b61023d6104463660046122bc565b610cf0565b61023d6104593660046122bc565b610d2e565b7f000000000000000000000000053d55f9b5af8694c503eb288a1b7e552f5907106102e0565b6103476104923660046122e6565b610d46565b603d546001600160a01b03166102e0565b61023d6104b636600461233f565b610d56565b61027d610de3565b61023d6104d13660046124db565b610ded565b6102e07f000000000000000000000000929ec64c34a17401f460460d4b9390518e5b473e81565b61034761050b366004612301565b610e4f565b61034761051e36600461251e565b610fae565b61027d610531366004612588565b6001600160a01b039182165f90815260356020908152604080832093909416825291909152205490565b61027d6105693660046122e6565b6001600160a01b03165f90815260346020526040902054600160801b90046001600160801b031690565b6060603780546105a2906125bf565b80601f01602080910402602001604051908101604052809291908181526020018280546105ce906125bf565b80156106195780601f106105f057610100808354040283529160200191610619565b820191905f5260205f20905b8154815290600101906020018083116105fc57829003601f168201915b5050505050905090565b5f6106313384846001611140565b5060015b92915050565b5f5f610646836111c0565b60365491509150915091565b603d5460405163d15e005360e01b81526001600160a01b0391821660048201525f916106ef917f000000000000000000000000794a61358d6845594f94dc1db02a252b5b4814ad9091169063d15e005390602401602060405180830381865afa1580156106c1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106e591906125f1565b6036545b906111e3565b905090565b5f610635826111c0565b603d5460405163d15e005360e01b81526001600160a01b0391821660048201525f9182917f000000000000000000000000794a61358d6845594f94dc1db02a252b5b4814ad9091169063d15e005390602401602060405180830381865afa15801561076b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061078f91906125f1565b90505f61079b866111c0565b90506107d48633866107bb866107b183826111f5565b6106e9908861261c565b6107c586886111e3565b6107cf919061261c565b611200565b6107e786866107e28761129d565b6112d4565b50600195945050505050565b337f000000000000000000000000794a61358d6845594f94dc1db02a252b5b4814ad6001600160a01b03161461083c57604051632a59ce7160e11b815260040160405180910390fd5b61085185858561084b8661129d565b85611438565b5050505050565b5f6106ef6116fa565b335f8181526035602090815260408083206001600160a01b0387168452909152812054909161063191859061089790869061262f565b6001611140565b337f000000000000000000000000794a61358d6845594f94dc1db02a252b5b4814ad6001600160a01b0316146108e757604051632a59ce7160e11b815260040160405180910390fd5b603d546108fe906001600160a01b03168383611731565b5050565b603d5460405163d15e005360e01b81526001600160a01b0391821660048201525f91610635917f000000000000000000000000794a61358d6845594f94dc1db02a252b5b4814ad9091169063d15e005390602401602060405180830381865afa158015610971573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061099591906125f1565b6106e9846111c0565b337f000000000000000000000000794a61358d6845594f94dc1db02a252b5b4814ad6001600160a01b0316146109e757604051632a59ce7160e11b815260040160405180910390fd5b81156108fe57610a3c7f000000000000000000000000794a61358d6845594f94dc1db02a252b5b4814ad7f000000000000000000000000053d55f9b5af8694c503eb288a1b7e552f59071084846111e36117b9565b505050565b6001600160a01b0381165f908152603a6020526040812054610635565b60015460059060ff1680610a715750303b155b80610a7c57505f5481115b610ae45760405162461bcd60e51b815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201526d195b881a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b60015460ff16158015610b02576001805460ff1916811790555f8290555b7f000000000000000000000000794a61358d6845594f94dc1db02a252b5b4814ad6001600160a01b03168b6001600160a01b031614610b5457604051634c2b89eb60e01b815260040160405180910390fd5b610b9288888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061193992505050565b610bd086868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061194592505050565b6039805460ff191660ff8b16179055603d80546001600160a01b0319166001600160a01b038c16179055610c02611951565b603b819055507f000000000000000000000000794a61358d6845594f94dc1db02a252b5b4814ad6001600160a01b03168a6001600160a01b03167fb19e051f8af41150ccccb3fc2c2d8d15f4a4cf434f32a559ba75fe73d6eea20b7f000000000000000000000000053d55f9b5af8694c503eb288a1b7e552f5907107f000000000000000000000000929ec64c34a17401f460460d4b9390518e5b473e8d8d8d8d8d8d8d604051610cbb9998979695949392919061266a565b60405180910390a38015610cd4576001805460ff191690555b5050505050505050505050565b6060603880546105a2906125bf565b335f8181526035602090815260408083206001600160a01b03871684529091528120549091610d249085610897868561261c565b5060019392505050565b5f5f610d398361129d565b9050610d243385836112d4565b610d5381335f6001611140565b50565b5f337f000000000000000000000000794a61358d6845594f94dc1db02a252b5b4814ad6001600160a01b031614610da057604051632a59ce7160e11b815260040160405180910390fd5b5f610db0878786866111e36119f9565b90506001600160a01b0386163014610dd957603d54610dd9906001600160a01b03168787611731565b9695505050505050565b5f6106ef60365490565b5f337f000000000000000000000000794a61358d6845594f94dc1db02a252b5b4814ad6001600160a01b031614610e3757604051632a59ce7160e11b815260040160405180910390fd5b610e46858585856111e36117b9565b95945050505050565b5f7f000000000000000000000000a97684ead0e402dc232d5a977953df7ecbab3cdb6001600160a01b031663707cd7166040518163ffffffff1660e01b8152600401602060405180830381865afa158015610eac573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ed091906126d7565b90506001600160a01b038116637be53ca1336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610f24573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f4891906126f2565b610f655760405163cdd36a9760e01b815260040160405180910390fd5b603d546001600160a01b0390811690851603610f945760405163bf9cb8bb60e01b815260040160405180910390fd5b610fa86001600160a01b0385168484611731565b50505050565b6001600160a01b038716610fd557604051633bf95ba760e01b815260040160405180910390fd5b83421115610ff657604051637d9533a960e11b815260040160405180910390fd5b6001600160a01b0387165f908152603a602052604081205490611017610858565b604080517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c960208201526001600160a01b03808d1692820192909252908a1660608201526080810189905260a0810184905260c0810188905260e001604051602081830303815290604052805190602001206040516020016110b092919061190160f01b81526002810192909252602282015260420190565b6040516020818303038152906040528051906020012090506110d481868686611c1d565b6001600160a01b0316896001600160a01b03161461110557604051638baa579f60e01b815260040160405180910390fd5b61111082600161262f565b6001600160a01b038a165f908152603a60205260409020556111358989896001611140565b505050505050505050565b6001600160a01b038085165f9081526035602090815260408083209387168352929052208290558015610fa857826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516111b291815260200190565b60405180910390a350505050565b6001600160a01b03165f908152603460205260409020546001600160781b031690565b5f6111ee8383611c49565b9392505050565b5f6111ee8383611c70565b6001600160a01b038085165f908152603560209081526040808320938716835292905220548281101561125f57604051637dc7a0d960e11b81526001600160a01b03851660048201526024810182905260448101849052606401610adb565b5f19810361126d5750610fa8565b5f8282101561127c578161127e565b825b9050611295868661128f848661261c565b5f611140565b505050505050565b5f6001600160781b038211156112d0576040516306dfcc6560e41b81526078600482015260248101839052604401610adb565b5090565b603d5460405163d15e005360e01b81526001600160a01b0391821660048201819052915f917f000000000000000000000000794a61358d6845594f94dc1db02a252b5b4814ad9091169063d15e005390602401602060405180830381865afa158015611342573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061136691906125f1565b90505f611372866111c0565b90505f6113886001600160781b038616846111f5565b90506113a88787876001600160781b03166113a28561129d565b87611438565b604051631277299360e01b81526001600160a01b0385811660048301528881166024830152878116604483015260648201839052608482018490527f000000000000000000000000794a61358d6845594f94dc1db02a252b5b4814ad169063127729939060a4015f604051808303815f87803b158015611426575f5ffd5b505af1158015610cd4573d5f5f3e3d5ffd5b5f611442866111c0565b6001600160a01b0387165f9081526034602052604081205491925090611479908390600160801b90046001600160801b03166111e3565b61148383856111e3565b61148d919061261c565b90505f611499876111c0565b6001600160a01b0388165f90815260346020526040812054919250906114d0908390600160801b90046001600160801b03166111e3565b6114da83876111e3565b6114e4919061261c565b90506114ef85611cb3565b6001600160a01b038a165f90815260346020526040902080546001600160801b03928316600160801b02921691909117905561152a85611cb3565b6001600160a01b0389165f90815260346020526040902080546001600160801b03928316600160801b029216919091179055611567898988611ce6565b82156115d5576040518381526001600160a01b038a16905f905f5160206128c15f395f51905f529060200160405180910390a3604080518481526020810185905280820187905290516001600160a01b038b169133915f5160206128a15f395f51905f529181900360600190a35b876001600160a01b0316896001600160a01b0316141580156115f657505f81115b15611663576040518181526001600160a01b038916905f905f5160206128c15f395f51905f529060200160405180910390a3604080518281526020810183905280820187905290516001600160a01b038a169133915f5160206128a15f395f51905f529181900360600190a35b876001600160a01b0316896001600160a01b03165f5160206128c15f395f51905f528960405161169591815260200190565b60405180910390a3604080516001600160781b0388168152602081018790526001600160a01b03808b1692908c16917f4beccb90f994c31aced7a23b5611020728a23d8ec5cddd1a3e9d97b96fda8666910160405180910390a3505050505050505050565b5f7f000000000000000000000000000000000000000000000000000000000000a4b146036117295750603b5490565b6106ef611951565b60405163a9059cbb60e01b8082526001600160a01b038416600483015260248201839052905f8060448382895af161176b573d5f5f3e3d5ffd5b5061177584611ed2565b610fa85760405162461bcd60e51b815260206004820152601560248201527423a83b191d103330b4b632b2103a3930b739b332b960591b6044820152606401610adb565b5f835f036117da5760405163199f5a0360e31b815260040160405180910390fd5b5f6117e4866111c0565b90505f6117fe6117f4838861262f565b868663ffffffff16565b6001600160a01b0388165f9081526034602052604081205491925090611839908490600160801b90046001600160801b031663ffffffff8816565b90505f8161184b85898963ffffffff16565b611855919061261c565b905061186087611cb3565b6001600160a01b038a165f90815260346020526040902080546001600160801b03928316600160801b0292169190911790556118a48961189f8a61129d565b611f75565b5f6118af838561261c565b9050896001600160a01b03165f6001600160a01b03165f5160206128c15f395f51905f52836040516118e391815260200190565b60405180910390a360408051828152602081018490529081018990526001600160a01b03808c1691908d16905f5160206128a15f395f51905f529060600160405180910390a35050911598975050505050505050565b60376108fe8282612769565b60386108fe8282612769565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61197b61209a565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b5f835f03611a1a576040516302075cc160e41b815260040160405180910390fd5b5f611a24876111c0565b90505f611a346117f4878461261c565b6001600160a01b0389165f9081526034602052604081205491925090611a6f908490600160801b90046001600160801b031663ffffffff8816565b90505f81611a8185898963ffffffff16565b611a8b919061261c565b9050611a9687611cb3565b6001600160a01b038b165f90815260346020526040902080546001600160801b03928316600160801b029216919091179055611ada8a611ad58a61129d565b6120a4565b81831115611b6a575f611aed838561261c565b90508a6001600160a01b03165f6001600160a01b03165f5160206128c15f395f51905f5283604051611b2191815260200190565b60405180910390a360408051828152602081018490529081018990526001600160a01b038c169081905f5160206128a15f395f51905f529060600160405180910390a350611c04565b5f611b75848461261c565b90505f6001600160a01b03168b6001600160a01b03165f5160206128c15f395f51905f5283604051611ba991815260200190565b60405180910390a360408051828152602081018490529081018990526001600160a01b03808c1691908d16907f4cf25bc1d991c17529c25213d3cc0cda295eeaad5f13f361969b12ea48015f909060600160405180910390a3505b611c0e888561261c565b159a9950505050505050505050565b5f5f5f5f611c2d888888886120e8565b925092509250611c3d82826121b0565b50909695505050505050565b5f815f1904831115821517611c5c575f5ffd5b506b033b2e3c9fd0803ce800000091020490565b5f8115744f3a68dbc8f03f243baf513267aa9a3ee524f8e02884111715611c95575f5ffd5b506b033b2e3c9fd0803ce80000009190910281810491900615150190565b5f6001600160801b038211156112d0576040516306dfcc6560e41b81526080600482015260248101839052604401610adb565b6001600160a01b0383165f908152603460205260409020546001600160781b0316611d118282612824565b6001600160a01b038581165f9081526034602052604080822080546001600160781b0319166001600160781b039586161790559186168152205416611d568382612843565b6001600160a01b038581165f90815260346020526040902080546001600160781b0319166001600160781b0393909316929092179091557f000000000000000000000000929ec64c34a17401f460460d4b9390518e5b473e1615610851576036546040516318c39f1760e11b81526001600160a01b037f000000000000000000000000929ec64c34a17401f460460d4b9390518e5b473e16906331873e2e90611e0790899085908890600401612862565b5f604051808303815f87803b158015611e1e575f5ffd5b505af1158015611e30573d5f5f3e3d5ffd5b50505050846001600160a01b0316866001600160a01b031614611295576040516318c39f1760e11b81526001600160a01b037f000000000000000000000000929ec64c34a17401f460460d4b9390518e5b473e16906331873e2e90611e9d90889085908790600401612862565b5f604051808303815f87803b158015611eb4575f5ffd5b505af1158015611ec6573d5f5f3e3d5ffd5b50505050505050505050565b5f611ef4565b62461bcd60e51b5f52602060045280602452508060445260645ffd5b3d8015611f335760208114611f6457611f2e7f475076323a206d616c666f726d6564207472616e7366657220726573756c7400601f611ed8565b611f6f565b823b611f5b57611f5b7311d41d8c8e881b9bdd08184818dbdb9d1c9858dd60621b6014611ed8565b60019150611f6f565b3d5f5f3e5f51151591505b50919050565b603654611f8b6001600160781b0383168261262f565b6036556001600160a01b0383165f908152603460205260409020546001600160781b0316611fb98382612843565b6001600160a01b038581165f90815260346020526040902080546001600160781b0319166001600160781b0393909316929092179091557f000000000000000000000000929ec64c34a17401f460460d4b9390518e5b473e1615610fa8576040516318c39f1760e11b81526001600160a01b037f000000000000000000000000929ec64c34a17401f460460d4b9390518e5b473e16906331873e2e9061206790879086908690600401612862565b5f604051808303815f87803b15801561207e575f5ffd5b505af1158015612090573d5f5f3e3d5ffd5b5050505050505050565b60606106ef610593565b6036546120ba6001600160781b0383168261261c565b6036556001600160a01b0383165f908152603460205260409020546001600160781b0316611fb98382612824565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561212157505f915060039050826121a6565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015612172573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b03811661219d57505f9250600191508290506121a6565b92505f91508190505b9450945094915050565b5f8260038111156121c3576121c361288c565b036121cc575050565b60018260038111156121e0576121e061288c565b036121fe5760405163f645eedf60e01b815260040160405180910390fd5b60028260038111156122125761221261288c565b036122335760405163fce698f760e01b815260048101829052602401610adb565b60038260038111156122475761224761288c565b036108fe576040516335e2f38360e21b815260048101829052602401610adb565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6111ee6020830184612268565b6001600160a01b0381168114610d53575f5ffd5b5f5f604083850312156122cd575f5ffd5b82356122d8816122a8565b946020939093013593505050565b5f602082840312156122f6575f5ffd5b81356111ee816122a8565b5f5f5f60608486031215612313575f5ffd5b833561231e816122a8565b9250602084013561232e816122a8565b929592945050506040919091013590565b5f5f5f5f5f60a08688031215612353575f5ffd5b853561235e816122a8565b9450602086013561236e816122a8565b94979496505050506040830135926060810135926080909101359150565b5f5f6040838503121561239d575f5ffd5b50508035926020909101359150565b803560ff811681146123bc575f5ffd5b919050565b5f5f83601f8401126123d1575f5ffd5b50813567ffffffffffffffff8111156123e8575f5ffd5b6020830191508360208285010111156123ff575f5ffd5b9250929050565b5f5f5f5f5f5f5f5f5f60c08a8c03121561241e575f5ffd5b8935612429816122a8565b985060208a0135612439816122a8565b975061244760408b016123ac565b965060608a013567ffffffffffffffff811115612462575f5ffd5b61246e8c828d016123c1565b90975095505060808a013567ffffffffffffffff81111561248d575f5ffd5b6124998c828d016123c1565b90955093505060a08a013567ffffffffffffffff8111156124b8575f5ffd5b6124c48c828d016123c1565b915080935050809150509295985092959850929598565b5f5f5f5f608085870312156124ee575f5ffd5b84356124f9816122a8565b93506020850135612509816122a8565b93969395505050506040820135916060013590565b5f5f5f5f5f5f5f60e0888a031215612534575f5ffd5b873561253f816122a8565b9650602088013561254f816122a8565b9550604088013594506060880135935061256b608089016123ac565b9699959850939692959460a0840135945060c09093013592915050565b5f5f60408385031215612599575f5ffd5b82356125a4816122a8565b915060208301356125b4816122a8565b809150509250929050565b600181811c908216806125d357607f821691505b602082108103611f6f57634e487b7160e01b5f52602260045260245ffd5b5f60208284031215612601575f5ffd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561063557610635612608565b8082018082111561063557610635612608565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b6001600160a01b038a811682528916602082015260ff8816604082015260c0606082018190525f9061269f908301888a612642565b82810360808401526126b2818789612642565b905082810360a08401526126c7818587612642565b9c9b505050505050505050505050565b5f602082840312156126e7575f5ffd5b81516111ee816122a8565b5f60208284031215612702575f5ffd5b815180151581146111ee575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b601f821115610a3c57805f5260205f20601f840160051c8101602085101561274a5750805b601f840160051c820191505b81811015610851575f8155600101612756565b815167ffffffffffffffff81111561278357612783612711565b6127978161279184546125bf565b84612725565b6020601f8211600181146127c9575f83156127b25750848201515b5f19600385901b1c1916600184901b178455610851565b5f84815260208120601f198516915b828110156127f857878501518255602094850194600190920191016127d8565b508482101561281557868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b6001600160781b03828116828216039081111561063557610635612608565b6001600160781b03818116838216019081111561063557610635612608565b6001600160a01b0393909316835260208301919091526001600160781b0316604082015260600190565b634e487b7160e01b5f52602160045260245ffdfe458f5fa412d0f69b08dd84872b0215675cc67bc1d5b6fd93300a1c3878b86196ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa164736f6c634300081b000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000794a61358d6845594f94dc1db02a252b5b4814ad000000000000000000000000929ec64c34a17401f460460d4b9390518e5b473e000000000000000000000000053d55f9b5af8694c503eb288a1b7e552f590710
-----Decoded View---------------
Arg [0] : pool (address): 0x794a61358D6845594F94dc1DB02A252b5b4814aD
Arg [1] : rewardsController (address): 0x929EC64c34a17401F460460D4B9390518E5B473e
Arg [2] : treasury (address): 0x053D55f9B5AF8694c503EB288a1B7E552f590710
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000794a61358d6845594f94dc1db02a252b5b4814ad
Arg [1] : 000000000000000000000000929ec64c34a17401f460460d4b9390518e5b473e
Arg [2] : 000000000000000000000000053d55f9b5af8694c503eb288a1b7e552f590710
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 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.