Digital Mandarin Gecko
High
In the AmirX
contract, there is a potential issue in the defiToStablecoinSwap
function where the logic for setting the output amount (ss.oAmount
) after performing a DeFi swap does not validate if the balance change is zero. This can lead to unintended behavior in downstream operations, such as conducting a stablecoin swap with an incorrect or zero amount.
The defiToStablecoinSwap
function calculates the difference between fBalance
and iBalance
after a DeFi swap to set ss.oAmount
, but it does not check if this difference is zero. This lack of validation can result in a stablecoin swap being executed with an incorrect or zero oAmount
, which may cause inconsistent behavior compared to the swap
function.
In defiToStablecoinSwap
function,
https://github.com/sherlock-audit/2024-11-telcoin/blob/main/telcoin-audit/contracts/swap/AmirX.sol#L125
In swap
function,
https://github.com/sherlock-audit/2024-11-telcoin/blob/main/telcoin-audit/contracts/swap/AmirX.sol#L93
swap
function can do functionalities like defiToStablecoinSwap
, stablecoinToDefiSwap
, defiSwap
by changing paramters.
- The
defiToStablecoinSwap
function is called. - A DeFi swap is successfully executed, modifying the token balance.
- The contract is not paused.
- The caller has the
SWAPPER_ROLE
. - For
defiToStablecoinSwap
, input parameterss.oAmount
is not ZERO
- A user or malicious actor triggers the
defiToStablecoinSwap
function. - The DeFi swap does not result in any balance change (i.e.,
fBalance - iBalance
is zero). - The function sets
ss.oAmount
to zero and proceeds with the_stablecoinSwap
operation. - In
_stablecoinSwap
, ifss.oAmount
is zero, the function might still attempt to burn or transfer zero tokens:This can result in unintended behavior, triggering unexpected contract operations.if (isXYZ(ss.origin)) { Stablecoin(ss.origin).burnFrom(wallet, ss.oAmount); } else { ERC20PermitUpgradeable(ss.origin).safeTransferFrom( wallet, ss.liquiditySafe, ss.oAmount ); }
- The
ss.oAmount
being zero can lead to:- Users can get target stable coin without burning.
- Potential issues when zero-amount burns or transfers are attempted.
- Users potentially expecting a swap result but receiving none, causing confusion and inefficiency.
uint256 iBalance = ERC20(ss.origin).balanceOf(wallet);
_defiSwap(wallet, defi); // DeFi swap that does not change balance
uint256 fBalance = ERC20(ss.origin).balanceOf(wallet);
assert(fBalance - iBalance == 0); // Condition met
_stablecoinSwap(wallet, ss); // Executes with zero `ss.oAmount`
Add a condition to check if fBalance - iBalance
is non-zero before assigning it to ss.oAmount
and calling _stablecoinSwap
:
uint256 iBalance = ERC20(ss.origin).balanceOf(wallet);
_defiSwap(wallet, defi);
uint256 fBalance = ERC20(ss.origin).balanceOf(wallet);
if (fBalance - iBalance != 0) {
ss.oAmount = fBalance - iBalance;
}
_stablecoinSwap(wallet, ss);
This ensures that the stablecoin swap only proceeds if there is a valid output amount, preventing zero-amount burns or transfers and aligning the behavior with that of the swap
function.