aave-protocol-v2/contracts/protocol/libraries/configuration/UserConfiguration.sol
2021-11-24 10:18:22 +00:00

135 lines
4.8 KiB
Solidity

// 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;
}
}