From 2a6901a87f3016c85b720291c39c5a5fdfb7d715 Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Tue, 6 Aug 2024 17:31:35 +1000 Subject: [PATCH 1/2] Fix checkBalance bug in new OETHVaultCore (#2162) * Added unit test for checkBalance when balance is less than the outstanding requests * Fix _checkBalance so it returns 0 when the amount of WETH in the vault and strategies is less than the outstanding withdrawal requests * Moved asset check to top of _checkBalance --- contracts/contracts/vault/OETHVaultCore.sol | 18 ++++++++++++------ contracts/test/vault/oeth-vault.js | 5 +++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/contracts/contracts/vault/OETHVaultCore.sol b/contracts/contracts/vault/OETHVaultCore.sol index 72ae8f3368..abdcd72948 100644 --- a/contracts/contracts/vault/OETHVaultCore.sol +++ b/contracts/contracts/vault/OETHVaultCore.sol @@ -395,15 +395,21 @@ contract OETHVaultCore is VaultCore { override returns (uint256 balance) { + if (_asset != weth) { + return 0; + } + balance = super._checkBalance(_asset); - if (_asset == weth) { - WithdrawalQueueMetadata memory queue = withdrawalQueueMetadata; - // Need to remove WETH that is reserved for the withdrawal queue - if (balance + queue.claimed >= queue.queued) { - return balance + queue.claimed - queue.queued; - } + WithdrawalQueueMetadata memory queue = withdrawalQueueMetadata; + // If there is not enough WETH in the vault and strategies to cover the outstanding withdrawals. + // It can happen if more than half of the users have requested a withdrawal but have not claimed. + if (balance + queue.claimed < queue.queued) { + return 0; } + + // Need to remove WETH that is reserved for the withdrawal queue + return balance + queue.claimed - queue.queued; } /** diff --git a/contracts/test/vault/oeth-vault.js b/contracts/test/vault/oeth-vault.js index 92d7571af9..60d45f1f99 100644 --- a/contracts/test/vault/oeth-vault.js +++ b/contracts/test/vault/oeth-vault.js @@ -2149,6 +2149,11 @@ describe("OETH Vault", function () { // 100 from mints - 99 outstanding withdrawals - 2 from slashing = -1 value which is rounder up to zero expect(await fixture.oethVault.totalValue()).to.equal(0); }); + it("Should have check balance of zero", async () => { + const { oethVault, weth } = fixture; + // 100 from mints - 99 outstanding withdrawals - 2 from slashing = -1 value which is rounder up to zero + expect(await oethVault.checkBalance(weth.address)).to.equal(0); + }); it("Fail to allow user to create a new request due to too many outstanding requests", async () => { const { oethVault, matt } = fixture; From 3c82454ef6e31b3ff77bfcecfe36f20348d1c8d9 Mon Sep 17 00:00:00 2001 From: Nicholas Addison Date: Tue, 6 Aug 2024 17:32:01 +1000 Subject: [PATCH 2/2] simplified _totalValue by calling _checkBalance (#2163) --- contracts/contracts/vault/OETHVaultCore.sol | 28 ++++++--------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/contracts/contracts/vault/OETHVaultCore.sol b/contracts/contracts/vault/OETHVaultCore.sol index abdcd72948..12b14c3041 100644 --- a/contracts/contracts/vault/OETHVaultCore.sol +++ b/contracts/contracts/vault/OETHVaultCore.sol @@ -399,11 +399,14 @@ contract OETHVaultCore is VaultCore { return 0; } + // Get the WETH in the vault and the strategies balance = super._checkBalance(_asset); WithdrawalQueueMetadata memory queue = withdrawalQueueMetadata; - // If there is not enough WETH in the vault and strategies to cover the outstanding withdrawals. - // It can happen if more than half of the users have requested a withdrawal but have not claimed. + + // If the vault becomes insolvent enough that the total value in the vault and all strategies + // is less than the outstanding withdrawals. + // For example, there was a mass slashing event and most users request a withdrawal. if (balance + queue.claimed < queue.queued) { return 0; } @@ -452,29 +455,14 @@ contract OETHVaultCore is VaultCore { emit AssetAllocated(weth, depositStrategyAddr, allocateAmount); } - /// @dev The total value of all assets held by the vault and all its strategies + /// @dev The total value of all WETH held by the vault and all its strategies /// less any WETH that is reserved for the withdrawal queue. - /// For OETH, this is just WETH in the vault and strategies. /// // If there is not enough WETH in the vault and all strategies to cover all outstanding // withdrawal requests then return a total value of 0. function _totalValue() internal view override returns (uint256 value) { - value = _totalValueInVault() + _totalValueInStrategies(); - - // Need to remove WETH that is reserved for the withdrawal queue. - WithdrawalQueueMetadata memory queue = withdrawalQueueMetadata; - // reserved for the withdrawal queue = cumulative queued total - total claimed - uint256 reservedForQueue = queue.queued - queue.claimed; - - if (value < reservedForQueue) { - // This can happen if the vault becomes insolvent enough that the - // total value in the vault and all strategies is less than the outstanding withdrawals. - // For example, there was a mass slashing event and most users request a withdrawal. - return 0; - } - - // Adjust the total value by the amount reserved for the withdrawal queue - return value - reservedForQueue; + // As WETH is the only asset, just return the WETH balance + return _checkBalance(weth); } /// @dev Only WETH is supported in the OETH Vault so return the WETH balance only