Light ModeLight
Light ModeDark

One Bug Per Day

One H/M every day from top Wardens

Checkmark

Join over 1120 wardens!

Checkmark

Receive the email at any hour!

Ad

Rounding error in WUSDA can result in loss of user funds, especially when manipulated by an attacker

criticalCode4rena

Lines of code

https://github.com/code-423n4/2023-07-amphora/blob/daae020331404647c661ab534d20093c875483e1/core/solidity/contracts/core/WUSDA.sol#L247

Vulnerability details

Impact

Due to floor rounding in Solidity, it is possible for rounding errors to affect functions in the WUSDA contract.

Specifically, when WUSDA::_usdaToWUSDA is invoked internally, if _usdaAmount is sufficiently small compared with MAX_wUSDA_SUPPLY (10M) and the total USDA supply then it is possible for the _wusdaAmount return value to round down to 0.

solidity
function _usdaToWUSDA(uint256 _usdaAmount, uint256 _totalUsdaSupply) private pure returns (uint256 _wusdaAmount) { _wusdaAmount = (_usdaAmount * MAX_wUSDA_SUPPLY) / _totalUsdaSupply; }

When calling the WUSDA::deposit/depositTo functions, which call the internal WUSDA::_deposit function with this rounded _wusdaAmount value, the implication is that depositors could receive little/no WUSDA for their USDA. Additionally, calls to the WUSDA::withdraw/withdrawTo functions could be process without actually burning any WUSDA. This is clearly not desirable as USDA can be subsequently redeemed for sUSD (at the expense of the protocol reserves and its other depositors).

solidity
function deposit(uint256 _usdaAmount) external override returns (uint256 _wusdaAmount) { _wusdaAmount = _usdaToWUSDA(_usdaAmount, _usdaSupply()); _deposit(_msgSender(), _msgSender(), _usdaAmount, _wusdaAmount); } function withdraw(uint256 _usdaAmount) external override returns (uint256 _wusdaAmount) { _wusdaAmount = _usdaToWUSDA(_usdaAmount, _usdaSupply()); _withdraw(_msgSender(), _msgSender(), _usdaAmount, _wusdaAmount); }

Even when the USDA supply is sufficiently small to avoid this issue, an attacker could still utilize a sUSD flash loan to artificially inflate the USDA total supply which causes the down rounding, potentially front-running a victim such that their deposit is processed without minting any WUSDA and then withdrawing the inflated USDA supply to repay the flash loan.

Proof of Concept

normal case:

  • Total USDA supply is 10B.
  • Alice calls WUSDA::deposit with _usdaAmount of 1e23 (10_000 tokens).
  • _wusdaAmount is rounded down to 1e20/100 tokens (1e23 * 1e25 / 1e28 = 1e20).
  • Alice receives 100 WUSDA rather than 10_000.
  • In reality, the total supply of sUSD is around 40M, so a more realistic scenario assuming 10M total USDA supply may be that Alice deposits 10e18 and receives 1 WUSDA or 1/10th the expected amount (10e18 * 1e25 / 1e26 = 1e18).

flash loan & attacker front-running case:

  • Total USDA supply is 1M.
  • Alice calls WUSDA::deposit with _usdaAmount of 9.9e22 (99_000 tokens).
  • Attacker front-runs this transaction and calls WUSDA::deposit with _usdaAmount of 3.3e22 (33_000 tokens).
  • Attacker receives 33_000 WUSDA.
  • Attacker takes out a sUSD flash loan of 39M.
  • Attacker deposits 39M sUSD into USDA.
  • Alice's transaction is included here, but _wusdaAmount is rounded down to 24_750 tokens (9.9e22 * 1e25 / 4e25 = 2.475e22).
  • Alice receives 24_750 WUSDA rather than 99_000 (only 1/4 of the expected amount).
  • Attacker backruns Alice's transaction and calls WUSDA::withdraw with _usdaAmount of 132e21 (132_000 tokens).
  • Using the same rounding logic, _wusdaAmount is rounded down to 33_000 tokens (132e21 * 1e25 / 4e25 = 33e22).
  • Attacker withdraws 132_000 WUSDA and receives the 99_000 USDA deposited by Alice in addition to their original 33_000.
  • Attacker redeems USDA, repays the flash loan and profits 90_000 USDA/sUSD at the expense of Alice.

Tools Used

Manual review.

Recommended Mitigation Steps

Consider reverting if either WUSDA::_usdaToWUSDA or WUSDA::_wUSDAToUSDA return a zero value. Also consider multiplication by some scalar precision amount. Protections against manipulation of USDA total supply within a single block would also be desirable, perhaps achievable by implementing some multi-block delay.

Assessed type

Other