Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update last total assets in updateWithdrawQueue #337

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/MetaMorpho.sol
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,8 @@ contract MetaMorpho is ERC4626, ERC20Permit, Ownable2Step, Multicall, IMetaMorph
bool[] memory seen = new bool[](currLength);
Id[] memory newWithdrawQueue = new Id[](newLength);

uint256 lostAssets;

for (uint256 i; i < newLength; ++i) {
uint256 prevIndex = indexes[i];

Expand All @@ -346,12 +348,20 @@ contract MetaMorpho is ERC4626, ERC20Permit, Ownable2Step, Multicall, IMetaMorph

if (config[id].cap != 0) revert ErrorsLib.InvalidMarketRemovalNonZeroCap(id);

if (MORPHO.supplyShares(id, address(this)) != 0) {
uint256 supplyShares = MORPHO.supplyShares(id, address(this));

if (supplyShares != 0) {
if (config[id].removableAt == 0) revert ErrorsLib.InvalidMarketRemovalNonZeroSupply(id);

if (block.timestamp < config[id].removableAt) {
revert ErrorsLib.InvalidMarketRemovalTimelockNotElapsed(id);
}

// Not accruing interest to avoid possible reverts due to the IRM.
uint256 totalSupplyAssets = MORPHO.totalSupplyAssets(id);
Jean-Grimal marked this conversation as resolved.
Show resolved Hide resolved
uint256 totalSupplyShares = MORPHO.totalSupplyShares(id);

lostAssets += supplyShares.toAssetsDown(totalSupplyAssets, totalSupplyShares);
}

delete config[id];
Expand All @@ -360,6 +370,9 @@ contract MetaMorpho is ERC4626, ERC20Permit, Ownable2Step, Multicall, IMetaMorph

withdrawQueue = newWithdrawQueue;

// Accrue interest on all the enabled markets except the removed ones.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait this does not accrue interest ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Accrue interest on all the enabled markets except the removed ones.
// Accrue fee on all the enabled markets except the removed ones.

_updateLastTotalAssets(lastTotalAssets.zeroFloorSub(lostAssets));

emit EventsLib.SetWithdrawQueue(_msgSender(), newWithdrawQueue);
}

Expand Down
60 changes: 60 additions & 0 deletions test/forge/FeeTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ contract FeeTest is IntegrationTest {
using Math for uint256;
using MathLib for uint256;
using MarketParamsLib for MarketParams;
using MorphoBalancesLib for IMorpho;

function setUp() public override {
super.setUp();
Expand Down Expand Up @@ -348,4 +349,63 @@ contract FeeTest is IntegrationTest {
assertEq(assets, expectedAssets, "assets");
assertGe(assets, assetsBefore, "assets increased");
}

function testUpdateWithdrawQueueRemovingDisabledMarketWithFee(
uint256 firstAmountSupplied,
uint256 secondAmountSupplied,
address newFeeRecipient,
uint256 blocks
) public {
firstAmountSupplied = bound(firstAmountSupplied, MIN_TEST_ASSETS, MAX_TEST_ASSETS);
secondAmountSupplied = bound(secondAmountSupplied, MIN_TEST_ASSETS, MAX_TEST_ASSETS);
blocks = _boundBlocks(blocks);
vm.assume(newFeeRecipient != FEE_RECIPIENT && newFeeRecipient != address(0));

_setCap(allMarkets[0], firstAmountSupplied);
_setCap(allMarkets[1], secondAmountSupplied);
MerlinEgalite marked this conversation as resolved.
Show resolved Hide resolved

Id[] memory supplyQueue = new Id[](2);
supplyQueue[0] = allMarkets[0].id();
supplyQueue[1] = allMarkets[1].id();
MerlinEgalite marked this conversation as resolved.
Show resolved Hide resolved

vm.prank(ALLOCATOR);
vault.setSupplyQueue(supplyQueue);
MerlinEgalite marked this conversation as resolved.
Show resolved Hide resolved

loanToken.setBalance(SUPPLIER, firstAmountSupplied + secondAmountSupplied);

vm.prank(SUPPLIER);
vault.deposit(firstAmountSupplied + secondAmountSupplied, ONBEHALF);

_setCap(allMarkets[1], 0);

vm.prank(CURATOR);
vault.submitMarketRemoval(allMarkets[1].id());

vm.warp(block.timestamp + TIMELOCK);

uint256[] memory indexes = new uint256[](2);
indexes[0] = 0;
indexes[1] = 1;

vm.prank(ALLOCATOR);
vault.updateWithdrawQueue(indexes);

assertApproxEqAbs(vault.lastTotalAssets(), firstAmountSupplied, 1, "lastTotalAssets");

_forward(blocks);
MerlinEgalite marked this conversation as resolved.
Show resolved Hide resolved

uint256 expectedTotalAssets = morpho.expectedSupplyAssets(allMarkets[0], address(vault));
uint256 expectedFeeAssets = (expectedTotalAssets - vault.lastTotalAssets()).mulDiv(FEE, WAD);
uint256 expectedFeeShares = expectedFeeAssets.mulDiv(
vault.totalSupply() + 10 ** ConstantsLib.DECIMALS_OFFSET,
expectedTotalAssets - expectedFeeAssets + 1,
Math.Rounding.Floor
);

// Set new fee recipient to accrue fee.
vm.prank(OWNER);
vault.setFeeRecipient(newFeeRecipient);

assertEq(vault.balanceOf(FEE_RECIPIENT), expectedFeeShares, "feeShares");
}
}
Loading