Malicious Users Can Force An Emergency Settlement On Any Vault
Summary
Malicious users can force an emergency settlement on any vault causing a denial of service.
Vulnerability Detail
The following function shows that an emergency settlement can only be triggered if the total number of BPT held by the vault exceeds the BPT threshold.
File: SettlementUtils.sol
86: function _getEmergencySettlementParams(
87: StrategyContext memory strategyContext,
88: PoolContext memory poolContext,
89: uint256 maturity,
90: uint256 totalBPTSupply
91: ) internal view returns(uint256 bptToSettle) {
92: StrategyVaultSettings memory settings = strategyContext.vaultSettings;
93: StrategyVaultState memory state = strategyContext.vaultState;
94:
95: // Not in settlement window, check if BPT held is greater than maxBalancerPoolShare * total BPT supply
96: uint256 emergencyBPTWithdrawThreshold = settings._bptThreshold(totalBPTSupply);
97:
98: if (strategyContext.totalBPTHeld <= emergencyBPTWithdrawThreshold)
99: revert Errors.InvalidEmergencySettlement();
Another point to note is that a major side-effect of an emergency settlement is that the vault will be locked up after the emergency settlement. No one is allowed to enter the vault and users are only allowed to exit from the vault by taking their proportional share of cash and strategy tokens. Thus, if anyone can force an emergency settlement on any vault, it would cause a widespread denial of service.
However, it is possible for anyone to force an emergency settlement on any vault.
Notice that in Line 65 below, the totalBPTSupply used for computing the BPT threshold is the spot/current total supply of BPT of a pool.
The BPT threshold of the vault is 20 BPT (100 * 0.2)
The total number of BTP held by the vault is 15
At this point in time, there is no way for anyone to trigger an emergency settlement on the vault because the total number of BTP held by the vault has not exceeded to BPT threshold yet.
However, since the BPT threshold is calculated on the spot/current total supply of BPT, it can be manipulated within a single block/transaction. BPT can also be obtained from the open market.
A malicious user could obtain a flash-loan DAI and obtain 90 BPT from the open market. He then exits the Balancer pool with all the 90 BPT and redeems the underlying assets, and this will cause the total supply of BPT to fall from 100 to 10.
At this point, the total supply of BPT is 10, so the BPT threshold of the vault will become 2 BPT (10 * 0.2). The malicious user can proceed to trigger the emergency settlement on the vault and cause the vault to be locked up.
After the attack, the attacker proceeds to swap the redeemed underlying assets to the DAI and repay back the loan. Flash-loan cost is 1 wei in dydx, so the cost of attack is limited to slippage during swaps. If swaps involve only stablecoin, then the cost of attack is further reduced since stable swap usually has minimum slippage.
Impact
Malicious users can lock up all the leverage vaults offered by Notional causing denial-of-service. This results in a loss of funds for the protocol as the vault is no longer generating profit for the protocol, and also a loss of funds for vault users as they cannot realize the profits because they are forced to exit the vault prematurely.
The following are various reasons why someone would want to perform a DOS on Notional vaults:
Damage the reputation of Notional, and reduce users' trust in Notional
A competitor who is also offering a leverage vault attempts to bring down Notional
Consider updating the implementation to avoid using the spot/current total supply of BPT to determine the BPT threshold as this can be manipulated within a single block/transaction to force a certain condition. A short-term quick fix would be to hardcode the threshold or have the BTP threshold manually set by Notional governance instead of computing the threshold on the fly.
In addition, the emergency settlement function is permissionless and can be called by anyone. If possible, implement access control to ensure that this function can only be triggered by Notional to reduce the attack surface.
xiaoming90
high
Malicious Users Can Force An Emergency Settlement On Any Vault
Summary
Malicious users can force an emergency settlement on any vault causing a denial of service.
Vulnerability Detail
The following function shows that an emergency settlement can only be triggered if the total number of BPT held by the vault exceeds the BPT threshold.
https://github.com/sherlock-audit/2022-09-notional/blob/main/leveraged-vaults/contracts/vaults/balancer/internal/settlement/SettlementUtils.sol#L86
Another point to note is that a major side-effect of an emergency settlement is that the vault will be locked up after the emergency settlement. No one is allowed to enter the vault and users are only allowed to exit from the vault by taking their proportional share of cash and strategy tokens. Thus, if anyone can force an emergency settlement on any vault, it would cause a widespread denial of service.
However, it is possible for anyone to force an emergency settlement on any vault.
Notice that in Line 65 below, the
totalBPTSupply
used for computing the BPT threshold is the spot/current total supply of BPT of a pool.https://github.com/sherlock-audit/2022-09-notional/blob/main/leveraged-vaults/contracts/vaults/balancer/external/MetaStable2TokenAuraHelper.sol#L52
Assume the following:
maxBalancerPoolShare
of the vault is set to 20%At this point in time, there is no way for anyone to trigger an emergency settlement on the vault because the total number of BTP held by the vault has not exceeded to BPT threshold yet.
However, since the BPT threshold is calculated on the spot/current total supply of BPT, it can be manipulated within a single block/transaction. BPT can also be obtained from the open market.
A malicious user could obtain a flash-loan DAI and obtain 90 BPT from the open market. He then exits the Balancer pool with all the 90 BPT and redeems the underlying assets, and this will cause the total supply of BPT to fall from 100 to 10.
At this point, the total supply of BPT is 10, so the BPT threshold of the vault will become 2 BPT (10 * 0.2). The malicious user can proceed to trigger the emergency settlement on the vault and cause the vault to be locked up.
After the attack, the attacker proceeds to swap the redeemed underlying assets to the DAI and repay back the loan. Flash-loan cost is 1 wei in dydx, so the cost of attack is limited to slippage during swaps. If swaps involve only stablecoin, then the cost of attack is further reduced since stable swap usually has minimum slippage.
Impact
Malicious users can lock up all the leverage vaults offered by Notional causing denial-of-service. This results in a loss of funds for the protocol as the vault is no longer generating profit for the protocol, and also a loss of funds for vault users as they cannot realize the profits because they are forced to exit the vault prematurely.
The following are various reasons why someone would want to perform a DOS on Notional vaults:
Code Snippet
https://github.com/sherlock-audit/2022-09-notional/blob/main/leveraged-vaults/contracts/vaults/balancer/internal/settlement/SettlementUtils.sol#L86 https://github.com/sherlock-audit/2022-09-notional/blob/main/leveraged-vaults/contracts/vaults/balancer/external/MetaStable2TokenAuraHelper.sol#L52
Tool used
Manual Review
Recommendation
Consider updating the implementation to avoid using the spot/current total supply of BPT to determine the BPT threshold as this can be manipulated within a single block/transaction to force a certain condition. A short-term quick fix would be to hardcode the threshold or have the BTP threshold manually set by Notional governance instead of computing the threshold on the fly.
In addition, the emergency settlement function is permissionless and can be called by anyone. If possible, implement access control to ensure that this function can only be triggered by Notional to reduce the attack surface.
Duplicate of #66