// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; import {Errors} from '../helpers/Errors.sol'; import {DataTypes} from '../types/DataTypes.sol'; /** * @title ReserveConfiguration library * @author Aave * @notice Implements the bitmap logic to handle the reserve configuration */ library ReserveConfiguration { uint256 constant LTV_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000; // prettier-ignore uint256 constant LIQUIDATION_THRESHOLD_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF; // prettier-ignore uint256 constant LIQUIDATION_BONUS_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF; // prettier-ignore uint256 constant DECIMALS_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFF; // prettier-ignore uint256 constant ACTIVE_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFF; // prettier-ignore uint256 constant FROZEN_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFF; // prettier-ignore uint256 constant BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFF; // prettier-ignore uint256 constant STABLE_BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFF; // prettier-ignore uint256 constant RESERVE_FACTOR_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF; // prettier-ignore /// @dev For the LTV, the start bit is 0 (up to 15), but we don't declare it as for 0 no bit movement is needed uint256 constant LIQUIDATION_THRESHOLD_START_BIT_POSITION = 16; uint256 constant LIQUIDATION_BONUS_START_BIT_POSITION = 32; uint256 constant RESERVE_DECIMALS_START_BIT_POSITION = 48; uint256 constant IS_ACTIVE_START_BIT_POSITION = 56; uint256 constant IS_FROZEN_START_BIT_POSITION = 57; uint256 constant BORROWING_ENABLED_START_BIT_POSITION = 58; uint256 constant STABLE_BORROWING_ENABLED_START_BIT_POSITION = 59; uint256 constant RESERVE_FACTOR_START_BIT_POSITION = 64; uint256 constant MAX_VALID_LTV = 65535; uint256 constant MAX_VALID_LIQUIDATION_THRESHOLD = 65535; uint256 constant MAX_VALID_LIQUIDATION_BONUS = 65535; uint256 constant MAX_VALID_DECIMALS = 255; uint256 constant MAX_VALID_RESERVE_FACTOR = 65535; /** * @dev sets the Loan to Value of the reserve * @param self the reserve configuration * @param ltv the new ltv **/ function setLtv(DataTypes.ReserveBitmap memory self, uint256 ltv) internal pure { require(ltv <= MAX_VALID_LTV, Errors.RC_INVALID_LTV); self.data = (self.data & LTV_MASK) | ltv; } /** * @dev gets the Loan to Value of the reserve * @param self the reserve configuration * @return the loan to value **/ function getLtv(DataTypes.ReserveBitmap storage self) internal view returns (uint256) { return self.data & ~LTV_MASK; } /** * @dev sets the liquidation threshold of the reserve * @param self the reserve configuration * @param threshold the new liquidation threshold **/ function setLiquidationThreshold(DataTypes.ReserveBitmap memory self, uint256 threshold) internal pure { require(threshold <= MAX_VALID_LIQUIDATION_THRESHOLD, Errors.RC_INVALID_LIQ_THRESHOLD); self.data = (self.data & LIQUIDATION_THRESHOLD_MASK) | (threshold << LIQUIDATION_THRESHOLD_START_BIT_POSITION); } /** * @dev gets the liquidation threshold of the reserve * @param self the reserve configuration * @return the liquidation threshold **/ function getLiquidationThreshold(DataTypes.ReserveBitmap storage self) internal view returns (uint256) { return (self.data & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION; } /** * @dev sets the liquidation bonus of the reserve * @param self the reserve configuration * @param bonus the new liquidation bonus **/ function setLiquidationBonus(DataTypes.ReserveBitmap memory self, uint256 bonus) internal pure { require(bonus <= MAX_VALID_LIQUIDATION_BONUS, Errors.RC_INVALID_LIQ_BONUS); self.data = (self.data & LIQUIDATION_BONUS_MASK) | (bonus << LIQUIDATION_BONUS_START_BIT_POSITION); } /** * @dev gets the liquidation bonus of the reserve * @param self the reserve configuration * @return the liquidation bonus **/ function getLiquidationBonus(DataTypes.ReserveBitmap storage self) internal view returns (uint256) { return (self.data & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION; } /** * @dev sets the decimals of the underlying asset of the reserve * @param self the reserve configuration * @param decimals the decimals **/ function setDecimals(DataTypes.ReserveBitmap memory self, uint256 decimals) internal pure { require(decimals <= MAX_VALID_DECIMALS, Errors.RC_INVALID_DECIMALS); self.data = (self.data & DECIMALS_MASK) | (decimals << RESERVE_DECIMALS_START_BIT_POSITION); } /** * @dev gets the decimals of the underlying asset of the reserve * @param self the reserve configuration * @return the decimals of the asset **/ function getDecimals(DataTypes.ReserveBitmap storage self) internal view returns (uint256) { return (self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION; } /** * @dev sets the active state of the reserve * @param self the reserve configuration * @param active the active state **/ function setActive(DataTypes.ReserveBitmap memory self, bool active) internal pure { self.data = (self.data & ACTIVE_MASK) | (uint256(active ? 1 : 0) << IS_ACTIVE_START_BIT_POSITION); } /** * @dev gets the active state of the reserve * @param self the reserve configuration * @return the active state **/ function getActive(DataTypes.ReserveBitmap storage self) internal view returns (bool) { return (self.data & ~ACTIVE_MASK) != 0; } /** * @dev sets the frozen state of the reserve * @param self the reserve configuration * @param frozen the frozen state **/ function setFrozen(DataTypes.ReserveBitmap memory self, bool frozen) internal pure { self.data = (self.data & FROZEN_MASK) | (uint256(frozen ? 1 : 0) << IS_FROZEN_START_BIT_POSITION); } /** * @dev gets the frozen state of the reserve * @param self the reserve configuration * @return the frozen state **/ function getFrozen(DataTypes.ReserveBitmap storage self) internal view returns (bool) { return (self.data & ~FROZEN_MASK) != 0; } /** * @dev enables or disables borrowing on the reserve * @param self the reserve configuration * @param enabled true if the borrowing needs to be enabled, false otherwise **/ function setBorrowingEnabled(DataTypes.ReserveBitmap memory self, bool enabled) internal pure { self.data = (self.data & BORROWING_MASK) | (uint256(enabled ? 1 : 0) << BORROWING_ENABLED_START_BIT_POSITION); } /** * @dev gets the borrowing state of the reserve * @param self the reserve configuration * @return the borrowing state **/ function getBorrowingEnabled(DataTypes.ReserveBitmap storage self) internal view returns (bool) { return (self.data & ~BORROWING_MASK) != 0; } /** * @dev enables or disables stable rate borrowing on the reserve * @param self the reserve configuration * @param enabled true if the stable rate borrowing needs to be enabled, false otherwise **/ function setStableRateBorrowingEnabled(DataTypes.ReserveBitmap memory self, bool enabled) internal pure { self.data = (self.data & STABLE_BORROWING_MASK) | (uint256(enabled ? 1 : 0) << STABLE_BORROWING_ENABLED_START_BIT_POSITION); } /** * @dev gets the stable rate borrowing state of the reserve * @param self the reserve configuration * @return the stable rate borrowing state **/ function getStableRateBorrowingEnabled(DataTypes.ReserveBitmap storage self) internal view returns (bool) { return (self.data & ~STABLE_BORROWING_MASK) != 0; } /** * @dev sets the reserve factor of the reserve * @param self the reserve configuration * @param reserveFactor the reserve factor **/ function setReserveFactor(DataTypes.ReserveBitmap memory self, uint256 reserveFactor) internal pure { require(reserveFactor <= MAX_VALID_RESERVE_FACTOR, Errors.RC_INVALID_RESERVE_FACTOR); self.data = (self.data & RESERVE_FACTOR_MASK) | (reserveFactor << RESERVE_FACTOR_START_BIT_POSITION); } /** * @dev gets the reserve factor of the reserve * @param self the reserve configuration * @return the reserve factor **/ function getReserveFactor(DataTypes.ReserveBitmap storage self) internal view returns (uint256) { return (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION; } /** * @dev gets the configuration flags of the reserve * @param self the reserve configuration * @return the state flags representing active, frozen, borrowing enabled, stableRateBorrowing enabled **/ function getFlags(DataTypes.ReserveBitmap storage self) internal view returns ( bool, bool, bool, bool ) { uint256 dataLocal = self.data; return ( (dataLocal & ~ACTIVE_MASK) != 0, (dataLocal & ~FROZEN_MASK) != 0, (dataLocal & ~BORROWING_MASK) != 0, (dataLocal & ~STABLE_BORROWING_MASK) != 0 ); } /** * @dev gets the configuration paramters of the reserve * @param self the reserve configuration * @return the state params representing ltv, liquidation threshold, liquidation bonus, the reserve decimals **/ function getParams(DataTypes.ReserveBitmap storage self) internal view returns ( uint256, uint256, uint256, uint256, uint256 ) { uint256 dataLocal = self.data; return ( dataLocal & ~LTV_MASK, (dataLocal & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION, (dataLocal & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION, (dataLocal & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION, (dataLocal & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION ); } /** * @dev gets the configuration paramters of the reserve from a memory object * @param self the reserve configuration * @return the state params representing ltv, liquidation threshold, liquidation bonus, the reserve decimals **/ function getParamsMemory(DataTypes.ReserveBitmap memory self) internal pure returns ( uint256, uint256, uint256, uint256, uint256 ) { return ( self.data & ~LTV_MASK, (self.data & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION, (self.data & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION, (self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION, (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION ); } /** * @dev gets the configuration flags of the reserve from a memory object * @param self the reserve configuration * @return the state flags representing active, frozen, borrowing enabled, stableRateBorrowing enabled **/ function getFlagsMemory(DataTypes.ReserveBitmap memory self) internal pure returns ( bool, bool, bool, bool ) { return ( (self.data & ~ACTIVE_MASK) != 0, (self.data & ~FROZEN_MASK) != 0, (self.data & ~BORROWING_MASK) != 0, (self.data & ~STABLE_BORROWING_MASK) != 0 ); } }