Assessment reports>Beefy UniswapV3>Medium findings>Withdrawals from vault might revert after donations
Category: Coding Mistakes

Withdrawals from vault might revert after donations

Medium Severity
Low Impact
Low Likelihood

Description

The BeefyVaultConcLiq contract's withdraw function allows holders of the vault's shares to redeem them against the two tokens. The function calculates the amounts of the two tokens the users should be transferred, _amount0 and _amount1, and obtains the balances before0 and before1 that the vault contract currently holds in these tokens. During normal operations, these values would be zero (see also ref). If the balance the vault holds is not enough to redeem the shares, the necessary tokens are withdrawn from the strategy contract. This is done starting from line 227:

if (before0 < _amount0 ||  before1 < _amount1) {

    uint _withdraw0 = _amount0 - before0;
    uint _withdraw1 = _amount1 - before1;

    strategy.withdraw(_withdraw0, _withdraw1);

This code will revert due to an arithmetic underflow if the branch is taken because one of the before values is smaller than the corresponding _amount value, but the other before value is larger than the corresponding _amount value (for example, if before0 < _amount0 but before1 < _amount1).

Impact

Assume, as will be the case during normal operations, that the vault does not hold any of token0 or token1. An attacker could transfer some amount of one token, say x of token0, to the vault. Withdrawals of amounts of token0 smaller than x would then revert. This issue thus allows a denial-of-service attack on withdrawals, albeit one at a potentially significant cost to the attacker.

Recommendations

Consider replacing

uint _withdraw0 = _amount0 - before0;

by

uint _withdraw0;
if (_amount0 >= before0) _withdraw0 = _amount0 - before0;

to make _withdraw0 zero when _amount0 < before0, and analogously for _withdraw1.

Alternatively, given that the vault should not hold tokens during normal operations (see also ref), the logic in withdraw could be simplified by always withdrawing the full amounts needed from the strategy contract and not using any tokens sent to the vault directly. This would mean, however, that any token0 or token1 sent to the vault accidentally would be stuck instead of being treated as a donation and used on withdrawals.

Remediation

This issue has been acknowledged by Beefy, and a fix was implemented in commit 8ff8e999.

Zellic © 2024Back to top ↑