abi.decode is (seemingly) not decoding correctly, at least for a bytes, in memory, of length 68 (i.e. byte4, bytes32, bytes32)
When I call myFunc below in this way:
const dataHex = '0x052f1ef000000000000000000000000000000000000000000000000000000000000000002c91ae39b411ab15cfdcf148a174f4aa7e922c8f9c050daa346a72c933a1a731';
const { receipt, logs } = await contractInstance.myFunc(callDataHex);
I get the following results:
// Try to decode first 4 bytes from left (works)
event Debug(bytes4);
function myFunc(bytes memory data) public {
(bytes4 sig) = abi.decode(data, (bytes4));
emit Debug(sig);
}
logs[0].args[0] is 0x052f1ef0
// Try to decode first 4 bytes and second 32 bytes from left (fails, gets first 4 bytes from left, then 32 bytes 4 away from the right)
event Debug(bytes4, byte32);
function myFunc(bytes memory data) public {
(bytes4 sig, bytes32 thing_1) = abi.decode(data, (bytes4, bytes32));
emit Debug(sig, thing_1);
}
logs[0].args[0] is 0x052f1ef0
logs[0].args[1] is 0x000000002c91ae39b411ab15cfdcf148a174f4aa7e922c8f9c050daa346a72c9
// Try to decode first 32 bytes and second 32 bytes from left (works)
event Debug(bytes32, byte32);
function myFunc(bytes memory data) public {
(bytes32 thing_1, bytes32 thing_2) = abi.decode(data, (bytes32, bytes32));
emit Debug(thing_1, thing_2);
}
logs[0].args[0] is 0x052f1ef000000000000000000000000000000000000000000000000000000000
logs[0].args[1] is 0x000000002c91ae39b411ab15cfdcf148a174f4aa7e922c8f9c050daa346a72c9
// Try to decode first 4 bytes, second 32 bytes, and third 32 bytes, from left (reverts)
event Debug(bytes4, byte32, bytes32);
function myFunc(bytes memory data) public {
(bytes4 sig, bytes32 thing_1, bytes32 thing_2) = abi.decode(data, (bytes4, bytes32, bytes32));
emit Debug(sig, thing_1, thing_2);
}
Error: Returned error: VM Exception while processing transaction: revert
// And just to make sure data is what I think it is:
event Debug(bytes);
function myFunc(bytes memory data) public {
(bytes4 sig, bytes32 thing_1) = abi.decode(data, (bytes4));
emit Debug(data);
}
logs[0].args[0] is 0x052f1ef000000000000000000000000000000000000000000000000000000000000000002c91ae39b411ab15cfdcf148a174f4aa7e922c8f9c050daa346a72c933a1a731
// Try to decode first 32 bytes, second 4 bytes, from left (reverts)
event Debug(byte32, bytes4);
function myFunc(bytes memory data) public {
(bytes32 thing_1, bytes4 thing_2) = abi.decode(data, (bytes32, bytes4));
emit Debug(thing_1, thing_2);
}
Error: Returned error: VM Exception while processing transaction: revert
However, this all works correct if data uses calldata as storage, instead of memory, in the function signature.
@deluca-mike From #9439:
abi.decodeis the converse ofabi.encode. From the fact that you are usingbytes4 sigI assume that you are trying to do abi decoding and function selector decoding at the same time. This won't work because the abi encoding pads all types to 32 bytes, while the function selector is not padded.If you change
_datatobytes calldata, then you can use the following to decode:abi.decode(_data[4:], (bytes32, address, bytes32, bytes32));
So what you're seeing is how it's supposed to work currently, though we're considering adding abi.decodeWithSignature() to the language to better support your use case.
I'm going to close this as a duplicate not to split the discussion. Please feel free to post your comments in #9439 if you have something to add to the discussion.
Most helpful comment
@deluca-mike From #9439:
So what you're seeing is how it's supposed to work currently, though we're considering adding
abi.decodeWithSignature()to the language to better support your use case.I'm going to close this as a duplicate not to split the discussion. Please feel free to post your comments in #9439 if you have something to add to the discussion.