// SPDX-License-Identifier: agpl-3.0 pragma solidity 0.6.12; import {Errors} from '../helpers/Errors.sol'; import {DataTypes} from '../types/DataTypes.sol'; /** * @title UserConfiguration library * @author Aave * @notice Implements the bitmap logic to handle the user configuration */ library UserConfiguration { uint256 internal constant BORROWING_MASK = 0x5555555555555555555555555555555555555555555555555555555555555555; uint256 internal constant _maxReserves = 256; uint256 internal constant _indexCount = _maxReserves / 128 + ((_maxReserves % 128 > 0) ? 1 : 0); /** * @dev Sets if the user is borrowing the reserve identified by reserveIndex * @param self The configuration object * @param reserveIndex The index of the reserve in the bitmap * @param borrowing True if the user is borrowing the reserve, false otherwise **/ function setBorrowing( DataTypes.UserConfigurationMap storage self, uint256 reserveIndex, bool borrowing ) internal { require(reserveIndex < _maxReserves, Errors.UL_INVALID_INDEX); uint256 index = reserveIndex / 128; reserveIndex = reserveIndex % 128; self.data[index] = (self.data[index] & ~(1 << (reserveIndex * 2))) | (uint256(borrowing ? 1 : 0) << (reserveIndex * 2)); } /** * @dev Sets if the user is using as collateral the reserve identified by reserveIndex * @param self The configuration object * @param reserveIndex The index of the reserve in the bitmap * @param usingAsCollateral True if the user is usin the reserve as collateral, false otherwise **/ function setUsingAsCollateral( DataTypes.UserConfigurationMap storage self, uint256 reserveIndex, bool usingAsCollateral ) internal { require(reserveIndex < _maxReserves, Errors.UL_INVALID_INDEX); uint256 index = reserveIndex / 128; reserveIndex = reserveIndex % 128; self.data[index] = (self.data[index] & ~(1 << (reserveIndex * 2 + 1))) | (uint256(usingAsCollateral ? 1 : 0) << (reserveIndex * 2 + 1)); } /** * @dev Used to validate if a user has been using the reserve for borrowing or as collateral * @param self The configuration object * @param reserveIndex The index of the reserve in the bitmap * @return True if the user has been using a reserve for borrowing or as collateral, false otherwise **/ function isUsingAsCollateralOrBorrowing( DataTypes.UserConfigurationMap memory self, uint256 reserveIndex ) internal pure returns (bool) { require(reserveIndex < _maxReserves, Errors.UL_INVALID_INDEX); uint256 index = reserveIndex / 128; reserveIndex = reserveIndex % 128; return (self.data[index] >> (reserveIndex * 2)) & 3 != 0; } /** * @dev Used to validate if a user has been using the reserve for borrowing * @param self The configuration object * @param reserveIndex The index of the reserve in the bitmap * @return True if the user has been using a reserve for borrowing, false otherwise **/ function isBorrowing(DataTypes.UserConfigurationMap memory self, uint256 reserveIndex) internal pure returns (bool) { require(reserveIndex < _maxReserves, Errors.UL_INVALID_INDEX); uint256 index = reserveIndex / 128; reserveIndex = reserveIndex % 128; return (self.data[index] >> (reserveIndex * 2)) & 1 != 0; } /** * @dev Used to validate if a user has been using the reserve as collateral * @param self The configuration object * @param reserveIndex The index of the reserve in the bitmap * @return True if the user has been using a reserve as collateral, false otherwise **/ function isUsingAsCollateral(DataTypes.UserConfigurationMap memory self, uint256 reserveIndex) internal pure returns (bool) { require(reserveIndex < _maxReserves, Errors.UL_INVALID_INDEX); uint256 index = reserveIndex / 128; reserveIndex = reserveIndex % 128; return (self.data[index] >> (reserveIndex * 2 + 1)) & 1 != 0; } /** * @dev Used to validate if a user has been borrowing from any reserve * @param self The configuration object * @return True if the user has been borrowing any reserve, false otherwise **/ function isBorrowingAny(DataTypes.UserConfigurationMap memory self) internal pure returns (bool) { for (uint8 i = 0; i < _indexCount; i++) { if (self.data[i] & BORROWING_MASK != 0) { return true; } } return false; } /** * @dev Used to validate if a user has not been using any reserve * @param self The configuration object * @return True if the user has been borrowing any reserve, false otherwise **/ function isEmpty(DataTypes.UserConfigurationMap memory self) internal pure returns (bool) { for (uint8 i = 0; i < _indexCount; i++) { if (self.data[i] != 0) { return false; } } return true; } }