sherlock-audit / 2023-04-unitasprotocol-judging

4 stars 3 forks source link

Yuki - Swap result is calculated with a wrong price when buying USD1. #79

Closed sherlock-admin closed 1 year ago

sherlock-admin commented 1 year ago

Yuki

high

Swap result is calculated with a wrong price when buying USD1.

Summary

Swaps are made based on a wrong token price, when buying USD1.

Vulnerability Detail

At the end of the function _getSwapResults an if statement is triggered when tokenIn equals priceQuoteToken, this indicated the swap is used in order to buy USD1 and that the oracle price should be inverted.

By the dev comment - it is cleary stated that the price should be inverted when the swap is used for buying USD1.

https://github.com/sherlock-audit/2023-04-unitasprotocol/blob/main/Unitas-Protocol/src/Unitas.sol#L461-L464

But since the if statement is applied at the end of the function, nothing actually happens and the swap result is already calculated using the wrong price.

https://github.com/sherlock-audit/2023-04-unitasprotocol/blob/main/Unitas-Protocol/src/Unitas.sol#L445-L465

Impact

Swaps are made based on a wrong token price, when buying USD1.

Code Snippet

https://github.com/sherlock-audit/2023-04-unitasprotocol/blob/main/Unitas-Protocol/src/Unitas.sol#L445-L464

https://github.com/sherlock-audit/2023-04-unitasprotocol/blob/main/Unitas-Protocol/src/Unitas.sol#L461-L464

Tool used

Manual Review

Recommendation

When a swap is made in order to buy USD1, the oracle price should be inverted before the function calculates the swap result:

        SwapRequest memory request;
        request.tokenIn = tokenIn;
        request.tokenOut = tokenOut;
        request.amountType = amountType;
        request.amount = amount;
        request.feeNumerator = feeNumerator;
        request.feeBase = tokenManager.SWAP_FEE_BASE();
        request.feeToken = address(feeToken);
        request.price = price;
        request.priceBase = 10 ** oracle.decimals();
        request.quoteToken = priceQuoteToken;

        if (tokenIn == priceQuoteToken) {
            // The base currency of oracle price is USD1, inverts the price when buying USD1
            price = request.priceBase * request.priceBase / price;
            request.price = price;
        }

        (amountIn, amountOut, fee) = _calculateSwapResult(request);

        _require(amountIn > 0 && amountOut > 0, Errors.SWAP_RESULT_INVALID);