[Ethereum] Why are there two methods encoding arguments? “abi.encode” and “abi.encodePacked”


When we call a function on an external contract, the EVM computes a bytes buffer which contains the function signature and arguments.

There are two ways to serialize arguments:

  1. abi.encode
  2. abi.encodePacked

The differences between the two methods are well documented and I have understood them.

What I want to understand is why there are two methods in the first place? It is not clear when we should use the first and when we should use the second.

How can I see which method is used when I make this calls?

Call 1:

(success, ) = address(c).call(abi.encodeWithSignature("myfunction(uint256,uint256)", 400,500));

Call 2:

(success, ) = address(c).call(abi.encodeWithSelector(bytes4(keccak256("myfunction(uint256,uint256)")), 400,500)  )

Call 3:

(success, ) = address(c).call(  bytes4(keccak256("myfunction(uint256,uint256)")),    400, 500);

Call 4:


Thanks a lot.

Best Answer

I'd recommend to use 4 at all times if possible. It is easy to remember and write. The behavior is that it will revert the whole transaction if the call fails, which is the most reasonable alternative in general.

  • abi.encode encode its parameters using the ABI specs. The ABI was designed to make calls to contracts. Parameters are padded to 32 bytes. If you are making calls to a contract you likely have to use abi.encode

  • abi.encodePacked encode its parameters using the minimal space required by the type. Encoding an uint8 it will use 1 byte. It is used when you want to save some space, and not calling a contract.

  • abi.encodeWithSignature same as encode but with the function signature as first parameter. Use when the signature is known and don't want to calculate the selector.

  • abi.encodeWithSelector same as encode but selector is the first parameter. It almost equal to encodeWithSignature, use whatever fits best.

Case 3 was deprecated do not use, call+abi.encode should do the same job.

Related Topic