Due to a mismatch of hardcoded and dynamic calldata offsets in the TSender.huff
and TSender_NoCheck.huff
contracts, both contracts transfer funds to incorrect addresses when called with specific calldata.
The Huff code (TSender.huff
and TSender_NoCheck.huff
) hardcodes certain calldata offset values (e.g., RECIPIENT_ONE_OFFSET = 0xa4
). However, the offset of dynamic types like arrays is not fixed in calldata, leading to incorrect code execution if the calldata is formatted differently than expected.
The current ABI encoding used by Solidity and Vyper does not enforce a fixed order for dynamic type offsets. As a result, both calldata examples below are valid and decoded equivalently by the reference and Yul contracts (see POC below). However, while calldata A works as expected in the Huff contract, calldata B results in transfers to incorrect addresses.
At a specific point in the Huff code, the difference between the recipients
and amounts
array offsets is computed for further use. However, due to the inversion of the recipients
and amounts
array offsets and the use of the hardcoded NUMBER_OF_RECIPIENTS_OFFSET
, this difference becomes zero when calldata B is fed to TSender.huff
(Check this scenario in EVM Playground, the contract bytecode and calldata are already filled in). Consequently, when this difference is subtracted to obtain the correct offset of the current recipient element in the recipients
array, the wrong offset is used. Thus, the current amount value at this offset is incorrectly used both as the amount and as the recipient of the ERC20 transactions (i.e instead of calling transfer(0x4dba461ca9342f4a6cf942abd7eacf8ae259108c, 0x64)
, it calls transfer(0x64, 0x64)
).
See the POC below. Note that the Huff contracts are not equivalent to the reference or Yul contracts. Although the same calldata is used to call all three contracts, TSender.huff
and TSender_NoCheck.huff
transfer tokens to the wrong recipient. Add the following code to the /test
folder in the TSender repo and run it with forge test
TSender.huff
and TSender_NoCheck.huff
contracts will transfer funds to wrong addresses when called with specific calldata.
Manual Review.
Do not use hardcoded offsets for any of the dynamic types (address[] recipients
and uint256[] amounts
).
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.