From 41a2e9f7f2adf6456eee6f2b2a654ae84186bbab Mon Sep 17 00:00:00 2001 From: Quentin Garchery Date: Mon, 14 Nov 2022 00:00:03 +0100 Subject: [PATCH 1/5] feat: modify storage to show inverted rates --- test-foundry/aave-v2/TestRatesLens.t.sol | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/test-foundry/aave-v2/TestRatesLens.t.sol b/test-foundry/aave-v2/TestRatesLens.t.sol index 7f50dc471..ae351b61d 100644 --- a/test-foundry/aave-v2/TestRatesLens.t.sol +++ b/test-foundry/aave-v2/TestRatesLens.t.sol @@ -1029,7 +1029,7 @@ contract TestRatesLens is TestSetup { borrower1.borrow(aDai, 1 ether); // Invert spreads on DAI. - (uint256 poolSupplyRate, uint256 poolBorrowRate) = _invertSpreadOnDai(); + (, uint256 poolBorrowRate) = _invertSpreadOnDai2(); (uint256 avgSupplyRate, , ) = lens.getAverageSupplyRatePerYear(aDai); (uint256 avgBorrowRate, , ) = lens.getAverageBorrowRatePerYear(aDai); @@ -1113,4 +1113,13 @@ contract TestRatesLens is TestSetup { // Rates must be inverted. assertGt(poolSupplyRate, poolBorrowRate); } + + function _invertSpreadOnDai2() public returns (uint256 poolSupplyRate, uint256 poolBorrowRate) { + DataTypes.ReserveData memory reserve = pool.getReserveData(dai); + poolSupplyRate = reserve.currentLiquidityRate; + poolBorrowRate = poolSupplyRate / 2; + uint256 newRate = (poolBorrowRate << 128) | poolSupplyRate; + bytes32 rateSlot = bytes32(uint256(keccak256(abi.encode(address(dai), 53))) + uint256(2)); + vm.store(address(pool), rateSlot, bytes32(newRate)); + } } From 82ae690f02df9d52b07b638972b121f024dcb071 Mon Sep 17 00:00:00 2001 From: Quentin Garchery Date: Mon, 14 Nov 2022 00:14:23 +0100 Subject: [PATCH 2/5] refactor: use first inversion of rates, more comments --- test-foundry/aave-v2/TestRatesLens.t.sol | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test-foundry/aave-v2/TestRatesLens.t.sol b/test-foundry/aave-v2/TestRatesLens.t.sol index ae351b61d..87624e470 100644 --- a/test-foundry/aave-v2/TestRatesLens.t.sol +++ b/test-foundry/aave-v2/TestRatesLens.t.sol @@ -1029,7 +1029,7 @@ contract TestRatesLens is TestSetup { borrower1.borrow(aDai, 1 ether); // Invert spreads on DAI. - (, uint256 poolBorrowRate) = _invertSpreadOnDai2(); + (, uint256 poolBorrowRate) = _invertSpreadOnDai(); (uint256 avgSupplyRate, , ) = lens.getAverageSupplyRatePerYear(aDai); (uint256 avgBorrowRate, , ) = lens.getAverageBorrowRatePerYear(aDai); @@ -1117,9 +1117,16 @@ contract TestRatesLens is TestSetup { function _invertSpreadOnDai2() public returns (uint256 poolSupplyRate, uint256 poolBorrowRate) { DataTypes.ReserveData memory reserve = pool.getReserveData(dai); poolSupplyRate = reserve.currentLiquidityRate; + // Make the borrow rate less than the supply rate poolBorrowRate = poolSupplyRate / 2; uint256 newRate = (poolBorrowRate << 128) | poolSupplyRate; + // Slot of the mapping _reserves is 53 to take into account 52 storage slots of VersionedInitializable plus the ILendingPoolAddressesProvider slot. + // Offset in the ReserveData struct is 2. bytes32 rateSlot = bytes32(uint256(keccak256(abi.encode(address(dai), 53))) + uint256(2)); vm.store(address(pool), rateSlot, bytes32(newRate)); + + reserve = pool.getReserveData(dai); + // Rates must be inverted. + assertGt(reserve.currentLiquidityRate, reserve.currentVariableBorrowRate); } } From 710a54e7f75d8c5a0c925203b5bb547db9fcd5ee Mon Sep 17 00:00:00 2001 From: Quentin Garchery Date: Mon, 14 Nov 2022 09:23:58 +0100 Subject: [PATCH 3/5] refactor: invert spread 2 refactor --- test-foundry/aave-v2/TestRatesLens.t.sol | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test-foundry/aave-v2/TestRatesLens.t.sol b/test-foundry/aave-v2/TestRatesLens.t.sol index 87624e470..54b1f43bc 100644 --- a/test-foundry/aave-v2/TestRatesLens.t.sol +++ b/test-foundry/aave-v2/TestRatesLens.t.sol @@ -1114,10 +1114,12 @@ contract TestRatesLens is TestSetup { assertGt(poolSupplyRate, poolBorrowRate); } - function _invertSpreadOnDai2() public returns (uint256 poolSupplyRate, uint256 poolBorrowRate) { - DataTypes.ReserveData memory reserve = pool.getReserveData(dai); - poolSupplyRate = reserve.currentLiquidityRate; - // Make the borrow rate less than the supply rate + function _invertSpreadOnDaiWithStorageManipulation() + public + returns (uint256 poolSupplyRate, uint256 poolBorrowRate) + { + poolSupplyRate = pool.getReserveData(dai).currentLiquidityRate; + // Make the borrow rate less than the supply rate. poolBorrowRate = poolSupplyRate / 2; uint256 newRate = (poolBorrowRate << 128) | poolSupplyRate; // Slot of the mapping _reserves is 53 to take into account 52 storage slots of VersionedInitializable plus the ILendingPoolAddressesProvider slot. @@ -1125,8 +1127,8 @@ contract TestRatesLens is TestSetup { bytes32 rateSlot = bytes32(uint256(keccak256(abi.encode(address(dai), 53))) + uint256(2)); vm.store(address(pool), rateSlot, bytes32(newRate)); - reserve = pool.getReserveData(dai); // Rates must be inverted. + DataTypes.ReserveData memory reserve = pool.getReserveData(dai); assertGt(reserve.currentLiquidityRate, reserve.currentVariableBorrowRate); } } From 511b51a3769fd00c8bd714879d4129b4ceef4f9c Mon Sep 17 00:00:00 2001 From: Quentin Garchery Date: Mon, 14 Nov 2022 09:30:00 +0100 Subject: [PATCH 4/5] refactor: make old and new rates cleaner --- test-foundry/aave-v2/TestRatesLens.t.sol | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/test-foundry/aave-v2/TestRatesLens.t.sol b/test-foundry/aave-v2/TestRatesLens.t.sol index 54b1f43bc..1db444bf2 100644 --- a/test-foundry/aave-v2/TestRatesLens.t.sol +++ b/test-foundry/aave-v2/TestRatesLens.t.sol @@ -1118,17 +1118,21 @@ contract TestRatesLens is TestSetup { public returns (uint256 poolSupplyRate, uint256 poolBorrowRate) { - poolSupplyRate = pool.getReserveData(dai).currentLiquidityRate; + // Keep the current supply rate. + uint256 newPoolSupplyRate = pool.getReserveData(dai).currentLiquidityRate; // Make the borrow rate less than the supply rate. - poolBorrowRate = poolSupplyRate / 2; - uint256 newRate = (poolBorrowRate << 128) | poolSupplyRate; + uint256 newPoolBorrowRate = newPoolSupplyRate / 2; + // Rates are packed in the _reserves struct. + uint256 newRates = (newPoolBorrowRate << 128) | newPoolSupplyRate; // Slot of the mapping _reserves is 53 to take into account 52 storage slots of VersionedInitializable plus the ILendingPoolAddressesProvider slot. // Offset in the ReserveData struct is 2. bytes32 rateSlot = bytes32(uint256(keccak256(abi.encode(address(dai), 53))) + uint256(2)); - vm.store(address(pool), rateSlot, bytes32(newRate)); + vm.store(address(pool), rateSlot, bytes32(newRates)); - // Rates must be inverted. DataTypes.ReserveData memory reserve = pool.getReserveData(dai); - assertGt(reserve.currentLiquidityRate, reserve.currentVariableBorrowRate); + poolSupplyRate = reserve.currentLiquidityRate; + poolBorrowRate = reserve.currentVariableBorrowRate; + // Rates must be inverted. + assertGt(poolSupplyRate, poolBorrowRate); } } From b7109319d6d447f7d95ace667a7f832bea6b82fc Mon Sep 17 00:00:00 2001 From: Quentin Garchery Date: Mon, 14 Nov 2022 15:54:41 +0100 Subject: [PATCH 5/5] Update test-foundry/aave-v2/TestRatesLens.t.sol Co-authored-by: Romain Milon --- test-foundry/aave-v2/TestRatesLens.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-foundry/aave-v2/TestRatesLens.t.sol b/test-foundry/aave-v2/TestRatesLens.t.sol index 1db444bf2..10743f062 100644 --- a/test-foundry/aave-v2/TestRatesLens.t.sol +++ b/test-foundry/aave-v2/TestRatesLens.t.sol @@ -1115,7 +1115,7 @@ contract TestRatesLens is TestSetup { } function _invertSpreadOnDaiWithStorageManipulation() - public + internal returns (uint256 poolSupplyRate, uint256 poolBorrowRate) { // Keep the current supply rate.