Soaring Pebble Meerkat
Medium
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
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.
user swapping on AmirX.swap
with directional == false
A stable coin from liquidity safe which is not a recognized stablecoin (XYZ)
, turns on fee to charge fee on transfer tax.
-
user want to do a swap from stablecoin to _defiSwap in a non directional way of
AmirX.swap
-
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 callAmirX.swap
withdirectional == false
. -
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.
-
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.
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: }
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
No response
No response