Skip to content
This repository was archived by the owner on Dec 18, 2025. It is now read-only.

Commit 94b2cdc

Browse files
authored
Merge pull request #2 from morpho-org/fix/indexes-caching-mc
fix(mc): indexes caching
2 parents f42b538 + aaab802 commit 94b2cdc

4 files changed

Lines changed: 79 additions & 5 deletions

File tree

src/compound/InterestRatesManager.sol

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,6 @@ contract InterestRatesManager is IInterestRatesManager, MorphoStorage {
5252
function updateP2PIndexes(address _poolToken) external {
5353
Types.LastPoolIndexes storage poolIndexes = lastPoolIndexes[_poolToken];
5454

55-
if (block.number == poolIndexes.lastUpdateBlockNumber) return;
56-
5755
Types.MarketParameters memory marketParams = marketParameters[_poolToken];
5856

5957
uint256 poolSupplyIndex = ICToken(_poolToken).exchangeRateCurrent();

src/compound/lens/IndexesLens.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ abstract contract IndexesLens is LensStorage {
179179
{
180180
marketParameters = morpho.marketParameters(_poolToken);
181181

182-
if (!_updated || block.number == _lastPoolIndexes.lastUpdateBlockNumber) {
182+
if (!_updated) {
183183
return (
184184
morpho.p2pSupplyIndex(_poolToken),
185185
morpho.p2pBorrowIndex(_poolToken),

test/compound/TestLens.t.sol

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,9 @@ contract TestLens is TestSetup {
7474
uint256 amount = 10_000 ether;
7575
uint256 toBorrow = amount / 2;
7676

77-
borrower1.approve(dai, amount);
77+
borrower1.approve(dai, type(uint256).max);
7878
indexes.index1 = ICToken(cDai).exchangeRateCurrent();
7979
borrower1.supply(cDai, amount);
80-
uint256 p2pBorrowIndex = morpho.p2pBorrowIndex(cDai);
8180
borrower1.borrow(cDai, toBorrow);
8281

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

9594
uint256 total;
9695

96+
// To update p2p indexes on Morpho (they can change inside of a block because the poolSupplyIndex can change due to rounding errors).
97+
borrower1.supply(cDai, 1);
98+
uint256 p2pBorrowIndex = morpho.p2pBorrowIndex(cDai);
9799
{
98100
uint256 onPool = amount.div(indexes.index1);
99101
uint256 matchedInP2P = toBorrow.div(morpho.p2pSupplyIndex(cDai));
@@ -1719,4 +1721,40 @@ contract TestLens is TestSetup {
17191721
morpho.setIsLiquidateBorrowPaused(cDai, true);
17201722
assertTrue(lens.getMarketPauseStatus(cDai).isLiquidateBorrowPaused);
17211723
}
1724+
1725+
function testPoolIndexGrowthInsideBlock() public {
1726+
supplier1.approve(dai, type(uint256).max);
1727+
supplier1.supply(cDai, 1 ether);
1728+
1729+
uint256 poolBorrowIndexBefore = lens.getIndexes(cDai, true).poolSupplyIndex;
1730+
1731+
vm.prank(address(supplier1));
1732+
ERC20(dai).transfer(cDai, 10_000 ether);
1733+
1734+
supplier1.supply(cDai, 1);
1735+
1736+
uint256 poolSupplyIndexAfter = lens.getIndexes(cDai, true).poolSupplyIndex;
1737+
1738+
assertGt(poolSupplyIndexAfter, poolBorrowIndexBefore);
1739+
}
1740+
1741+
function testP2PIndexGrowthInsideBlock() public {
1742+
borrower1.approve(dai, type(uint256).max);
1743+
borrower1.supply(cDai, 1 ether);
1744+
borrower1.borrow(cDai, 0.5 ether);
1745+
setDefaultMaxGasForMatchingHelper(0, 0, 0, 0);
1746+
// Bypass the borrow repay in the same block by overwritting the storage slot lastBorrowBlock[borrower1].
1747+
hevm.store(address(morpho), keccak256(abi.encode(address(borrower1), 178)), 0);
1748+
// Create delta.
1749+
borrower1.repay(cDai, type(uint256).max);
1750+
1751+
uint256 p2pSupplyIndexBefore = lens.getCurrentP2PSupplyIndex(cDai);
1752+
1753+
vm.prank(address(supplier1));
1754+
ERC20(dai).transfer(cDai, 10_000 ether);
1755+
1756+
uint256 p2pSupplyIndexAfter = lens.getCurrentP2PSupplyIndex(cDai);
1757+
1758+
assertGt(p2pSupplyIndexAfter, p2pSupplyIndexBefore);
1759+
}
17221760
}

test/compound/TestSupply.t.sol

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,44 @@ contract TestSupply is TestSetup {
321321
assertGt(gasUsed2, gasUsed1 + 5e4);
322322
}
323323

324+
function testPoolIndexGrowthInsideBlock() public {
325+
supplier1.approve(dai, type(uint256).max);
326+
supplier1.supply(cDai, 1 ether);
327+
328+
(, uint256 poolSupplyIndexCachedBefore, ) = morpho.lastPoolIndexes(cDai);
329+
330+
vm.prank(address(supplier1));
331+
ERC20(dai).transfer(cDai, 10_000 ether);
332+
333+
supplier1.supply(cDai, 1);
334+
335+
(, uint256 poolSupplyIndexCachedAfter, ) = morpho.lastPoolIndexes(cDai);
336+
337+
assertGt(poolSupplyIndexCachedAfter, poolSupplyIndexCachedBefore);
338+
}
339+
340+
function testP2PIndexGrowthInsideBlock() public {
341+
borrower1.approve(dai, type(uint256).max);
342+
borrower1.supply(cDai, 1 ether);
343+
borrower1.borrow(cDai, 0.5 ether);
344+
setDefaultMaxGasForMatchingHelper(0, 0, 0, 0);
345+
// Bypass the borrow repay in the same block by overwritting the storage slot lastBorrowBlock[borrower1].
346+
hevm.store(address(morpho), keccak256(abi.encode(address(borrower1), 178)), 0);
347+
// Create delta.
348+
borrower1.repay(cDai, type(uint256).max);
349+
350+
uint256 p2pSupplyIndexBefore = morpho.p2pSupplyIndex(cDai);
351+
352+
vm.prank(address(supplier1));
353+
ERC20(dai).transfer(cDai, 10_000 ether);
354+
355+
borrower1.supply(cDai, 1);
356+
357+
uint256 p2pSupplyIndexAfter = morpho.p2pSupplyIndex(cDai);
358+
359+
assertGt(p2pSupplyIndexAfter, p2pSupplyIndexBefore);
360+
}
361+
324362
/// @dev Helper for gas usage test
325363
function _getSupplyGasUsage(uint256 amount, uint256 maxGas) internal returns (uint256 gasUsed) {
326364
// 2 * NMAX borrowers borrow amount

0 commit comments

Comments
 (0)