.cache

TLDR

The cache function creates a cached copy of struct ReservesData in memory, as reserveCache to avoid repeated calls to storage which are expensive.

Essentially, reserveCache will serve as the working copy within which data will be modified and updated through the course of execution.

  • Caches ReserveData into ReserveCache struct

  • ReserveData exists in storage, ReserveCache exist in memory

  • Read/Write calls to memory are cheaper than storage

ReserveData (DataTypes.sol)
  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;
    //the current stable borrow rate. Expressed in ray
    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;
    //stableDebtToken address
    address stableDebtTokenAddress;
    //variableDebtToken address
    address variableDebtTokenAddress;
    //address of the interest rate strategy
    address interestRateStrategyAddress;
    //the current treasury balance, scaled
    uint128 accruedToTreasury;
    //the outstanding unbacked aTokens minted through the bridging feature
    uint128 unbacked;
    //the outstanding debt borrowed against this asset in isolation mode
    uint128 isolationModeTotalDebt;
  }
ReserveCache (DataTypes.sol)

  • Each reserve (asset) in Aave has its own unique configuration, rates, indexes, and token contracts (aToken and other debt tokens).

  • For each reserve, this data is captured within a struct ReserveData. These structs are accessed via the mapping _reserves, which maps the asset address to its corresponding ReserveData.

  • _reserves is defined on PoolStorage.sol which is inherited by Pool.sol

PoolStorage.sol
// Map of reserves and their data (underlyingAssetOfReserve => reserveData)
  mapping(address => DataTypes.ReserveData) internal _reserves;

Caching reserve into reserveCache

.cache serves to map the data held within reserve onto reserveCache, by unpacking and through some calculations.

reserveData -> reserveCache
// reservesData is PoolStorage::_reserves
DataTypes.ReserveData storage reserve = reservesData[params.asset];
DataTypes.ReserveCache memory reserveCache = reserve.cache();

ReserveData variables NOT cached:

  • id

  • aTokenAddress

  • interestRateStrategyAddress

  • accruedToTreasury

  • unbacked

  • isolationModeTotalDebt

Code

1. Get ReserveConfigurationMap reserveConfiguration

reserveCache.reserveConfiguration = reserve.configuration;
  • simply copies reserveConfigurationMap from storage to memory

2. Get reserveFactor

The value of reserveFactor is obtained by passing reserveConfiguration, obtained earlier, into function getReserveFactor.

reserveCache.reserveFactor = reserveCache.reserveConfiguration.getReserveFactor();

The reserveFactor, amongst other data, is stored within ReserveConfigurationMap, which is a bitmap. See getReserveFactor for in-depth explanation.

The reserve factor is a percentage of protocol interest which goes to the Aave Ecosystem Reserve. The rest of the borrow interest goes to the suppliers.

3 - 4. Get indexes: current and next

  1. currLiquidityIndex and nextLiquidityIndex

reserveCache.currLiquidityIndex = reserveCache.nextLiquidityIndex = reserve.liquidityIndex;
  1. currVariableBorrowIndex and nextVariableBorrowIndex

reserveCache.currVariableBorrowIndex = reserveCache.nextVariableBorrowIndex 
= reserve.variableBorrowIndex;
  • reserve.liquidityIndex is the value of the supply index, as per the last time updateState was ran previously. Similarly, reserve.variableBorrowIndex.

  • nextLiquidityIndex and nextVariableBorrowIndex will be updated in updateState, to reflect interest accruel till current block.timestamp.

Having both next and current indexes allows us to compare interest deltas and the like.

5 - 6. Get rates: currLiquidityRate & currVariableBorrowRate

reserveCache.currLiquidityRate = reserve.currentLiquidityRate;
reserveCache.currVariableBorrowRate = reserve.currentVariableBorrowRate;
  • currentLiquidityRate: current supply rate

  • currentVariableBorrowRate: current variable borrow rate

Both reserve.currentLiquidityRate and reserve.currentVariableBorrowRate are updated each time .updateInterestRates is executed.

7-10. Token Addresses

    reserveCache.aTokenAddress = reserve.aTokenAddress;
    reserveCache.stableDebtTokenAddress = reserve.stableDebtTokenAddress;
    reserveCache.variableDebtTokenAddress = reserve.variableDebtTokenAddress;

    reserveCache.reserveLastUpdateTimestamp = reserve.lastUpdateTimestamp;

Values are obtained as follows:

ReserveData
ReserveCache

aTokenAddress

aTokenAddress

stableDebtTokenAddress

stableDebtTokenAddress

variableDebtTokenAddress

variableDebtTokenAddress

lastUpdateTimeStamp

reserveLastUpdateTimeStamp

reserve.lastUpdateTimestamp is updated each time .updateState is executed.

11. Get currScaledVariableDebt & nextScaledVariableDebt

reserveCache.currScaledVariableDebt = reserveCache.nextScaledVariableDebt = IVariableDebtToken(reserveCache.variableDebtTokenAddress).scaledTotalSupply();
  • returns scaled variable debt

  • actual variable debt can be obtained by: scaledBalance * variableBorrowIndex

12. Get currPrincipalStableDebt, currAvgStableBorrowRate, currTotalStableDebt

    (
      reserveCache.currPrincipalStableDebt,
      reserveCache.currTotalStableDebt,
      reserveCache.currAvgStableBorrowRate,
      reserveCache.stableDebtLastUpdateTimestamp
    ) = IStableDebtToken(reserveCache.stableDebtTokenAddress).getSupplyData();
getSupplyData()

currPrincipalStableDebt = super.totalSupply() = _totalSupply

  • Reflects total stable debt, accounting for interest accrued from inception till _totalSupplyTimestamp.

  • Does not account for interest accrued from _totalSupplyTimestamp to now.

currTotalStableDebt = _calcTotalSupply(avgRate)

  • Calculates total stable debt, accounting for interest accrued to date.

currAvgStableBorrowRate = _avgStableRate

  • weighted global average rate, calculated across all stable borrows

stableDebtLastUpdateTimestamp = _totalSupplyTimestamp

  • Timestamp of the last update of _totalSupply

See getSupplyData for detailed explanations

13. Get nextAvgStableBorrowRate, nextTotalStableDebt

reserveCache.nextTotalStableDebt = reserveCache.currTotalStableDebt;
reserveCache.nextAvgStableBorrowRate = reserveCache.currAvgStableBorrowRate;

Last updated

Was this helpful?