Sneaky Macaroon Sealion
Medium
Handling of ss.oAmount
in defiToStablecoinSwap
and swap
functions (under certain swap conditions) when fBalance - iBalance == 0
greatly differ despite which can lead to stablecoin swaps being done for free or users paying for both defiswap and stablecoin swap.
defiToStablecoinSwap
function has three major steps, it performs a defi swap, sets ss.oAmount
to balance difference before and after the defi swap and performs a 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);
@>1 _defiSwap(wallet, defi);
uint256 fBalance = ERC20(ss.origin).balanceOf(wallet);
@>2 ss.oAmount = fBalance - iBalance;
//change balance to reflect change
@>3 _stablecoinSwap(wallet, ss);
}
Also, under the hood, directional swap
function when ss.destination
destination is is not 0, functions exactly as a defi to stablecoin swap. The function first performs a _defiSwap
and later performs a _stablecoinSwap
swap but in between sets ss.oAmount
to balance difference before and after the defi swap. The difference here being that ss.oAmount
is only set if fBalance - iBalance == 0
function swap(
address wallet,
bool directional,
StablecoinSwap memory ss,
DefiSwap memory defi
) external payable onlyRole(SWAPPER_ROLE) whenNotPaused {
//...
if (directional) {
// if only defi swap
if (ss.destination == address(0)) _defiSwap(wallet, defi);
else {
// if defi then stablecoin swap
//check balance to adjust second swap
uint256 iBalance = ERC20(ss.origin).balanceOf(wallet);
@>1 if (defi.walletData.length != 0) _defiSwap(wallet, defi);
uint256 fBalance = ERC20(ss.origin).balanceOf(wallet);
//change balance to reflect change
@>2 if (fBalance - iBalance != 0) ss.oAmount = fBalance - iBalance;
@>3 _stablecoinSwap(wallet, ss);
}
//...
}
As can be seen, even though the functions(swap function under some conditions) perform the same steps, the ss.oAmount
set during for stablecoin swap in the two functions are different and in case of the defiToStablecoinSwap
function, can lead to users conducting free swaps.
No response
No response
No response
Users conducting free swaps with 0 amount.
No response
Add the if (fBalance - iBalance != 0)
check to defiToStablecoinSwap
function.