Skip to content

Latest commit

 

History

History
137 lines (93 loc) · 5.27 KB

026.md

File metadata and controls

137 lines (93 loc) · 5.27 KB

Soaring Pebble Meerkat

Medium

Issue with FOT stable token

Summary

All swaps going from defi swap to stable swap route consider FOT tax, but when the stable coin which is exetrnal applies FOT, then the swaps break

Root Cause

if the token target is not a recognized stablecoin (XYZ) during a stablecoin to defi swap on AmirX.swap with directional == false will cause issue when that target stable token is a fee on transfer token. ex: USDC might switch on fees, but code here is not modifying accordingly.

Internal pre-conditions

user swapping on AmirX.swap with directional == false

External pre-conditions

A stable coin from liquidity safe which is not a recognized stablecoin (XYZ), turns on fee to charge fee on transfer tax.

Attack Path

  1. user want to do a swap from stablecoin to _defiSwap in a non directional way of AmirX.swap

  2. But the origin token is a external stablecoin(ex: ENA, GHO, USDC, USDT). So he wants to swap stablecoin native to telcoin into exetrnal stablecoin like ENA, into a defi swap (ENA to WETH). In this case he will call AmirX.swap with directional == false.

  3. The issue is if the external stablecoin like USDC, ENA, switches on the fee on transfer tax, then the code is not modifying the wallet data that swaps external stable coin into WETH.

  4. look at line 93, the ss.oAmount is modified to latest balance if any fee on tax is applied during defi to stablecoin swap route. But, when stablecoin to defi route, the code is not considering this by assuming all stable coins are FOT tax free. But they can switch on whenever they want. Lately, ENA received a proposal to switch on. USDC or USDT might do it when they want extra fees.

https://github.com/sherlock-audit/2024-11-telcoin/blob/b9c751b59e78a7123a636e31ecafc9147046f190/telcoin-audit/contracts/swap/AmirX.sol#L73-L102

https://github.com/sherlock-audit/2024-11-telcoin/blob/b9c751b59e78a7123a636e31ecafc9147046f190/telcoin-audit/contracts/stablecoin/StablecoinHandler.sol#L144-L182

AmirX.sol

73:     function swap(
74:         address wallet,
75:         bool directional,
76:         StablecoinSwap memory ss,
77:         DefiSwap memory defi
78:     ) external payable onlyRole(SWAPPER_ROLE) whenNotPaused {
80:         if (ss.destination != address(0)) _verifyStablecoinSwap(wallet, ss);
81:         if (defi.walletData.length != 0) _verifyDefiSwap(wallet, defi);
82: 
83:         if (directional) {
85:             if (ss.destination == address(0)) _defiSwap(wallet, defi);
86:             else {
89:                 uint256 iBalance = ERC20(ss.origin).balanceOf(wallet);
90:                 if (defi.walletData.length != 0) _defiSwap(wallet, defi);
91:                 uint256 fBalance = ERC20(ss.origin).balanceOf(wallet);

93:    >>>          if (fBalance - iBalance != 0) ss.oAmount = fBalance - iBalance;
94:                 _stablecoinSwap(wallet, ss);
95:             }
96:         } else {
97:             // if stablecoin swap
99:    >>>      _stablecoinSwap(wallet, ss);
100:             // if only stablecoin swap
101:   >>>       if (defi.walletData.length != 0) _defiSwap(wallet, defi);
102:         }
103:     }


StablecoinHandler.sol

140:     function _stablecoinSwap(
141:         address wallet,
142:         StablecoinSwap memory ss
143:     ) internal {
144:         if (
145:             ss.stablecoinFeeCurrency != address(0) &&
146:             ss.stablecoinFeeSafe != address(0)
147:         )
149:                 then make swap for free ?, or evern use 0rigin asset as this token and pswap out to anyone
150:                 for free colateral ? */
151:             ERC20PermitUpgradeable(ss.stablecoinFeeCurrency).safeTransferFrom(
152:                 wallet,
153:                 ss.stablecoinFeeSafe,
154:                 ss.feeAmount
155:             );
156: 
157:         // Handle the transfer or burning of the origin currency:
158:         // If the origin is a recognized stablecoin (XYZ), burn the specified amount from the wallet.
159:         if (isXYZ(ss.origin)) {
160:             Stablecoin(ss.origin).burnFrom(wallet, ss.oAmount);
161:         } else {
163:   >>>       ERC20PermitUpgradeable(ss.origin).safeTransferFrom(
164:                 wallet,
165:                 ss.liquiditySafe,
166:                 ss.oAmount
167:             );
168:         }
169: 
170:         // Handle the minting or transferring of the target currency:
171:         // If the target is a recognized stablecoin (XYZ), mint the required amount to the destination address.
172:         if (isXYZ(ss.target)) {
173:             Stablecoin(ss.target).mintTo(ss.destination, ss.tAmount);
174:         } else {
176:   >>>       ERC20PermitUpgradeable(ss.target).safeTransferFrom(
177:                 ss.liquiditySafe,
178:                 ss.destination,
179:                 ss.tAmount
180:             );
181:         }
182:     }

Impact

The defi swaps will fail due to the FOT stable coin when swapping from stable coin to defi swap,because the wallet data is not updated considering the received stables after FOT tax. All swaps going from defi swap to stable swap route consider FOT tax, but the above mentioned case doesn’t consider . Swaps fail on AmirX.swap with directional == false. so, DOS. PoCMitigation

PoC

No response

Mitigation

No response