Skip to content

Latest commit

 

History

History
79 lines (60 loc) · 2.39 KB

075.md

File metadata and controls

79 lines (60 loc) · 2.39 KB

Bright Violet Crocodile

Medium

Defi Swaps may end up with the same iBalance and fBalance which will incorrectly update ss.oAmount

Summary

In AmirX::swap(), it updates ss.oAmount when the final ss.origin amount is different than the initial one. However, it should always update ss.oAmount as this is the most correct amount from the swap and it should not transfer funds from the wallet that were not swapped.

Root Cause

In AmirX:93, it does not always update ss.oAmount, spending extra funds from the user that were not provided by the swap.

Internal pre-conditions

None.

External pre-conditions

None.

Attack Path

User calls AmirX:swap() with an amount that leads to the same ss.origin balance before and after the swap. This may happen due to a combination of slippage and paying fees using a feeToken equal to ss.origin.

Suppose the user had 100 USDC and 5 AAVE in the wallet and defi swapped 5 AAVE for USDC. If the slippage + fees lead to a final wallet balance of 100 USDC, ss.oAmount will not be updated to 0 and it will transfer USDC out of the wallet which will end up with less than 100 USDC, when it should end up with exactly 100 USDC.

Impact

The swapper transfers more ss.origin tokens out of the wallet than what the wallet swapped, which should never happen.

PoC

function swap(
    address wallet,
    bool directional,
    StablecoinSwap memory ss,
    DefiSwap memory defi
) external payable onlyRole(SWAPPER_ROLE) whenNotPaused {
    ...
    if (directional) {
        // if only defi swap
        if (ss.destination == address(0)) _defiSwap(wallet, defi);
        else {
            ...
            if (fBalance - iBalance != 0) ss.oAmount = fBalance - iBalance; //@audit should always update ss.oAmount 
            ...
        }
    } else {
        ...
    }
}

Mitigation

function swap(
    address wallet,
    bool directional,
    StablecoinSwap memory ss,
    DefiSwap memory defi
) external payable onlyRole(SWAPPER_ROLE) whenNotPaused {
    ...
    if (directional) {
        // if only defi swap
        if (ss.destination == address(0)) _defiSwap(wallet, defi);
        else {
            ...
            ss.oAmount = fBalance - iBalance; 
            ...
        }
    } else {
        ...
    }
}