1

I've been messing around with the abi.encode... functions and I think I have a good grasp of the differences, except abi.encode and abi.encodeWithSelector. Because, they give similar but slightly different results, so I'm not sure when to use one or the other.

 abi.encodeWithSelector(bytes4(keccak256("add(uint256,uint256)")), 10,10); abi.encode(bytes4(keccak256("add(uint256,uint256)")), 10, 10); 

The output of encodeWithSelector is

0x771602f7000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a 

and the output of encode is

0x771602f700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a 

and when I use delegatecall the return value of encodeWithSelector is 20, as expected, but encode is 42949672960

1 Answer 1

1

The normal abi.encode encodes values according to the abicoder. A bytes4 value is padded to 32 bytes

0x771602f700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a ^ first 32 byte word ^ second 32 byte word ^ third 32 byte word 

Using abi.encodeWithSelector allows you to correctly encode function calldata by adding a 4 bytes selector at the beginning (which can also be accessed using add.selector). The encoding becomes

0x771602f7000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a ^ 4 bytes selector ^ first 32 byte word ^ second 32 byte word 

When using encode, the function reads the parameters from calldata with their expected offset. When incorrectly encoding with abi.encode, the first parameter (first 32 bytes after the 4 bytes selector) are 0, the second 32 bytes read a00000000, because of how the calldata is shifted now, as can be seen here (the third word is simply ignored):

0x771602f700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000a ^ 4 bytes selector ^ first 32 byte word ^ second 32 byte word ^ third 32 byte word 

0xa00000000 is 42949672960 encoded. So abi.encode essentially returns the result of add(0, 42949672960)

2
  • Thank you for the detailed answer. But then in what situation would I use encode? Commented Jun 6, 2022 at 13:30
  • It's often used for calculating the keccak256 hash of some data (it requires bytes as input). Or when sending arbitrary data (to another contract for example) it can be encoded as bytes and then decoded later. This is for example done for L1 <-> L2 message passing. Commented Jun 6, 2022 at 14:12

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.