Skip to content

Commit

Permalink
Merge pull request #1666 from morpho-org/fix/indexes-caching-issue
Browse files Browse the repository at this point in the history
Fix indexes caching issue
  • Loading branch information
MathisGD authored Jun 8, 2023
2 parents 0df9d1a + 94b2cdc commit 2b4993c
Show file tree
Hide file tree
Showing 13 changed files with 162 additions and 14 deletions.
2 changes: 1 addition & 1 deletion .github/actions/ci-foundry-upgrade/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ runs:
shell: bash

- name: Install Foundry
uses: onbjerg/foundry-toolchain@v1
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

Expand Down
2 changes: 1 addition & 1 deletion .github/actions/ci-foundry/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ runs:
shell: bash

- name: Install Foundry
uses: onbjerg/foundry-toolchain@v1
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-storage-check-aave-v2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
shell: bash

- name: Install Foundry
uses: onbjerg/foundry-toolchain@v1
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-storage-check-compound.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
shell: bash

- name: Install Foundry
uses: onbjerg/foundry-toolchain@v1
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-storage-snapshot-check-aave-v2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
run: yarn install --frozen-lockfile

- name: Install Foundry
uses: onbjerg/foundry-toolchain@v1
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-storage-snapshot-check-compound.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
run: yarn install --frozen-lockfile

- name: Install Foundry
uses: onbjerg/foundry-toolchain@v1
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

Expand Down
2 changes: 0 additions & 2 deletions src/aave-v2/InterestRatesManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ contract InterestRatesManager is IInterestRatesManager, MorphoStorage {
function updateIndexes(address _poolToken) external {
Types.PoolIndexes storage marketPoolIndexes = poolIndexes[_poolToken];

if (block.timestamp == marketPoolIndexes.lastUpdateTimestamp) return;

Types.Market storage market = market[_poolToken];
(uint256 newPoolSupplyIndex, uint256 newPoolBorrowIndex) = _getPoolIndexes(
market.underlyingToken
Expand Down
2 changes: 0 additions & 2 deletions src/compound/InterestRatesManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ contract InterestRatesManager is IInterestRatesManager, MorphoStorage {
function updateP2PIndexes(address _poolToken) external {
Types.LastPoolIndexes storage poolIndexes = lastPoolIndexes[_poolToken];

if (block.number == poolIndexes.lastUpdateBlockNumber) return;

Types.MarketParameters memory marketParams = marketParameters[_poolToken];

uint256 poolSupplyIndex = ICToken(_poolToken).exchangeRateCurrent();
Expand Down
2 changes: 1 addition & 1 deletion src/compound/lens/IndexesLens.sol
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ abstract contract IndexesLens is LensStorage {
{
marketParameters = morpho.marketParameters(_poolToken);

if (!_updated || block.number == _lastPoolIndexes.lastUpdateBlockNumber) {
if (!_updated) {
return (
morpho.p2pSupplyIndex(_poolToken),
morpho.p2pBorrowIndex(_poolToken),
Expand Down
36 changes: 36 additions & 0 deletions test/aave-v2/TestLens.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -1658,4 +1658,40 @@ contract TestLens is TestSetup {
morpho.setIsLiquidateBorrowPaused(aDai, true);
assertTrue(lens.getMarketPauseStatus(aDai).isLiquidateBorrowPaused);
}

function testPoolIndexGrowthInsideBlock() public {
supplier1.approve(dai, type(uint256).max);
supplier1.supply(aDai, 10 ether);

uint256 poolSupplyIndexBefore = lens.getIndexes(aDai).poolSupplyIndex;

FlashLoan flashLoan = new FlashLoan(pool);
vm.prank(address(supplier2));
ERC20(dai).transfer(address(flashLoan), 10_000 ether); // To pay the premium.
flashLoan.callFlashLoan(dai, 10_000 ether);

uint256 poolSupplyIndexAfter = lens.getIndexes(aDai).poolSupplyIndex;

assertGt(poolSupplyIndexAfter, poolSupplyIndexBefore);
}

function testP2PIndexGrowthInsideBlock() public {
borrower1.approve(dai, type(uint256).max);
borrower1.supply(aDai, 10 ether);
borrower1.borrow(aDai, 5 ether);
setDefaultMaxGasForMatchingHelper(3e6, 3e6, 3e6, 0);
// Create delta.
borrower1.repay(aDai, type(uint256).max);

uint256 p2pSupplyIndexBefore = lens.getCurrentP2PSupplyIndex(aDai);

FlashLoan flashLoan = new FlashLoan(pool);
vm.prank(address(supplier2));
ERC20(dai).transfer(address(flashLoan), 10_000 ether); // To pay the premium.
flashLoan.callFlashLoan(dai, 10_000 ether);

uint256 p2pSupplyIndexAfter = lens.getCurrentP2PSupplyIndex(aDai);

assertGt(p2pSupplyIndexAfter, p2pSupplyIndexBefore);
}
}
42 changes: 41 additions & 1 deletion test/aave-v2/TestSupply.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ contract TestSupply is TestSetup {

FlashLoan flashLoan = new FlashLoan(pool);
vm.prank(address(supplier2));
ERC20(dai).transfer(address(flashLoan), 10_000 ether); // to pay the premium.
ERC20(dai).transfer(address(flashLoan), 10_000 ether); // To pay the premium.
flashLoan.callFlashLoan(dai, flashLoanAmount);

vm.warp(block.timestamp + 1);
Expand All @@ -277,6 +277,46 @@ contract TestSupply is TestSetup {
assertGt(gasUsed2, gasUsed1 + 1e4);
}

function testPoolIndexGrowthInsideBlock() public {
supplier1.approve(dai, type(uint256).max);
supplier1.supply(aDai, 1);

(, uint256 poolSupplyIndexCachedBefore, ) = morpho.poolIndexes(aDai);

FlashLoan flashLoan = new FlashLoan(pool);
vm.prank(address(supplier2));
ERC20(dai).transfer(address(flashLoan), 10_000 ether); // To pay the premium.
flashLoan.callFlashLoan(dai, 10_000 ether);

supplier1.supply(aDai, 1);

(, uint256 poolSupplyIndexCachedAfter, ) = morpho.poolIndexes(aDai);

assertGt(poolSupplyIndexCachedAfter, poolSupplyIndexCachedBefore);
}

function testP2PIndexGrowthInsideBlock() public {
borrower1.approve(dai, type(uint256).max);
borrower1.supply(aDai, 10 ether);
borrower1.borrow(aDai, 5 ether);
setDefaultMaxGasForMatchingHelper(3e6, 3e6, 3e6, 0);
// Create delta.
borrower1.repay(aDai, type(uint256).max);

uint256 p2pSupplyIndexBefore = morpho.p2pSupplyIndex(aDai);

FlashLoan flashLoan = new FlashLoan(pool);
vm.prank(address(supplier2));
ERC20(dai).transfer(address(flashLoan), 10_000 ether); // To pay the premium.
flashLoan.callFlashLoan(dai, 10_000 ether);

borrower1.supply(aDai, 1);

uint256 p2pSupplyIndexAfter = morpho.p2pSupplyIndex(aDai);

assertGt(p2pSupplyIndexAfter, p2pSupplyIndexBefore);
}

/// @dev Helper for gas usage test
function _getSupplyGasUsage(uint256 amount, uint256 maxGas) internal returns (uint256 gasUsed) {
// 2 * NMAX borrowers borrow amount
Expand Down
42 changes: 40 additions & 2 deletions test/compound/TestLens.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,9 @@ contract TestLens is TestSetup {
uint256 amount = 10_000 ether;
uint256 toBorrow = amount / 2;

borrower1.approve(dai, amount);
borrower1.approve(dai, type(uint256).max);
indexes.index1 = ICToken(cDai).exchangeRateCurrent();
borrower1.supply(cDai, amount);
uint256 p2pBorrowIndex = morpho.p2pBorrowIndex(cDai);
borrower1.borrow(cDai, toBorrow);

indexes.index2 = ICToken(cDai).exchangeRateCurrent();
Expand All @@ -94,6 +93,9 @@ contract TestLens is TestSetup {

uint256 total;

// To update p2p indexes on Morpho (they can change inside of a block because the poolSupplyIndex can change due to rounding errors).
borrower1.supply(cDai, 1);
uint256 p2pBorrowIndex = morpho.p2pBorrowIndex(cDai);
{
uint256 onPool = amount.div(indexes.index1);
uint256 matchedInP2P = toBorrow.div(morpho.p2pSupplyIndex(cDai));
Expand Down Expand Up @@ -1719,4 +1721,40 @@ contract TestLens is TestSetup {
morpho.setIsLiquidateBorrowPaused(cDai, true);
assertTrue(lens.getMarketPauseStatus(cDai).isLiquidateBorrowPaused);
}

function testPoolIndexGrowthInsideBlock() public {
supplier1.approve(dai, type(uint256).max);
supplier1.supply(cDai, 1 ether);

uint256 poolBorrowIndexBefore = lens.getIndexes(cDai, true).poolSupplyIndex;

vm.prank(address(supplier1));
ERC20(dai).transfer(cDai, 10_000 ether);

supplier1.supply(cDai, 1);

uint256 poolSupplyIndexAfter = lens.getIndexes(cDai, true).poolSupplyIndex;

assertGt(poolSupplyIndexAfter, poolBorrowIndexBefore);
}

function testP2PIndexGrowthInsideBlock() public {
borrower1.approve(dai, type(uint256).max);
borrower1.supply(cDai, 1 ether);
borrower1.borrow(cDai, 0.5 ether);
setDefaultMaxGasForMatchingHelper(0, 0, 0, 0);
// Bypass the borrow repay in the same block by overwritting the storage slot lastBorrowBlock[borrower1].
hevm.store(address(morpho), keccak256(abi.encode(address(borrower1), 178)), 0);
// Create delta.
borrower1.repay(cDai, type(uint256).max);

uint256 p2pSupplyIndexBefore = lens.getCurrentP2PSupplyIndex(cDai);

vm.prank(address(supplier1));
ERC20(dai).transfer(cDai, 10_000 ether);

uint256 p2pSupplyIndexAfter = lens.getCurrentP2PSupplyIndex(cDai);

assertGt(p2pSupplyIndexAfter, p2pSupplyIndexBefore);
}
}
38 changes: 38 additions & 0 deletions test/compound/TestSupply.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,44 @@ contract TestSupply is TestSetup {
assertGt(gasUsed2, gasUsed1 + 5e4);
}

function testPoolIndexGrowthInsideBlock() public {
supplier1.approve(dai, type(uint256).max);
supplier1.supply(cDai, 1 ether);

(, uint256 poolSupplyIndexCachedBefore, ) = morpho.lastPoolIndexes(cDai);

vm.prank(address(supplier1));
ERC20(dai).transfer(cDai, 10_000 ether);

supplier1.supply(cDai, 1);

(, uint256 poolSupplyIndexCachedAfter, ) = morpho.lastPoolIndexes(cDai);

assertGt(poolSupplyIndexCachedAfter, poolSupplyIndexCachedBefore);
}

function testP2PIndexGrowthInsideBlock() public {
borrower1.approve(dai, type(uint256).max);
borrower1.supply(cDai, 1 ether);
borrower1.borrow(cDai, 0.5 ether);
setDefaultMaxGasForMatchingHelper(0, 0, 0, 0);
// Bypass the borrow repay in the same block by overwritting the storage slot lastBorrowBlock[borrower1].
hevm.store(address(morpho), keccak256(abi.encode(address(borrower1), 178)), 0);
// Create delta.
borrower1.repay(cDai, type(uint256).max);

uint256 p2pSupplyIndexBefore = morpho.p2pSupplyIndex(cDai);

vm.prank(address(supplier1));
ERC20(dai).transfer(cDai, 10_000 ether);

borrower1.supply(cDai, 1);

uint256 p2pSupplyIndexAfter = morpho.p2pSupplyIndex(cDai);

assertGt(p2pSupplyIndexAfter, p2pSupplyIndexBefore);
}

/// @dev Helper for gas usage test
function _getSupplyGasUsage(uint256 amount, uint256 maxGas) internal returns (uint256 gasUsed) {
// 2 * NMAX borrowers borrow amount
Expand Down

0 comments on commit 2b4993c

Please sign in to comment.