diff --git a/package.json b/package.json index e29d195..7343ec1 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "publish:multisig-executor": "npx hardhat w3f-deploy multisig-executor", "test-unit": "forge test --match-path ./test/unit/**.sol", "test-integration": "forge test --match-path './test/integration/**' --fork-url $GOERLI_RPC_URL -vvv", + "test-integration-emergency-withdrawal-updated": "forge test --match-path './test/integration/IntegrationTestEmergencyWithdrawal.sol' --fork-url $GOERLI_RPC_URL -vvv", "coverage": "forge coverage --match-path './test/unit/**' --report summary --report lcov", "build": "forge build", "prettier-format": "prettier --config .prettierrc \"./(src|test|scripts)/**/*.sol\" --write", diff --git a/src/morpho/EmergencyWithdrawal.sol b/src/morpho/EmergencyWithdrawal.sol index 5bf765a..377fc54 100644 --- a/src/morpho/EmergencyWithdrawal.sol +++ b/src/morpho/EmergencyWithdrawal.sol @@ -11,10 +11,12 @@ import {MorphoLib} from "../../lib/metamorpho/lib/morpho-blue/src/libraries/peri import {UtilsLib} from "../../lib/metamorpho/lib/morpho-blue/src/libraries/UtilsLib.sol"; /// @title Emergency Withdrawal Contract +/// @author B.Protocol with a fix from Allez Labs to address attack edge case /// @notice This contract allows for the withdrawal of assets from all non-idle markets to the idle market in case of an emergency. /// It uses various libraries from the MetaMorpho protocol for interacting with the vaults and computing correct values /// Can only be called by a vault allocator to withdraw the maximum amount from all non-idle markets /// @dev this contract must have the allocator role on the vaults +/// Note from Allez Labs: Adding a fix to the emergency withdrawal contract to address an edge case attack vector. contract EmergencyWithdrawal { using MorphoBalancesLib for IMorpho; using MarketParamsLib for MarketParams; @@ -88,5 +90,8 @@ contract EmergencyWithdrawal { // allocations should always be: 1 allocation per non-idle market (should all be withdraws) // and exactly 1 allocation to the idle market with uint.max as the target supply vault.reallocate(allocations); + + // Allez Labs: Setting the supply queue so there are no more supplies possible. + vault.setSupplyQueue(new Id[](0)); } } diff --git a/test/integration/IntegrationTestEmergencyWithdrawal.sol b/test/integration/IntegrationTestEmergencyWithdrawal.sol index f0508ad..a0788e2 100644 --- a/test/integration/IntegrationTestEmergencyWithdrawal.sol +++ b/test/integration/IntegrationTestEmergencyWithdrawal.sol @@ -154,4 +154,16 @@ contract IntegrationTestEmergencyWithdrawal is Test { emergencyContract.withdrawUSDC(); displayMarketStatus("AFTER", USDC_VAULT); } + + function testEmergencyWithdrawETHSupplyQueue() public { + vm.prank(allocator); + emergencyContract.withdrawETH(); + assertEq(ETH_VAULT.supplyQueueLength(), 0); + } + + function testEmergencyWithdrawUSDCSupplyQueue() public { + vm.prank(allocator); + emergencyContract.withdrawUSDC(); + assertEq(USDC_VAULT.supplyQueueLength(), 0); + } }