sherlock-audit / 2023-04-splits-judging

4 stars 1 forks source link

Dug - With a pricing discount, value can be stolen from swappers 1 wei at a time #85

Closed sherlock-admin closed 1 year ago

sherlock-admin commented 1 year ago

Dug

medium

With a pricing discount, value can be stolen from swappers 1 wei at a time

Summary

Because of how _getQuoteAmount() is implemented in UniV3OracleImpl, 1 wei worth of a base token returns a quote amount of 0. This means that a user can withdraw 1 wei of a base token from a swapper without requiring any amount of $tokenToBeneficiary.

Vulnerability Detail

The _getQuoteAmount() function in UniV3OracleImpl is implemented with the the two following conditional return statements, both of which scale the amount based on the scaledOfferFactor:

// skip oracle if converted tokens are equal
if (cqp.cBase == cqp.cQuote) {
    return quoteParams_.baseAmount * po.scaledOfferFactor / PERCENTAGE_SCALE;
}

...

return unscaledAmountToBeneficiary * po.scaledOfferFactor / PERCENTAGE_SCALE;

Generally, for the swapper to incentivize users to execute swaps, a scaled offer factor less that 100% is used (i.e. a scaledOfferFactor less than 100_00_00). This means that the amount of quote tokens returned by _getQuoteAmount() is rounded down. This is fine for most cases, but if the amount of the base token is 1 wei, the amount of quote tokens returned is 0.

Impact

There are a couple immediate issues that come from this. The most obvious is a user can simply remove value from the swapper 1 wei at a time. While this is not a huge issue on mainnet, the project overview implies that other networks are considered in the future. In that situation, with lower transaction costs, this issue becomes more severe, especially when considering tokens with a low decimal value such as WBTC.

Another issue is that other users attempting to swap tokens for the full amount of a base token in the swapper could be griefed. A user could frontrun their transaction, removing 1 wei of the base token from the swapper. This would cause the transaction to revert as it attempts to withdraw more base tokens than are available.

Code Snippet

https://github.com/sherlock-audit/2023-04-splits/blob/main/splits-oracle/src/UniV3OracleImpl.sol#L248-L285

Tool used

Manual Review

Recommendation

Update the _getQuoteAmount() function to round up to the next wei instead of down when applying a discount.

Duplicate of #104