From 2b883e4f4318dea02d83e8730e04098e95aab9af Mon Sep 17 00:00:00 2001 From: Lasse Herskind <16536249+LHerskind@users.noreply.github.com> Date: Wed, 24 Nov 2021 10:18:22 +0000 Subject: [PATCH] fix: Adapt code to support >128 reserves --- .../protocol/lendingpool/LendingPool.sol | 4 +- .../configuration/UserConfiguration.sol | 51 ++++++++++++++----- .../protocol/libraries/types/DataTypes.sol | 2 +- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/contracts/protocol/lendingpool/LendingPool.sol b/contracts/protocol/lendingpool/LendingPool.sol index 8e38650c..304fa3a6 100644 --- a/contracts/protocol/lendingpool/LendingPool.sol +++ b/contracts/protocol/lendingpool/LendingPool.sol @@ -87,7 +87,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage _addressesProvider = provider; _maxStableRateBorrowSizePercent = 2500; _flashLoanPremiumTotal = 9; - _maxNumberOfReserves = 128; + _maxNumberOfReserves = UserConfiguration._maxReserves; } /** @@ -713,7 +713,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage } /** - * @dev Returns the fee on flash loans + * @dev Returns the fee on flash loans */ function FLASHLOAN_PREMIUM_TOTAL() public view returns (uint256) { return _flashLoanPremiumTotal; diff --git a/contracts/protocol/libraries/configuration/UserConfiguration.sol b/contracts/protocol/libraries/configuration/UserConfiguration.sol index 2994f05d..fed8ffda 100644 --- a/contracts/protocol/libraries/configuration/UserConfiguration.sol +++ b/contracts/protocol/libraries/configuration/UserConfiguration.sol @@ -13,6 +13,9 @@ 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 @@ -24,9 +27,11 @@ library UserConfiguration { uint256 reserveIndex, bool borrowing ) internal { - require(reserveIndex < 128, Errors.UL_INVALID_INDEX); - self.data = - (self.data & ~(1 << (reserveIndex * 2))) | + 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)); } @@ -41,9 +46,11 @@ library UserConfiguration { uint256 reserveIndex, bool usingAsCollateral ) internal { - require(reserveIndex < 128, Errors.UL_INVALID_INDEX); - self.data = - (self.data & ~(1 << (reserveIndex * 2 + 1))) | + 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)); } @@ -57,8 +64,10 @@ library UserConfiguration { DataTypes.UserConfigurationMap memory self, uint256 reserveIndex ) internal pure returns (bool) { - require(reserveIndex < 128, Errors.UL_INVALID_INDEX); - return (self.data >> (reserveIndex * 2)) & 3 != 0; + require(reserveIndex < _maxReserves, Errors.UL_INVALID_INDEX); + uint256 index = reserveIndex / 128; + reserveIndex = reserveIndex % 128; + return (self.data[index] >> (reserveIndex * 2)) & 3 != 0; } /** @@ -72,8 +81,10 @@ library UserConfiguration { pure returns (bool) { - require(reserveIndex < 128, Errors.UL_INVALID_INDEX); - return (self.data >> (reserveIndex * 2)) & 1 != 0; + require(reserveIndex < _maxReserves, Errors.UL_INVALID_INDEX); + uint256 index = reserveIndex / 128; + reserveIndex = reserveIndex % 128; + return (self.data[index] >> (reserveIndex * 2)) & 1 != 0; } /** @@ -87,8 +98,10 @@ library UserConfiguration { pure returns (bool) { - require(reserveIndex < 128, Errors.UL_INVALID_INDEX); - return (self.data >> (reserveIndex * 2 + 1)) & 1 != 0; + require(reserveIndex < _maxReserves, Errors.UL_INVALID_INDEX); + uint256 index = reserveIndex / 128; + reserveIndex = reserveIndex % 128; + return (self.data[index] >> (reserveIndex * 2 + 1)) & 1 != 0; } /** @@ -97,7 +110,12 @@ library UserConfiguration { * @return True if the user has been borrowing any reserve, false otherwise **/ function isBorrowingAny(DataTypes.UserConfigurationMap memory self) internal pure returns (bool) { - return self.data & BORROWING_MASK != 0; + for (uint8 i = 0; i < _indexCount; i++) { + if (self.data[i] & BORROWING_MASK != 0) { + return true; + } + } + return false; } /** @@ -106,6 +124,11 @@ library UserConfiguration { * @return True if the user has been borrowing any reserve, false otherwise **/ function isEmpty(DataTypes.UserConfigurationMap memory self) internal pure returns (bool) { - return self.data == 0; + for (uint8 i = 0; i < _indexCount; i++) { + if (self.data[i] != 0) { + return false; + } + } + return true; } } diff --git a/contracts/protocol/libraries/types/DataTypes.sol b/contracts/protocol/libraries/types/DataTypes.sol index a19e5efc..b3b76b15 100644 --- a/contracts/protocol/libraries/types/DataTypes.sol +++ b/contracts/protocol/libraries/types/DataTypes.sol @@ -42,7 +42,7 @@ library DataTypes { } struct UserConfigurationMap { - uint256 data; + uint256[2] data; // size is _maxReserves / 128 + ((_maxReserves % 128 > 0) ? 1 : 0), but need to be literal } enum InterestRateMode {NONE, STABLE, VARIABLE}