Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/post-cantina' into fix/issue-63
Browse files Browse the repository at this point in the history
  • Loading branch information
MathisGD committed Dec 28, 2023
2 parents e5ec31d + 08a20ab commit 89f0057
Show file tree
Hide file tree
Showing 6 changed files with 18 additions and 14 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ To achieve this, it is advised to allocate "idle" funds to any market on Morpho

- The vault's asset as loan token.
- No collateral token (`address(0)`).
- An arbitrary IRM.
- An IRM that does not trigger a revert (`address(0)`).
- An arbitrary oracle (`address(0)`).
- An arbitrary LLTV.
- An arbitrary LLTV (`0`).

Thus, these funds cannot be borrowed on Morpho Blue and are guaranteed to be liquid; though it won't generate interest.

Expand Down
8 changes: 4 additions & 4 deletions src/MetaMorpho.sol
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ contract MetaMorpho is ERC4626, ERC20Permit, Ownable2Step, Multicall, IMetaMorph
if (newFee > ConstantsLib.MAX_FEE) revert ErrorsLib.MaxFeeExceeded();
if (newFee != 0 && feeRecipient == address(0)) revert ErrorsLib.ZeroFeeRecipient();

// Accrue interest using the previous fee set before changing it.
// Accrue fee using the previous fee set before changing it.
_updateLastTotalAssets(_accrueFee());

// Safe "unchecked" cast because newFee <= MAX_FEE.
Expand All @@ -249,7 +249,7 @@ contract MetaMorpho is ERC4626, ERC20Permit, Ownable2Step, Multicall, IMetaMorph
if (newFeeRecipient == feeRecipient) revert ErrorsLib.AlreadySet();
if (newFeeRecipient == address(0) && fee != 0) revert ErrorsLib.ZeroFeeRecipient();

// Accrue interest to the previous fee recipient set before changing it.
// Accrue fee to the previous fee recipient set before changing it.
_updateLastTotalAssets(_accrueFee());

feeRecipient = newFeeRecipient;
Expand Down Expand Up @@ -301,7 +301,7 @@ contract MetaMorpho is ERC4626, ERC20Permit, Ownable2Step, Multicall, IMetaMorph
function submitMarketRemoval(MarketParams memory marketParams) external onlyCuratorRole {
Id id = marketParams.id();
if (config[id].removableAt != 0) revert ErrorsLib.AlreadySet();
if (!config[id].enabled) revert ErrorsLib.MarketNotEnabled();
if (!config[id].enabled) revert ErrorsLib.MarketNotEnabled(id);

_setCap(marketParams, id, 0);

Expand Down Expand Up @@ -382,7 +382,7 @@ contract MetaMorpho is ERC4626, ERC20Permit, Ownable2Step, Multicall, IMetaMorph
uint256 withdrawn = supplyAssets.zeroFloorSub(allocation.assets);

if (withdrawn > 0) {
if (allocation.marketParams.loanToken != asset()) revert ErrorsLib.InconsistentAsset(id);
if (!config[id].enabled) revert ErrorsLib.MarketNotEnabled(id);

// Guarantees that unknown frontrunning donations can be withdrawn, in order to disable a market.
uint256 shares;
Expand Down
10 changes: 7 additions & 3 deletions src/interfaces/IMetaMorpho.sol
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ interface IMetaMorphoBase {
function revokePendingCap(Id id) external;

/// @notice Submits a forced market removal from the vault, eventually losing all funds supplied to the market.
/// @notice Funds can be recovered by enabling this market again and withdrawing from it (using `reallocate`),
/// but funds will be distributed pro-rata to the shares at the time of withdrawal, not at the time of removal.
/// @notice This forced removal is expected to be used as an emergency process in case a market constantly reverts.
/// To softly remove a sane market, the curator role is expected to bundle a reallocation that empties the market
/// first (using `reallocate`), followed by the removal of the market (using `updateWithdrawQueue`).
/// @dev Warning: Removing a market with non-zero supply will instantly impact the vault's price per share.
function submitMarketRemoval(MarketParams memory marketParams) external;

/// @notice Revokes the pending removal of the market defined by `id`.
Expand Down Expand Up @@ -140,9 +146,7 @@ interface IMetaMorphoBase {
/// increase the cost of depositing to the vault.
function setSupplyQueue(Id[] calldata newSupplyQueue) external;

/// @notice Sets the withdraw queue as a permutation of the previous one, although markets with both zero cap and
/// zero vault's supply can be removed from the permutation.
/// @notice This is the only entry point to disable a market.
/// @notice Updates the withdraw queue. Some markets can be removed, but no market can be added.
/// @notice Removing a market requires the vault to have 0 supply on it, or to have previously submitted a removal
/// for this market (with the function `submitMarketRemoval`).
/// @notice Warning: Anyone can supply on behalf of the vault so the call to `updateWithdrawQueue` that expects a
Expand Down
4 changes: 2 additions & 2 deletions src/libraries/ErrorsLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ library ErrorsLib {
/// @notice Thrown when submitting a cap for a market which does not exist.
error MarketNotCreated();

/// @notice Thrown when submitting a non previously enabled market for removal.
error MarketNotEnabled();
/// @notice Thrown when interacting with a non previously enabled market `id`.
error MarketNotEnabled(Id id);

/// @notice Thrown when the submitted timelock is above the max timelock.
error AboveMaxTimelock();
Expand Down
4 changes: 2 additions & 2 deletions test/forge/ReallocateWithdrawTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ contract ReallocateWithdrawTest is IntegrationTest {
assertEq(_idle(), INITIAL_DEPOSIT, "idle");
}

function testReallocateWithdrawInconsistentAsset() public {
function testReallocateWithdrawMarketNotEnabled() public {
ERC20Mock loanToken2 = new ERC20Mock("loan2", "B2");
allMarkets[0].loanToken = address(loanToken2);

Expand All @@ -75,7 +75,7 @@ contract ReallocateWithdrawTest is IntegrationTest {
allocations.push(MarketAllocation(allMarkets[0], 0));

vm.prank(ALLOCATOR);
vm.expectRevert(abi.encodeWithSelector(ErrorsLib.InconsistentAsset.selector, allMarkets[0].id()));
vm.expectRevert(abi.encodeWithSelector(ErrorsLib.MarketNotEnabled.selector, allMarkets[0].id()));
vault.reallocate(allocations);
}

Expand Down
2 changes: 1 addition & 1 deletion test/forge/TimelockTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ contract TimelockTest is IntegrationTest {
}

function testSubmitMarketRemovalMarketNotEnabled() public {
vm.expectRevert(ErrorsLib.MarketNotEnabled.selector);
vm.expectRevert(abi.encodeWithSelector(ErrorsLib.MarketNotEnabled.selector, allMarkets[1].id()));
vm.prank(CURATOR);
vault.submitMarketRemoval(allMarkets[1]);
}
Expand Down

0 comments on commit 89f0057

Please sign in to comment.