Muscular Alabaster Deer
High
Fee-on-Transfer Tokens May Cause Insufficient/Reduced Balances in ss.liquiditySafe, ss.stablecoinFeeSafe, and defi.defiSafe
The reliance on direct token transfers in _stablecoinSwap
and _feeDispersal
without validating the actual token balances will cause insufficient/reduced balances in ss.liquiditySafe
, ss.stablecoinFeeSafe
, and defi.defiSafe
as fee-on-transfer tokens deduct a portion of the transferred amount, leading to future transaction failures or reverts when those balances are insufficient to make a transfer from ss.liquiditySafe
to ss.destination
.
Note: The contest details specify "user's might get less than expected", but NOT the protocol. Additionally, per the sponsor's confirmation, FOT are not in the contract prior. When the wallet does the defi swap some of the funds are sent to the user and the fee is sent to AmirX. Previously the Swapper sent this fund in but that's not what they want here; they should want to use the balance that is sent back from AmirX.
In StablecoinHandler.sol and AmirX.sol, the protocol does not account for fee-on-transfer behavior in the following scenarios:
_stablecoinSwap
: When transferring fee-on-transfer tokens toss.liquiditySafe
or fromss.liquiditySafe
toss.destination
, the intermediary balance may not match the expected amount. The same shall apply when transferring fromwallet
toss.stablecoinFeeSafe
._feeDispersal
and_buyBack
: Fee-on-transfer tokens converted to TELCOIN result in less TELCOIN being deposited intodefi.defiSafe
.
- Swapper Role initiates a swap where
ss.origin
orss.target
is a fee-on-transfer token. - A portion of the token amount is deducted as a transfer fee.
- Swapper Role assumes the nominal
ss.oAmount
will fully transfer without validating post-transfer balances. This also incurs protocol loss for the reduced amount received byss.stablecoinFeeSafe
- TELCOIN buybacks convert fee-on-transfer tokens with reduced amounts reaching
defi.defiSafe
.
- The protocol integrates with fee-on-transfer tokens for swaps or buybacks.
- Fee-on-transfer tokens are held by
wallet
and used asss.origin
,ss.target
, orfeeToken
for buyback operations.
Scenario 1: Insufficient ss.liquiditySafe
Balance
Transaction A: ss.origin
is a fee-on-transfer token.
- When transferring to
ss.stablecoinFeeSafe
andss.liquiditySafe
, the received amount is less than expected. Transaction B:ss.target
is a fee-on-transfer token. ss.liquiditySafe
attempts to transferss.tAmount
toss.destination
.- If Transaction A and B involve the same nominal amount, the reduced balance in
ss.liquiditySafe
will cause Transaction B to fail.
Scenario 2: Reduced defi.defiSafe
Balance
- The protocol collects fee-on-transfer tokens and converts them to TELCOIN during
_buyBack
. - Due to the transfer fee, less TELCOIN is deposited into
defi.defiSafe
.
Scenario 3: Reduced ss.stablecoinFeeSafe
Balance
- Fee-on-transfer tokens are transferred to
ss.stablecoinFeeSafe
. - The safe receives less than the expected fee amount, leading to discrepancies in protocol fee accounting.
- The protocol suffers transaction reverts or operational failures due to insufficient balances in
ss.liquiditySafe
, and a direct loss indefi.defiSafe
, andss.stablecoinFeeSafe
. - This disrupts core swap and fee-handling functionalities, potentially leading to loss of user trust and protocol downtime/losses.
No response
After transferring tokens, compare pre- and post-transfer balances to ensure the correct amounts are received. This should concern only the protocol per the readme detail. For instance, the following logic may be incorporated in _stablecoinSwap()
when handling the transfer of the origin currency:
uint256 preBalance = IERC20(ss.origin).balanceOf(ss.liquiditySafe);
IERC20(ss.origin).safeTransferFrom(wallet, ss.liquiditySafe, ss.oAmount);
uint256 postBalance = IERC20(ss.origin).balanceOf(ss.liquiditySafe);
require(postBalance - preBalance >= ss.oAmount, "Insufficient tokens received due to fee-on-transfer.");