Address Details
contract
0x8e6779F2AC23F196ef9a6b446e557A6f81fD4F51
- Contract Name
- ReserveLogic
- Creator
- 0x643c57–e72624 at 0x100878–1562c9
- Balance
- 0 CELO ( )
- Locked CELO Balance
- 0.00 CELO
- Voting CELO Balance
- 0.00 CELO
- Pending Unlocked Gold
- 0.00 CELO
- Tokens
-
Fetching tokens...
- Transactions
- 0 Transactions
- Transfers
- 0 Transfers
- Gas Used
- Fetching gas used...
- Last Balance Update
- 11834148
This contract has been verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- ReserveLogic
- Optimization enabled
- true
- Compiler version
- v0.6.12+commit.27d51765
- Optimization runs
- 200
- EVM Version
- istanbul
- Verified at
- 2021-12-15T12:35:13.281973Z
contracts/protocol/libraries/logic/ReserveLogic.sol
// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; import {SafeMath} from '../../../dependencies/openzeppelin/contracts/SafeMath.sol'; import {IERC20} from '../../../dependencies/openzeppelin/contracts/IERC20.sol'; import {SafeERC20} from '../../../dependencies/openzeppelin/contracts/SafeERC20.sol'; import {IAToken} from '../../../interfaces/IAToken.sol'; import {IStableDebtToken} from '../../../interfaces/IStableDebtToken.sol'; import {IVariableDebtToken} from '../../../interfaces/IVariableDebtToken.sol'; import {IReserveInterestRateStrategy} from '../../../interfaces/IReserveInterestRateStrategy.sol'; import {ReserveConfiguration} from '../configuration/ReserveConfiguration.sol'; import {MathUtils} from '../math/MathUtils.sol'; import {WadRayMath} from '../math/WadRayMath.sol'; import {PercentageMath} from '../math/PercentageMath.sol'; import {Errors} from '../helpers/Errors.sol'; import {DataTypes} from '../types/DataTypes.sol'; /** * @title ReserveLogic library * @author Aave * @notice Implements the logic to update the reserves state */ library ReserveLogic { using SafeMath for uint256; using WadRayMath for uint256; using PercentageMath for uint256; using SafeERC20 for IERC20; /** * @dev Emitted when the state of a reserve is updated * @param asset The address of the underlying asset of the reserve * @param liquidityRate The new liquidity rate * @param stableBorrowRate The new stable borrow rate * @param variableBorrowRate The new variable borrow rate * @param liquidityIndex The new liquidity index * @param variableBorrowIndex The new variable borrow index **/ event ReserveDataUpdated( address indexed asset, uint256 liquidityRate, uint256 stableBorrowRate, uint256 variableBorrowRate, uint256 liquidityIndex, uint256 variableBorrowIndex ); using ReserveLogic for DataTypes.ReserveData; using ReserveConfiguration for DataTypes.ReserveConfigurationMap; /** * @dev Returns the ongoing normalized income for the reserve * A value of 1e27 means there is no income. As time passes, the income is accrued * A value of 2*1e27 means for each unit of asset one unit of income has been accrued * @param reserve The reserve object * @return the normalized income. expressed in ray **/ function getNormalizedIncome(DataTypes.ReserveData storage reserve) internal view returns (uint256) { uint40 timestamp = reserve.lastUpdateTimestamp; //solium-disable-next-line if (timestamp == uint40(block.timestamp)) { //if the index was updated in the same block, no need to perform any calculation return reserve.liquidityIndex; } uint256 cumulated = MathUtils.calculateLinearInterest(reserve.currentLiquidityRate, timestamp).rayMul( reserve.liquidityIndex ); return cumulated; } /** * @dev Returns the ongoing normalized variable debt for the reserve * A value of 1e27 means there is no debt. As time passes, the income is accrued * A value of 2*1e27 means that for each unit of debt, one unit worth of interest has been accumulated * @param reserve The reserve object * @return The normalized variable debt. expressed in ray **/ function getNormalizedDebt(DataTypes.ReserveData storage reserve) internal view returns (uint256) { uint40 timestamp = reserve.lastUpdateTimestamp; //solium-disable-next-line if (timestamp == uint40(block.timestamp)) { //if the index was updated in the same block, no need to perform any calculation return reserve.variableBorrowIndex; } uint256 cumulated = MathUtils.calculateCompoundedInterest(reserve.currentVariableBorrowRate, timestamp).rayMul( reserve.variableBorrowIndex ); return cumulated; } /** * @dev Updates the liquidity cumulative index and the variable borrow index. * @param reserve the reserve object **/ function updateState(DataTypes.ReserveData storage reserve) internal { uint256 scaledVariableDebt = IVariableDebtToken(reserve.variableDebtTokenAddress).scaledTotalSupply(); uint256 previousVariableBorrowIndex = reserve.variableBorrowIndex; uint256 previousLiquidityIndex = reserve.liquidityIndex; uint40 lastUpdatedTimestamp = reserve.lastUpdateTimestamp; (uint256 newLiquidityIndex, uint256 newVariableBorrowIndex) = _updateIndexes( reserve, scaledVariableDebt, previousLiquidityIndex, previousVariableBorrowIndex, lastUpdatedTimestamp ); _mintToTreasury( reserve, scaledVariableDebt, previousVariableBorrowIndex, newLiquidityIndex, newVariableBorrowIndex, lastUpdatedTimestamp ); } /** * @dev Accumulates a predefined amount of asset to the reserve as a fixed, instantaneous income. Used for example to accumulate * the flashloan fee to the reserve, and spread it between all the depositors * @param reserve The reserve object * @param totalLiquidity The total liquidity available in the reserve * @param amount The amount to accomulate **/ function cumulateToLiquidityIndex( DataTypes.ReserveData storage reserve, uint256 totalLiquidity, uint256 amount ) internal { uint256 amountToLiquidityRatio = amount.wadToRay().rayDiv(totalLiquidity.wadToRay()); uint256 result = amountToLiquidityRatio.add(WadRayMath.ray()); result = result.rayMul(reserve.liquidityIndex); require(result <= type(uint128).max, Errors.RL_LIQUIDITY_INDEX_OVERFLOW); reserve.liquidityIndex = uint128(result); } /** * @dev Initializes a reserve * @param reserve The reserve object * @param aTokenAddress The address of the overlying atoken contract * @param interestRateStrategyAddress The address of the interest rate strategy contract **/ function init( DataTypes.ReserveData storage reserve, address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress, address interestRateStrategyAddress ) external { require(reserve.aTokenAddress == address(0), Errors.RL_RESERVE_ALREADY_INITIALIZED); reserve.liquidityIndex = uint128(WadRayMath.ray()); reserve.variableBorrowIndex = uint128(WadRayMath.ray()); reserve.aTokenAddress = aTokenAddress; reserve.stableDebtTokenAddress = stableDebtTokenAddress; reserve.variableDebtTokenAddress = variableDebtTokenAddress; reserve.interestRateStrategyAddress = interestRateStrategyAddress; } struct UpdateInterestRatesLocalVars { address stableDebtTokenAddress; uint256 availableLiquidity; uint256 totalStableDebt; uint256 newLiquidityRate; uint256 newStableRate; uint256 newVariableRate; uint256 avgStableRate; uint256 totalVariableDebt; } /** * @dev Updates the reserve current stable borrow rate, the current variable borrow rate and the current liquidity rate * @param reserve The address of the reserve to be updated * @param liquidityAdded The amount of liquidity added to the protocol (deposit or repay) in the previous action * @param liquidityTaken The amount of liquidity taken from the protocol (redeem or borrow) **/ function updateInterestRates( DataTypes.ReserveData storage reserve, address reserveAddress, address aTokenAddress, uint256 liquidityAdded, uint256 liquidityTaken ) internal { UpdateInterestRatesLocalVars memory vars; vars.stableDebtTokenAddress = reserve.stableDebtTokenAddress; (vars.totalStableDebt, vars.avgStableRate) = IStableDebtToken(vars.stableDebtTokenAddress) .getTotalSupplyAndAvgRate(); //calculates the total variable debt locally using the scaled total supply instead //of totalSupply(), as it's noticeably cheaper. Also, the index has been //updated by the previous updateState() call vars.totalVariableDebt = IVariableDebtToken(reserve.variableDebtTokenAddress) .scaledTotalSupply() .rayMul(reserve.variableBorrowIndex); ( vars.newLiquidityRate, vars.newStableRate, vars.newVariableRate ) = IReserveInterestRateStrategy(reserve.interestRateStrategyAddress).calculateInterestRates( reserveAddress, aTokenAddress, liquidityAdded, liquidityTaken, vars.totalStableDebt, vars.totalVariableDebt, vars.avgStableRate, reserve.configuration.getReserveFactor() ); require(vars.newLiquidityRate <= type(uint128).max, Errors.RL_LIQUIDITY_RATE_OVERFLOW); require(vars.newStableRate <= type(uint128).max, Errors.RL_STABLE_BORROW_RATE_OVERFLOW); require(vars.newVariableRate <= type(uint128).max, Errors.RL_VARIABLE_BORROW_RATE_OVERFLOW); reserve.currentLiquidityRate = uint128(vars.newLiquidityRate); reserve.currentStableBorrowRate = uint128(vars.newStableRate); reserve.currentVariableBorrowRate = uint128(vars.newVariableRate); emit ReserveDataUpdated( reserveAddress, vars.newLiquidityRate, vars.newStableRate, vars.newVariableRate, reserve.liquidityIndex, reserve.variableBorrowIndex ); } struct MintToTreasuryLocalVars { uint256 currentStableDebt; uint256 principalStableDebt; uint256 previousStableDebt; uint256 currentVariableDebt; uint256 previousVariableDebt; uint256 avgStableRate; uint256 cumulatedStableInterest; uint256 totalDebtAccrued; uint256 amountToMint; uint256 reserveFactor; uint40 stableSupplyUpdatedTimestamp; } /** * @dev Mints part of the repaid interest to the reserve treasury as a function of the reserveFactor for the * specific asset. * @param reserve The reserve reserve to be updated * @param scaledVariableDebt The current scaled total variable debt * @param previousVariableBorrowIndex The variable borrow index before the last accumulation of the interest * @param newLiquidityIndex The new liquidity index * @param newVariableBorrowIndex The variable borrow index after the last accumulation of the interest **/ function _mintToTreasury( DataTypes.ReserveData storage reserve, uint256 scaledVariableDebt, uint256 previousVariableBorrowIndex, uint256 newLiquidityIndex, uint256 newVariableBorrowIndex, uint40 timestamp ) internal { MintToTreasuryLocalVars memory vars; vars.reserveFactor = reserve.configuration.getReserveFactor(); if (vars.reserveFactor == 0) { return; } //fetching the principal, total stable debt and the avg stable rate ( vars.principalStableDebt, vars.currentStableDebt, vars.avgStableRate, vars.stableSupplyUpdatedTimestamp ) = IStableDebtToken(reserve.stableDebtTokenAddress).getSupplyData(); //calculate the last principal variable debt vars.previousVariableDebt = scaledVariableDebt.rayMul(previousVariableBorrowIndex); //calculate the new total supply after accumulation of the index vars.currentVariableDebt = scaledVariableDebt.rayMul(newVariableBorrowIndex); //calculate the stable debt until the last timestamp update vars.cumulatedStableInterest = MathUtils.calculateCompoundedInterest( vars.avgStableRate, vars.stableSupplyUpdatedTimestamp, timestamp ); vars.previousStableDebt = vars.principalStableDebt.rayMul(vars.cumulatedStableInterest); //debt accrued is the sum of the current debt minus the sum of the debt at the last update vars.totalDebtAccrued = vars .currentVariableDebt .add(vars.currentStableDebt) .sub(vars.previousVariableDebt) .sub(vars.previousStableDebt); vars.amountToMint = vars.totalDebtAccrued.percentMul(vars.reserveFactor); if (vars.amountToMint != 0) { IAToken(reserve.aTokenAddress).mintToTreasury(vars.amountToMint, newLiquidityIndex); } } /** * @dev Updates the reserve indexes and the timestamp of the update * @param reserve The reserve reserve to be updated * @param scaledVariableDebt The scaled variable debt * @param liquidityIndex The last stored liquidity index * @param variableBorrowIndex The last stored variable borrow index **/ function _updateIndexes( DataTypes.ReserveData storage reserve, uint256 scaledVariableDebt, uint256 liquidityIndex, uint256 variableBorrowIndex, uint40 timestamp ) internal returns (uint256, uint256) { uint256 currentLiquidityRate = reserve.currentLiquidityRate; uint256 newLiquidityIndex = liquidityIndex; uint256 newVariableBorrowIndex = variableBorrowIndex; //only cumulating if there is any income being produced if (currentLiquidityRate > 0) { uint256 cumulatedLiquidityInterest = MathUtils.calculateLinearInterest(currentLiquidityRate, timestamp); newLiquidityIndex = cumulatedLiquidityInterest.rayMul(liquidityIndex); require(newLiquidityIndex <= type(uint128).max, Errors.RL_LIQUIDITY_INDEX_OVERFLOW); reserve.liquidityIndex = uint128(newLiquidityIndex); //as the liquidity rate might come only from stable rate loans, we need to ensure //that there is actual variable debt before accumulating if (scaledVariableDebt != 0) { uint256 cumulatedVariableBorrowInterest = MathUtils.calculateCompoundedInterest(reserve.currentVariableBorrowRate, timestamp); newVariableBorrowIndex = cumulatedVariableBorrowInterest.rayMul(variableBorrowIndex); require( newVariableBorrowIndex <= type(uint128).max, Errors.RL_VARIABLE_BORROW_INDEX_OVERFLOW ); reserve.variableBorrowIndex = uint128(newVariableBorrowIndex); } } //solium-disable-next-line reserve.lastUpdateTimestamp = uint40(block.timestamp); return (newLiquidityIndex, newVariableBorrowIndex); } }
Contract ABI
[{"type":"event","name":"ReserveDataUpdated","inputs":[{"type":"address","name":"asset","internalType":"address","indexed":true},{"type":"uint256","name":"liquidityRate","internalType":"uint256","indexed":false},{"type":"uint256","name":"stableBorrowRate","internalType":"uint256","indexed":false},{"type":"uint256","name":"variableBorrowRate","internalType":"uint256","indexed":false},{"type":"uint256","name":"liquidityIndex","internalType":"uint256","indexed":false},{"type":"uint256","name":"variableBorrowIndex","internalType":"uint256","indexed":false}],"anonymous":false}]
Contract Creation Code
0x61023b610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c80632b33897c1461003a575b600080fd5b81801561004657600080fd5b5061008b600480360360a081101561005d57600080fd5b508035906001600160a01b03602082013581169160408101358216916060820135811691608001351661008d565b005b6004850154604080518082019091526002815261199960f11b6020820152906001600160a01b03161561013e5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156101035781810151838201526020016100eb565b50505050905090810190601f1680156101305780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506101476101f5565b6001860180546fffffffffffffffffffffffffffffffff19166001600160801b039290921691909117905561017a6101f5565b6001860180546001600160801b03928316600160801b0292169190911790556004850180546001600160a01b039586166001600160a01b031991821617909155600586018054948616948216949094179093556006850180549285169284169290921790915560079093018054939092169216919091179055565b6b033b2e3c9fd0803ce80000009056fea2646970667358221220f14cc361cfc8eee2aaa4125020a370f5f2f95cfd07715d513fa721499ae0f00e64736f6c634300060c0033
Deployed ByteCode
0x738e6779f2ac23f196ef9a6b446e557a6f81fd4f5130146080604052600436106100355760003560e01c80632b33897c1461003a575b600080fd5b81801561004657600080fd5b5061008b600480360360a081101561005d57600080fd5b508035906001600160a01b03602082013581169160408101358216916060820135811691608001351661008d565b005b6004850154604080518082019091526002815261199960f11b6020820152906001600160a01b03161561013e5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156101035781810151838201526020016100eb565b50505050905090810190601f1680156101305780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506101476101f5565b6001860180546fffffffffffffffffffffffffffffffff19166001600160801b039290921691909117905561017a6101f5565b6001860180546001600160801b03928316600160801b0292169190911790556004850180546001600160a01b039586166001600160a01b031991821617909155600586018054948616948216949094179093556006850180549285169284169290921790915560079093018054939092169216919091179055565b6b033b2e3c9fd0803ce80000009056fea2646970667358221220f14cc361cfc8eee2aaa4125020a370f5f2f95cfd07715d513fa721499ae0f00e64736f6c634300060c0033