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

Commit 8bed0f7

Browse files
Merge pull request #135 from morpho-dao/refactor/pool-indexes
Refactor pool indexes
2 parents 13294c7 + d3e025a commit 8bed0f7

8 files changed

Lines changed: 115 additions & 15 deletions

File tree

src/aave-v2/SupplyVaultBase.sol

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// SPDX-License-Identifier: GNU AGPLv3
22
pragma solidity 0.8.13;
33

4-
import {ILendingPool} from "@contracts/aave-v2/interfaces/aave/ILendingPool.sol";
54
import {IAToken} from "@contracts/aave-v2/interfaces/aave/IAToken.sol";
65
import {IMorpho} from "@contracts/aave-v2/interfaces/IMorpho.sol";
76

@@ -29,7 +28,6 @@ abstract contract SupplyVaultBase is ERC4626UpgradeableSafe, OwnableUpgradeable
2928
/// STORAGE ///
3029

3130
IMorpho public immutable morpho; // The main Morpho contract.
32-
ILendingPool public immutable pool;
3331
address public poolToken; // The pool token corresponding to the market to supply to through this vault.
3432

3533
/// CONSTRUCTOR ///
@@ -38,9 +36,7 @@ abstract contract SupplyVaultBase is ERC4626UpgradeableSafe, OwnableUpgradeable
3836
/// @param _morpho The address of the main Morpho contract.
3937
constructor(address _morpho) {
4038
if (_morpho == address(0)) revert ZeroAddress();
41-
4239
morpho = IMorpho(_morpho);
43-
pool = morpho.pool();
4440
}
4541

4642
/// INITIALIZER ///
@@ -89,6 +85,9 @@ abstract contract SupplyVaultBase is ERC4626UpgradeableSafe, OwnableUpgradeable
8985

9086
/// PUBLIC ///
9187

88+
/// @dev The indexes used by this function might not be up-to-date.
89+
/// As a consequence, view functions (like `maxWithdraw`) could underestimate the withdrawable amount.
90+
/// To redeem all their assets, users are encouraged to use the `redeem` function passing their vault tokens balance.
9291
function totalAssets() public view override returns (uint256) {
9392
address poolTokenMem = poolToken;
9493
Types.SupplyBalance memory supplyBalance = morpho.supplyBalanceInOf(
@@ -97,10 +96,42 @@ abstract contract SupplyVaultBase is ERC4626UpgradeableSafe, OwnableUpgradeable
9796
);
9897

9998
return
100-
supplyBalance.onPool.rayMul(pool.getReserveNormalizedIncome(asset())) +
99+
supplyBalance.onPool.rayMul(morpho.poolIndexes(poolTokenMem).poolSupplyIndex) +
101100
supplyBalance.inP2P.rayMul(morpho.p2pSupplyIndex(poolTokenMem));
102101
}
103102

103+
function deposit(uint256 assets, address receiver) public virtual override returns (uint256) {
104+
// Update the indexes to get the most up-to-date total assets balance.
105+
morpho.updateIndexes(poolToken);
106+
return super.deposit(assets, receiver);
107+
}
108+
109+
function mint(uint256 shares, address receiver) public virtual override returns (uint256) {
110+
// Update the indexes to get the most up-to-date total assets balance.
111+
morpho.updateIndexes(poolToken);
112+
return super.mint(shares, receiver);
113+
}
114+
115+
function withdraw(
116+
uint256 assets,
117+
address receiver,
118+
address owner
119+
) public virtual override returns (uint256) {
120+
// Update the indexes to get the most up-to-date total assets balance.
121+
morpho.updateIndexes(poolToken);
122+
return super.withdraw(assets, receiver, owner);
123+
}
124+
125+
function redeem(
126+
uint256 shares,
127+
address receiver,
128+
address owner
129+
) public virtual override returns (uint256) {
130+
// Update the indexes to get the most up-to-date total assets balance.
131+
morpho.updateIndexes(poolToken);
132+
return super.redeem(shares, receiver, owner);
133+
}
134+
104135
/// INTERNAL ///
105136

106137
function _deposit(

src/aave-v3/SupplyVaultBase.sol

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
pragma solidity 0.8.10;
33

44
import {IAToken} from "@aave/core-v3/contracts/interfaces/IAToken.sol";
5-
import {IPool} from "@contracts/aave-v3/interfaces/aave/IPool.sol";
65
import {IMorpho} from "@contracts/aave-v3/interfaces/IMorpho.sol";
76
import {IRewardsController} from "@aave/periphery-v3/contracts/rewards/interfaces/IRewardsController.sol";
87

@@ -30,7 +29,6 @@ abstract contract SupplyVaultBase is ERC4626UpgradeableSafe, OwnableUpgradeable
3029
/// STORAGE ///
3130

3231
IMorpho public immutable morpho; // The main Morpho contract.
33-
IPool public immutable pool; // The AaveV3 pool.
3432

3533
address public poolToken; // The pool token corresponding to the market to supply to through this vault.
3634

@@ -40,9 +38,7 @@ abstract contract SupplyVaultBase is ERC4626UpgradeableSafe, OwnableUpgradeable
4038
/// @param _morpho The address of the main Morpho contract.
4139
constructor(address _morpho) {
4240
if (_morpho == address(0)) revert ZeroAddress();
43-
4441
morpho = IMorpho(_morpho);
45-
pool = morpho.pool();
4642
}
4743

4844
/// INITIALIZER ///
@@ -91,6 +87,9 @@ abstract contract SupplyVaultBase is ERC4626UpgradeableSafe, OwnableUpgradeable
9187

9288
/// PUBLIC ///
9389

90+
/// @dev The indexes used by this function might not be up-to-date.
91+
/// As a consequence, view functions (like `maxWithdraw`) could underestimate the withdrawable amount.
92+
/// To redeem all their assets, users are encouraged to use the `redeem` function passing their vault tokens balance.
9493
function totalAssets() public view override returns (uint256) {
9594
address poolTokenMem = poolToken;
9695
Types.SupplyBalance memory supplyBalance = morpho.supplyBalanceInOf(
@@ -99,10 +98,42 @@ abstract contract SupplyVaultBase is ERC4626UpgradeableSafe, OwnableUpgradeable
9998
);
10099

101100
return
102-
supplyBalance.onPool.rayMul(pool.getReserveNormalizedIncome(asset())) +
101+
supplyBalance.onPool.rayMul(morpho.poolIndexes(poolTokenMem).poolSupplyIndex) +
103102
supplyBalance.inP2P.rayMul(morpho.p2pSupplyIndex(poolTokenMem));
104103
}
105104

105+
function deposit(uint256 assets, address receiver) public virtual override returns (uint256) {
106+
// Update the indexes to get the most up-to-date total assets balance.
107+
morpho.updateIndexes(poolToken);
108+
return super.deposit(assets, receiver);
109+
}
110+
111+
function mint(uint256 shares, address receiver) public virtual override returns (uint256) {
112+
// Update the indexes to get the most up-to-date total assets balance.
113+
morpho.updateIndexes(poolToken);
114+
return super.mint(shares, receiver);
115+
}
116+
117+
function withdraw(
118+
uint256 assets,
119+
address receiver,
120+
address owner
121+
) public virtual override returns (uint256) {
122+
// Update the indexes to get the most up-to-date total assets balance.
123+
morpho.updateIndexes(poolToken);
124+
return super.withdraw(assets, receiver, owner);
125+
}
126+
127+
function redeem(
128+
uint256 shares,
129+
address receiver,
130+
address owner
131+
) public virtual override returns (uint256) {
132+
// Update the indexes to get the most up-to-date total assets balance.
133+
morpho.updateIndexes(poolToken);
134+
return super.redeem(shares, receiver, owner);
135+
}
136+
106137
/// INTERNAL ///
107138

108139
function _deposit(

src/compound/SupplyVaultBase.sol

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,18 +91,51 @@ abstract contract SupplyVaultBase is ERC4626UpgradeableSafe, OwnableUpgradeable
9191

9292
/// PUBLIC ///
9393

94+
/// @dev The indexes used by this function might not be up-to-date.
95+
/// As a consequence, view functions (like `maxWithdraw`) could underestimate the withdrawable amount.
96+
/// To redeem all their assets, users are encouraged to use the `redeem` function passing their vault tokens balance.
9497
function totalAssets() public view override returns (uint256) {
95-
IMorpho morphoMem = morpho;
9698
address poolTokenMem = poolToken;
97-
98-
Types.SupplyBalance memory supplyBalance = morphoMem.supplyBalanceInOf(
99+
Types.SupplyBalance memory supplyBalance = morpho.supplyBalanceInOf(
99100
poolTokenMem,
100101
address(this)
101102
);
102103

103104
return
104-
supplyBalance.onPool.mul(ICToken(poolTokenMem).exchangeRateStored()) +
105-
supplyBalance.inP2P.mul(morphoMem.p2pSupplyIndex(poolTokenMem));
105+
supplyBalance.onPool.mul(morpho.lastPoolIndexes(poolTokenMem).lastSupplyPoolIndex) +
106+
supplyBalance.inP2P.mul(morpho.p2pSupplyIndex(poolTokenMem));
107+
}
108+
109+
function deposit(uint256 assets, address receiver) public virtual override returns (uint256) {
110+
// Update the indexes to get the most up-to-date total assets balance.
111+
morpho.updateP2PIndexes(poolToken);
112+
return super.deposit(assets, receiver);
113+
}
114+
115+
function mint(uint256 shares, address receiver) public virtual override returns (uint256) {
116+
// Update the indexes to get the most up-to-date total assets balance.
117+
morpho.updateP2PIndexes(poolToken);
118+
return super.mint(shares, receiver);
119+
}
120+
121+
function withdraw(
122+
uint256 assets,
123+
address receiver,
124+
address owner
125+
) public virtual override returns (uint256) {
126+
// Update the indexes to get the most up-to-date total assets balance.
127+
morpho.updateP2PIndexes(poolToken);
128+
return super.withdraw(assets, receiver, owner);
129+
}
130+
131+
function redeem(
132+
uint256 shares,
133+
address receiver,
134+
address owner
135+
) public virtual override returns (uint256) {
136+
// Update the indexes to get the most up-to-date total assets balance.
137+
morpho.updateP2PIndexes(poolToken);
138+
return super.redeem(shares, receiver, owner);
106139
}
107140

108141
/// INTERNAL ///

test/aave-v2/TestSupplyVault.t.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ contract TestSupplyVault is TestSetupVaults {
152152
uint256 _deal,
153153
uint256 _toTransfer
154154
) public {
155+
vm.assume(_to != daiSupplyVault.owner());
155156
_toTransfer = bound(_toTransfer, 0, _deal);
156157
deal($token, address(daiSupplyVault), _deal);
157158

test/aave-v3/TestSupplyHarvestVault.t.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ contract TestSupplyHarvestVault is TestSetupVaults {
324324
uint256 _deal,
325325
uint256 _toTransfer
326326
) public {
327+
vm.assume(_to != daiSupplyHarvestVault.owner());
327328
_toTransfer = bound(_toTransfer, 0, _deal);
328329
deal($token, address(daiSupplyHarvestVault), _deal);
329330

test/aave-v3/TestSupplyVault.t.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,7 @@ contract TestSupplyVault is TestSetupVaults {
461461
uint256 _deal,
462462
uint256 _toTransfer
463463
) public {
464+
vm.assume(_to != daiSupplyVault.owner());
464465
_toTransfer = bound(_toTransfer, 0, _deal);
465466
deal($token, address(daiSupplyVault), _deal);
466467

test/compound/TestSupplyHarvestVault.t.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ contract TestSupplyHarvestVault is TestSetupVaults {
337337
uint256 _deal,
338338
uint256 _toTransfer
339339
) public {
340+
vm.assume(_to != daiSupplyHarvestVault.owner());
340341
_toTransfer = bound(_toTransfer, 0, _deal);
341342
deal($token, address(daiSupplyHarvestVault), _deal);
342343

test/compound/TestSupplyVault.t.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ contract TestSupplyVault is TestSetupVaults {
326326
uint256 _deal,
327327
uint256 _toTransfer
328328
) public {
329+
vm.assume(_to != daiSupplyVault.owner());
329330
_toTransfer = bound(_toTransfer, 0, _deal);
330331
deal($token, address(daiSupplyVault), _deal);
331332

0 commit comments

Comments
 (0)