The fromToken
parameter decoded by the ParaSwapUtils::swap
read the value at the wrong offset, causing the subsequent paraswap call to always revert.
The ParaSwapUtils::swap
function is used in the PerpetualVault::_doDexSwap
which itself is called during most of swap actions:
We can see that the function takes a callData
input that is then used to call the to
address, which is verified to always match 0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57
, which is the AugustusSwapper
contract on Arbitrum and Avalanche.
We can also see that some parameters are extracted from callData
using assembly:
fromToken
by reading callData
at offset 68
fromAmount
by reading callData
at offset 100
receiver
by reading callData
at offset 196
Each of these parameters correspond to the third, forth and sixth fields of a struct (if we don't forget to account for the 4-bytes selector at the beginning of the calldata)
Now, if we go check the source code of the AugustusSwapper
at address 0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57
(which correspond to Augustus v5), and look at the Utils.sol
file we find that only one struct correspond to the decoding algorithm used in the ParaSwapUtils
:
The other possible structs (SellData
, MegaSwapSellData
and SimpleData
) have no matching fields with the decoding in the ParaSwapUtils
decoding, hence either the decoding is completely wrong, or it is wrong for fromToken
only.
So, we see that there is an issue in the decoding offset for fromToken
, which should be 36
and not 68
, as in the current implementation the value that will be decoded is toToken
, which will revert as this token is approved L23
but does not correspond to the token to swap.
Wrong calldata decoding causing every call to paraswap to revert.
High likelihood has this will happen every time Paraswap is called, medium/high impact as this will cause the swap to revert every time Paraswap is used.
Update the offset to to correct one:
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.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.