DeFiFoundry
50,000 USDC
View results
Submission Details
Severity: low
Invalid

Swapping via Paraswap won't work because of incorrect data type

Summary

The simpleSwap() function take the SimpleData type as a paramter. However, incorrect validation of the SimpleData type in the swap() and _validateCallData() functions in the ParaSwapUtils will make all swaps failed.

Vulnerability Details

The ParaSwapUtils library intends to perform swapping operations via Paraswap.

library ParaSwapUtils {
using SafeERC20 for IERC20;
function swap(address to, bytes memory callData) external {
_validateCallData(to, callData);
address approvalAddress = IAugustusSwapper(to).getTokenTransferProxy();
address fromToken;
uint256 fromAmount;
assembly {
fromToken := mload(add(callData, 68))
fromAmount := mload(add(callData, 100))
}
IERC20(fromToken).safeApprove(approvalAddress, fromAmount);
(bool success, ) = to.call(callData);
require(success, "paraswap call reverted");
}
function _validateCallData(address to, bytes memory callData) internal view {
require(to == address(0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57), "invalid paraswap callee");
address receiver;
assembly {
receiver := mload(add(callData, 196))
}
require(receiver == address(this), "invalid paraswap calldata");
}
}

If we check the contract 0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57 in Arbitrum and Avalanche, the swapSimple() functions of the swapper takes a single SimpleData struct parameter.

function simpleSwap(Utils.SimpleData memory data) public payable returns (uint256 receivedAmount) {
... ...
}
struct SimpleData {
address fromToken;
address toToken;
uint256 fromAmount;
uint256 toAmount;
uint256 expectedAmount;
address[] callees;
bytes exchangeData;
uint256[] startIndexes;
uint256[] values;
address payable beneficiary;
address payable partner;
uint256 feePercent;
bytes permit;
uint256 deadline;
bytes16 uuid;
}

Therefore, the callData in the ParaSwapUtils::swap() function should match with the abi.encodeWithSelector(<Swapper.simpleSwap.selector>, <SimpleData type variable>).

However, callData doesn't match with the SimpleData type at all.

  • fromToken is being taken from offset 68 which should be from 4.

  • fromAmount is being taken from offset 100 which should be from 68.

  • receiver(beneficiary in SimpleData type) is being taken from offset 196, but it's calculation is more complex to calculate.

Impact

DEX swapping won't work at all.

Tools Used

Manual Review

Recommendations

Update parsing the callData parameter to match with SimpleData type.

Updates

Lead Judging Commences

n0kto Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

invalid_ParaswapUtils_incorrect_offset_SimpleSwap

Keepers use megaSwap with this struct: struct MegaSwapSellData { address fromToken; uint256 fromAmount; uint256 toAmount; uint256 expectedAmount; address payable beneficiary; Utils.MegaSwapPath[] path; address payable partner; uint256 feePercent; bytes permit; uint256 deadline; bytes16 uuid; } 32 first bytes of callData bytes array → length of the bytes array. 4 bytes selector, 32 bytes → offset of the struct → 68 bytes before the fromToken.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!