Skip to content

Latest commit

 

History

History
94 lines (70 loc) · 4.68 KB

095.md

File metadata and controls

94 lines (70 loc) · 4.68 KB

Daring Zinc Porcupine

High

defiToStablecoinSwap is flawed causing loss of funds

Summary

defiToStablecoinSwap allows the wallet to swap some non xyz stablecoin or other erc20 into a stable coin. The function then does a stablecoinswap. The problem occurs if the user has already 100 of the stable coin and intends to do the defi swap so that he now has 200 of the stable coin, the flow will not allow the user to do a 200 value stable coin swap.

Root Cause

in AmirX.sol ln 111 https://github.com/sherlock-audit/2024-11-telcoin/blob/b9c751b59e78a7123a636e31ecafc9147046f190/telcoin-audit/contracts/swap/AmirX.sol#L111

the function is meant to do a defi swap and then feed these proceeds in order to do the stablecoin swap.

    function defiToStablecoinSwap(
        address wallet,
        StablecoinSwap memory ss,
        DefiSwap memory defi
    ) external payable onlyRole(SWAPPER_ROLE) whenNotPaused {
        // checks if defi will fail
        _verifyDefiSwap(wallet, defi);
        // checks if stablecoin swap will fail
        _verifyStablecoinSwap(wallet, ss);

        //check balance to adjust second swap
        uint256 iBalance = ERC20(ss.origin).balanceOf(wallet);
        _defiSwap(wallet, defi);
        uint256 fBalance = ERC20(ss.origin).balanceOf(wallet);
        ss.oAmount = fBalance - iBalance;
        //change balance to reflect change
        _stablecoinSwap(wallet, ss);
    }

From the function we can observe the flow.

  1. first the params are checked for both the defi and stable coin swap
  2. we now check the balance of the wallet and do the defi swap
  3. the after balance is checked and ss.oAmount is set to the difference of the balances after the swap.
  4. Using the new ss.oAmount we now do the stablecoinswap.

The issue lies in a situation where a user has 100 stablecoin and 100 of another erc20. The user wants to sell the erc20 by defi swap and using the proceeds he wants to do a stablecoin swap. For example if the defi swap yields him 100 stable coin, he now has 200 and wants to do the stablecoin swap with that amount. since the code incorrectly overrides the ss.oAmount, the user will pay less stablecoin and receive the same amount in ss.tAmount.

lets observe the flow to explain

  1. user has 100 stablecoin and 100 of other erc20
  2. he wants to sell the 100 of erc20 in the defi swap portion so that this value feeds into his stablecoin balance
  3. using his higher balance, lets say the defi swap gave him 100 more stablecoin, he now wants to use his 200 stablecoin to swap for another stablecoin in the _stablecoinSwap of the function.
  4. the users params for the stablecoin swap will include ss.oAmount = 200 and ss.tAmount = 200
  5. the problem occurs here
        uint256 iBalance = ERC20(ss.origin).balanceOf(wallet);
        _defiSwap(wallet, defi);
        uint256 fBalance = ERC20(ss.origin).balanceOf(wallet);
        ss.oAmount = fBalance - iBalance;
  1. the ss.oAmount is overridden, the code incorrectly assumes the users _stablecoinSwap was only meant to use the balance received from the defi swap, but instead the user wanted to feed his stable coin amount from the defiswap and then use the new increased stable coin amount to complete the stablecoin swap.
  2. this will result in ss.oAmount being changed to 100 while ss.tAmount remains 200.
  3. the stablecoin swap happens and the user is only charged 100 of the origin stablecoin for 200 of the target stablecoin.
  4. the protocol sees a loss of 100 of target stablecoin.

We can tell this is flawed logic because the inverse function of this , stablecoinToDefiSwap will not cause an issue when doing the same operations in reverse.

Internal pre-conditions

  1. user already holds some of the origin stabelcoin
  2. user is planning to increase his stablecoin amount first in the defiswap portion in order to complete the stablecoin part.

External pre-conditions

No response

Attack Path

  1. user has params as follows.
  2. he will hold 100 stablecoin in wallet
  3. he wants to swap 100 of other erc20 for the same stablecoin
  4. his account will now have 200 of stablecoin
  5. with the balance of 200 stable coin he wants to complete the stablecoin swap for 200 of another stablecoin
  6. the user's ss.oAmount is incorrectly overriden after the defiswap while ss.tAmount remains unchanged
  7. stable coin swap happens and user is only charged 100 of origin stablecoin for 200 of target stablecoin.

Impact

protocol loss of funds.

PoC

No response

Mitigation

Do not override the ss.oAmount. We are already making sure the rate of stablecoins is correct in the front end. If the defi swap does not yield enough stable coin to cover the stable coin portion of the swap, the tx will revert anyway.