Due to an underflow in Vault._updateCreditDelegations()
when vaults reduce their credit values, Vault.recalculateVaultsCreditCapacity()
will suffer a DoS, preventing the majority of the market-making protocol from interacting with the affected vault.
When Vault.recalculateVaultsCreditCapacity()
is called, one of its steps involves calling Vault._updateCreditDelegations()
, which, as the name implies, updates credit delegations for connected markets. At a certain point during the execution of Vault._updateCreditDelegations()
, the creditDeltaUsdX18
(the difference between the new market credit delegation and the previous one) is calculated (see the code snippet from Vault._updateCreditDelegations()
below).
However, if for any of the connected markets the new credit delegation (newCreditDelegationUsdX18
) is smaller than the previous one (previousCreditDelegationUsdX18
), the subtraction newCreditDelegationUsdX18.sub(previousCreditDelegationUsdX18)
will underflow, causing Vault.recalculateVaultsCreditCapacity()
to revert.
This makes it easy to trigger a denial-of-service (DoS) attack on Vault.recalculateVaultsCreditCapacity()
(whether intentionally or not) since it only requires a vault’s credit to be reduced, which would cause all calls to this function (and any other functions depending on it) to revert. For example, a malicious actor could deposit a significant amount of assets into a target vault and later redeem them (after the withdrawal request delay), leading to the aforementioned underflow during the next call to Vault.recalculateVaultsCreditCapacity()
(see the PoC section at the end of this report).
This issue is particularly problematic because Vault.recalculateVaultsCreditCapacity()
is extensively used throughout the codebase. Some of the important functions that call it:
CreditDelegationBranch.withdrawUsdTokenFromMarket()
CreditDelegationBranch.settleVaultsDebt()
CreditDelegationBranch.rebalanceVaultsAssets()
CreditDelegationBranch.updateVaultCreditCapacity()
VaultRouterBranch.deposit()
VaultRouterBranch.redeem()
VaultRouterBranch.stake()
VaultRouterBranch.unstake()
As a result, DoSing Vault.recalculateVaultsCreditCapacity()
also disrupts a significant portion of the protocol’s market-making functionality when interacting with the affected vault.
As explained above, DoSing Vault.recalculateVaultsCreditCapacity()
will effectively block the usage of the affected vault, because most of the interactions with it will be reverted.
Manual Review.
Consider fixing Vault._updateCreditDelegations()
to be able to deal with negative creditDeltaUsdX18
.
Copy the code below to a file in the test/
folder of the contest repository and run forge build && forge test --match-test POC
.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.