RareSkills Solidity Interview Question #35 Answered: What is the difference between abi.encode and abi.encodePacked?

Faybian Byrd
Coinmonks
3 min readMar 19, 2024

--

This series will provide answers to the list of Solidity interview questions that were published by RareSkills..

Question #35 (Medium): What is the difference between abi.encode and abi.encodePacked?

Answer: The difference between abi.encode and abi.encodePacked is that abi.encode encodes its parameters according to the ABI specifications, adding padding to inputs shorter than 32 bytes, while abi.encodePacked does not pad its inputs (except array elements) and does not follow the ABI specification but encodes its parameters and concatenates the values using the minimum number of bytes required by each type. Also, abi.encodePacked encodes dynamic types in-place and omits its length value, instead of appending the length and values to the end of the encoded data. Furthermore, abi.encodePacked does not support structs or nested arrays.

Demonstration:

// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

contract Encode {
function abiEncode() external pure returns (bytes memory) {
// Here is the result without the "0x" prefix:
// 0000000000000000000000000000000000000000000000000000000000000040 - 0x00 - Location of start of data for string "a"
// 0000000000000000000000000000000000000000000000000000000000000080 - 0x20 - Location of start of data for string "b"
// 0000000000000000000000000000000000000000000000000000000000000001 - 0x40 - Length of "a"
// 6100000000000000000000000000000000000000000000000000000000000000 - 0x60 - "a" in hex
// 0000000000000000000000000000000000000000000000000000000000000001 - 0x80 - Length of "b"
// 6200000000000000000000000000000000000000000000000000000000000000 - 0xa0 - "b" in hex
return abi.encode("a", "b");
}

function abiEncodePacked() external pure returns (bytes memory) {
// Result: 0x6162
return abi.encodePacked("a", "b");
}
}

Further Discussion:

The padding that’s added to encoded data as a result of using abi.encode is what avoids hash collisions when handling dynamic data types like strings and bytes. However, since abi.encodePacked does not pad its elements, it is subject to hash collisions.

For example, encoding the characters a, b and c in succession using abi.encodePacked will always produce the same result, no matter how the characters are grouped:

abi.encodePacked(“a”, “b”, “c”) == abi.encodePacked(“a”, “bc”) == abi.encodePacked(“ab”, “c”)

Therefore, the hash result for each operation would also be equivalent:

keccak256(abi.encodePacked(“a”, “b”, “c”)) == keccak256(abi.encodePacked(“a”, “bc”)) == keccak256(abi.encodePacked(“ab”, “c”))

Hence, the Solidity documentation warns:

If you use abi.encodePacked for signatures, authentication or data integrity, make sure to always use the same types and check that at most one of them is dynamic. Unless there is a compelling reason, abi.encode should be preferred.

Connect with me:

Latest articles:

Disclosure: Some content may have been generated with the help of artificial intelligence.

--

--

Faybian Byrd
Coinmonks

Senior Software Engineer, Full Stack/Frontend @Synapse Labs | Graduate - Advanced Solidity Bootcamp @ RareSkills. | Certified Solidity Developer (CSD)