53022 sc critical funds are not properly refunded to user which calls for swap on the dex aggregator
Description
Brief / Intro
Vulnerability Details
function swap(
IAggregationExecutor executor,
SwapDescription calldata desc,
bytes calldata data
)
external
payable
whenNotPaused()
returns (
uint256 returnAmount,
uint256 spentAmount
)
{
if (desc.minReturnAmount == 0) revert ZeroMinReturn();
IERC20 srcToken = desc.srcToken;
IERC20 dstToken = desc.dstToken;
bool srcETH = srcToken.isETH();
if (desc.flags & _REQUIRES_EXTRA_ETH != 0) {
if (msg.value <= (srcETH ? desc.amount : 0)) revert RouterErrors.InvalidMsgValue();
} else {
if (msg.value != (srcETH ? desc.amount : 0)) revert RouterErrors.InvalidMsgValue();
}
if (!srcETH) {
srcToken.safeTransferFromUniversal(msg.sender, desc.srcReceiver, desc.amount, desc.flags & _USE_PERMIT2 != 0);
}
returnAmount = _execute(executor, msg.sender, desc.amount, data);
spentAmount = desc.amount;
if (desc.flags & _PARTIAL_FILL != 0) {
uint256 unspentAmount = srcToken.uniBalanceOf(address(this));
if (unspentAmount > 1) {
// we leave 1 wei on the router for gas optimisations reasons
unchecked { unspentAmount--; }
spentAmount -= unspentAmount;
srcToken.uniTransfer(payable(msg.sender), unspentAmount);
}
if (returnAmount * desc.amount < desc.minReturnAmount * spentAmount) revert RouterErrors.ReturnAmountIsNotEnough(returnAmount, desc.minReturnAmount * spentAmount / desc.amount);
} else {
if (returnAmount < desc.minReturnAmount) revert RouterErrors.ReturnAmountIsNotEnough(returnAmount, desc.minReturnAmount);
}
address payable dstReceiver = (desc.dstReceiver == address(0)) ? payable(msg.sender) : desc.dstReceiver;
dstToken.uniTransfer(dstReceiver, returnAmount);
}Impact Details
References
Proof of Concept
Suggested Remediation (high level)
Previous53025 sc high commission on removed tokens is unclaimableNext53021 sc medium deposit and bridge workflow bricked by immediate share lock users cannot bridge immediately after deposit
Was this helpful?