Skip to content

Commit

Permalink
Merge branch 'feat/add-comments-on-lost-fees' of github.com:morpho-la…
Browse files Browse the repository at this point in the history
…bs/morpho-blue-metamorpho into feat/add-comments-on-lost-fees
  • Loading branch information
MerlinEgalite committed Dec 27, 2023
2 parents 949e596 + 3da9d6b commit 99651fd
Show file tree
Hide file tree
Showing 8 changed files with 33 additions and 19 deletions.
1 change: 0 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
[submodule "lib/morpho-blue"]
path = lib/morpho-blue
url = https://github.com/morpho-org/morpho-blue
branch = chore/remove-remapping-context
[submodule "lib/universal-rewards-distributor"]
path = lib/universal-rewards-distributor
url = https://github.com/morpho-org/universal-rewards-distributor
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ Those rewards can be transferred to the `skimRecipient`.
The vault's owner has the choice to distribute back these rewards to vault depositors however they want.
For more information about this use case, see the [Rewards](#rewards) section.

All actions that may be against users' interests (e.g. enabling a market with a high exposure, increasing the fee) are subject to a timelock of minimum 12 hours.
If set, the `guardian` can revoke the action during the timelock except for the fee increase.
All actions that may be against users' interests (e.g. enabling a market with a high exposure) are subject to a timelock of minimum 24 hours.
If set, the `guardian` can revoke the action during the timelock.
After the timelock, the action can be executed by anyone.

### Roles
Expand All @@ -48,8 +48,8 @@ It can:
- Set the rewards recipient.
- Increase the timelock.
- [Timelocked] Decrease the timelock.
- [Timelocked with no possible veto] Set the performance fee (capped to 50%).
- [Timelocked] Set the guardian.
- Set the performance fee (capped at 50%).
- Set the fee recipient.

#### Curator
Expand All @@ -67,6 +67,7 @@ It can:
- After the timelock has elapsed, the allocator role is free to remove the market from the withdraw queue. The funds supplied to this market will be lost.
- If the market ever functions again, the allocator role can withdraw the funds that were previously lost.
- Revoke the pending cap of any market.
- Revoke the pending removal of any market.

#### Allocator

Expand All @@ -76,7 +77,7 @@ It can:

- Set the `supplyQueue` and `withdrawQueue`, i.e. decide on the order of the markets to supply/withdraw from.
- Upon a deposit, the vault will supply up to the cap of each Morpho Blue market in the `supplyQueue` in the order set.
- Upon a withdrawal, the vault will first withdraw from the idle supply and then withdraw up to the liquidity of each Morpho Blue market in the `withdrawalQueue` in the order set.
- Upon a withdrawal, the vault will withdraw up to the liquidity of each Morpho Blue market in the `withdrawQueue` in the order set.
- The `supplyQueue` only contains markets which cap has previously been non-zero.
- The `withdrawQueue` contains all markets that have a non-zero cap or a non-zero vault allocation.
- Instantaneously reallocate funds by supplying on markets of the `withdrawQueue` and withdrawing from markets that have the same loan asset as the vault's asset.
Expand All @@ -93,6 +94,7 @@ It can:
- Revoke the pending timelock.
- Revoke the pending guardian (which means it can revoke any attempt to change the guardian).
- Revoke the pending cap of any market.
- Revoke the pending removal of any market.

### Idle Supply

Expand Down
2 changes: 1 addition & 1 deletion lib/morpho-blue
Submodule morpho-blue updated 63 files
+51 −0 .github/workflows/certora.yml
+1 −1 .github/workflows/foundry.yml
+4 −0 .gitignore
+1 −1 README.md
+389 −0 certora/LICENSE
+287 −0 certora/README.md
+14 −0 certora/confs/AccrueInterest.conf
+9 −0 certora/confs/AssetsAccounting.conf
+9 −0 certora/confs/ConsistentState.conf
+13 −0 certora/confs/ExactMath.conf
+13 −0 certora/confs/Health.conf
+9 −0 certora/confs/LibSummary.conf
+9 −0 certora/confs/Liveness.conf
+14 −0 certora/confs/RatioMath.conf
+12 −0 certora/confs/Reentrancy.conf
+9 −0 certora/confs/Reverts.conf
+12 −0 certora/confs/Transfer.conf
+48 −0 certora/dispatch/ERC20NoRevert.sol
+42 −0 certora/dispatch/ERC20Standard.sol
+45 −0 certora/dispatch/ERC20USDT.sol
+6 −0 certora/gambit.conf
+92 −0 certora/harness/MorphoHarness.sol
+17 −0 certora/harness/MorphoInternalAccess.sol
+35 −0 certora/harness/TransferHarness.sol
+138 −0 certora/specs/AccrueInterest.spec
+126 −0 certora/specs/AssetsAccounting.spec
+294 −0 certora/specs/ConsistentState.spec
+123 −0 certora/specs/ExactMath.spec
+108 −0 certora/specs/Health.spec
+26 −0 certora/specs/LibSummary.spec
+386 −0 certora/specs/Liveness.spec
+184 −0 certora/specs/RatioMath.spec
+61 −0 certora/specs/Reentrancy.spec
+179 −0 certora/specs/Reverts.spec
+82 −0 certora/specs/Transfer.spec
+1 −1 foundry.toml
+1 −1 lib/forge-std
+48 −34 src/Morpho.sol
+3 −2 src/interfaces/IIrm.sol
+17 −14 src/interfaces/IMorpho.sol
+3 −0 src/libraries/ErrorsLib.sol
+10 −7 src/libraries/EventsLib.sol
+4 −3 src/libraries/SafeTransferLib.sol
+3 −0 src/libraries/SharesMathLib.sol
+1 −1 src/libraries/UtilsLib.sol
+6 −7 src/libraries/periphery/MorphoBalancesLib.sol
+9 −7 test/forge/BaseTest.sol
+1 −1 test/forge/helpers/SigUtils.sol
+12 −0 test/forge/integration/AccrueInterestIntegrationTest.sol
+17 −1 test/forge/integration/AuthorizationIntegrationTest.sol
+3 −3 test/forge/integration/BorrowIntegrationTest.sol
+5 −0 test/forge/integration/CallbacksIntegrationTest.sol
+22 −20 test/forge/integration/CreateMarketIntegrationTest.sol
+66 −4 test/forge/integration/LiquidateIntegrationTest.sol
+3 −2 test/forge/integration/OnlyOwnerIntegrationTest.sol
+12 −0 test/forge/integration/SupplyCollateralIntegrationTest.sol
+12 −0 test/forge/integration/SupplyIntegrationTest.sol
+1 −1 test/forge/integration/WithdrawCollateralIntegrationTest.sol
+5 −3 test/forge/invariant/MorphoInvariantTest.sol
+14 −0 test/forge/libraries/SafeTransferLibTest.sol
+31 −1 test/hardhat/Morpho.spec.ts
+0 −288 test/morpho_tests.tree
+1 −1 tsconfig.json
10 changes: 3 additions & 7 deletions src/MetaMorpho.sol
Original file line number Diff line number Diff line change
Expand Up @@ -738,17 +738,13 @@ contract MetaMorpho is ERC4626, ERC20Permit, Ownable2Step, Multicall, IMetaMorph

if (supplyCap > 0) {
if (!marketConfig.enabled) {
supplyQueue.push(id);
withdrawQueue.push(id);

if (
supplyQueue.length > ConstantsLib.MAX_QUEUE_LENGTH
|| withdrawQueue.length > ConstantsLib.MAX_QUEUE_LENGTH
) {
revert ErrorsLib.MaxQueueLengthExceeded();
}
if (withdrawQueue.length > ConstantsLib.MAX_QUEUE_LENGTH) revert ErrorsLib.MaxQueueLengthExceeded();

marketConfig.enabled = true;

emit EventsLib.SetWithdrawQueue(msg.sender, withdrawQueue);
}

marketConfig.removableAt = 0;
Expand Down
13 changes: 8 additions & 5 deletions src/interfaces/IMetaMorpho.sol
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ interface IMetaMorphoBase {
/// @notice Revokes the pending cap of the market defined by `id`.
function revokePendingCap(Id id) external;

/// @notice Submits a forced market removal from the vault, potentially losing all funds supplied to the market.
/// @dev Warning: Submitting a forced removal will overwrite the timestamp at which the market will be removable.
/// @notice Submits a forced market removal from the vault, eventually losing all funds supplied to the market.
function submitMarketRemoval(Id id) external;

/// @notice Revokes the pending removal of the market defined by `id`.
Expand Down Expand Up @@ -143,9 +142,11 @@ interface IMetaMorphoBase {
/// @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 Removing a market requires the vault to have 0 supply on it; but anyone can supply on behalf of the
/// vault so the call to `updateWithdrawQueue` can be griefed by a frontrun. To circumvent this, the allocator can
/// simply bundle a reallocation that withdraws max from this market with a call to `updateWithdrawQueue`.
/// @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
/// market to be empty can be griefed by a front-run. To circumvent this, the allocator can simply bundle a
/// reallocation that withdraws max from this market with a call to `updateWithdrawQueue`.
/// @dev Warning: Removing a market with supply will decrease the fee accrued until the next deposit/withdrawal.
/// @param indexes The indexes of each market in the previous withdraw queue, in the new withdraw queue's order.
function updateWithdrawQueue(uint256[] calldata indexes) external;
Expand All @@ -159,6 +160,8 @@ interface IMetaMorphoBase {
/// reallocation.
/// - Donations to the vault on markets that are expected to be supplied to during reallocation.
/// - Withdrawals from markets that are expected to be withdrawn from during reallocation.
/// @dev Sender is expected to pass `assets = type(uint256).max` with the last MarketAllocation of `allocations` to
/// supply all the remaining withdrawn liquidity, which would ensure that `totalWithdrawn` = `totalSupplied`.
function reallocate(MarketAllocation[] calldata allocations) external;
}

Expand Down
1 change: 1 addition & 0 deletions test/forge/MetaMorphoInternalTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ contract MetaMorphoInternalTest is InternalTest {

Id id = allMarkets[0].id();
_setCap(id, CAP);
supplyQueue = [id];

loanToken.setBalance(SUPPLIER, suppliedAmount);
vm.prank(SUPPLIER);
Expand Down
13 changes: 13 additions & 0 deletions test/forge/helpers/IntegrationTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ contract IntegrationTest is BaseTest {
function _setCap(MarketParams memory marketParams, uint256 newCap) internal {
Id id = marketParams.id();
uint256 cap = vault.config(id).cap;
bool isEnabled = vault.config(id).enabled;
if (newCap == cap) return;

PendingUint192 memory pendingCap = vault.pendingCap(id);
Expand All @@ -115,6 +116,18 @@ contract IntegrationTest is BaseTest {
vault.acceptCap(id);

assertEq(vault.config(id).cap, newCap, "_setCap");

if (newCap > 0) {
if (!isEnabled) {
Id[] memory newSupplyQueue = new Id[](vault.supplyQueueLength() + 1);
for (uint256 k; k < vault.supplyQueueLength(); k++) {
newSupplyQueue[k] = vault.supplyQueue(k);
}
newSupplyQueue[vault.supplyQueueLength()] = id;
vm.prank(ALLOCATOR);
vault.setSupplyQueue(newSupplyQueue);
}
}
}

function _sortSupplyQueueIdleLast() internal {
Expand Down

0 comments on commit 99651fd

Please sign in to comment.