RareSkills Solidity Interview Question #35 Answered: What is the difference between abi.encode and abi.encodePacked?
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:
- LinkedIn: https://www.linkedin.com/in/faybianbyrd/
- Twitter: https://twitter.com/FaybianByrd
- Github: https://github.com/FaybianB
Latest articles:
- Question #25 (Easy): What is the difference between view and pure?
- Question #26 (Easy): What is the difference between transferFrom and safeTransferFrom in ERC721?
- Question #27 (Easy): How can an ERC1155 token be made into a non-fungible token?
- Question #28 (Easy): What is access control and why is it important?
- Question #29 (Easy): What does a modifier do?
- Question #30 (Easy): What is the largest value a uint256 can store?
- Question #31 (Easy): What is variable and fixed interest rate?
- Question #32 (Medium): What is the difference between transfer and send? Why should they not be used?
- Question #33 (Medium): How do you write a gas-efficient for loop in Solidity?
- Question #34 (Medium): What is a storage collision in a proxy contract?
Disclosure: Some content may have been generated with the help of artificial intelligence.