abi.encode, abi.encodePacked, and abi.decode in Solidity 
Published: 2024-01-09 10:14:30

<p data-pm-slice="1 1 []">In Solidity, several key functions for encoding and decoding data are <code>abi.encode</code>, <code>encodePacked</code> decode <code>string.concat</code>  ,<code>bytes.concat</code> and finally, type casting using bytes or strings.</p>
These functions allow you to convert Solidity data types like strings, integers, addresses, etc., into a compact binary representation and back again.

Understanding how to encode and decode data properly is essential when building smart contracts that need to emit events, return data to clients, or interact with external contracts and protocols.

Not having a good idea of how to get this done can lead to bugs, unintended behavior, or wasted gas fees.

In this article, we will take a low-level look at how these Solidity encoding functions work under the hood. We'll explore the key differences between encode and encodePacked and when to use each. We'll also cover some common pitfalls and issues that can arise when encoding and decoding data in your contracts.

Like Patrick will say, let's dive into the rabbit hole. Hope to see you on the other side.
<h2>Prerequisite</h2>
<ul>
 	<li>Basic knowledge of Solidity or any programming language</li>
 	<li><a class="attrlink" href="https://remix.ethereum.org/?#code=Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC45OwoKaW1wb3J0ICJAb3BlbnplcHBlbGluL2NvbnRyYWN0c0A0LjkuMy90b2tlbi9FUkMyMC9FUkMyMC5zb2wiOwppbXBvcnQgIkBvcGVuemVwcGVsaW4vY29udHJhY3RzQDQuOS4zL3Rva2VuL0VSQzIwL2V4dGVuc2lvbnMvRVJDMjBCdXJuYWJsZS5zb2wiOwppbXBvcnQgIkBvcGVuemVwcGVsaW4vY29udHJhY3RzQDQuOS4zL3NlY3VyaXR5L1BhdXNhYmxlLnNvbCI7CmltcG9ydCAiQG9wZW56ZXBwZWxpbi9jb250cmFjdHNANC45LjMvYWNjZXNzL093bmFibGUuc29sIjsKaW1wb3J0ICJAb3BlbnplcHBlbGluL2NvbnRyYWN0c0A0LjkuMy90b2tlbi9FUkMyMC9leHRlbnNpb25zL0VSQzIwUGVybWl0LnNvbCI7Cgpjb250cmFjdCBOb0V2aWRlbmNlIGlzIEVSQzIwLCBFUkMyMEJ1cm5hYmxlLCBQYXVzYWJsZSwgT3duYWJsZSwgRVJDMjBQZXJtaXQgewogICAgY29uc3RydWN0b3IoKSBFUkMyMCgiTm9FdmlkZW5jZSIsICJORUQiKSBFUkMyMFBlcm1pdCgiTm9FdmlkZW5jZSIpIHsKICAgICAgICBfbWludChtc2cuc2VuZGVyLCAzMCAqIDEwICoqIGRlY2ltYWxzKCkpOwogICAgfQoKICAgIGZ1bmN0aW9uIHBhdXNlKCkgcHVibGljIG9ubHlPd25lciB7CiAgICAgICAgX3BhdXNlKCk7CiAgICB9CgogICAgZnVuY3Rpb24gdW5wYXVzZSgpIHB1YmxpYyBvbmx5T3duZXIgewogICAgICAgIF91bnBhdXNlKCk7CiAgICB9CgogICAgZnVuY3Rpb24gbWludChhZGRyZXNzIHRvLCB1aW50MjU2IGFtb3VudCkgcHVibGljIG9ubHlPd25lciB7CiAgICAgICAgX21pbnQodG8sIGFtb3VudCk7CiAgICB9CgogICAgZnVuY3Rpb24gX2JlZm9yZVRva2VuVHJhbnNmZXIoYWRkcmVzcyBmcm9tLCBhZGRyZXNzIHRvLCB1aW50MjU2IGFtb3VudCkKICAgICAgICBpbnRlcm5hbAogICAgICAgIHdoZW5Ob3RQYXVzZWQKICAgICAgICBvdmVycmlkZQogICAgewogICAgICAgIHN1cGVyLl9iZWZvcmVUb2tlblRyYW5zZmVyKGZyb20sIHRvLCBhbW91bnQpOwogICAgfQp9Cg&amp;lang=en&amp;optimize=false&amp;runs=200&amp;evmVersion=null&amp;version=soljson-v0.8.18+commit.87f61d96.js" target="_blank" rel="noreferrer nofollow noopener">Remix IDE</a></li>
</ul>
<h2>abi.encode</h2>
<code>abi.encode</code> is a function in Solidity that is part of the Application Binary Interface (ABI) encoding mechanism. It mostly encodes multiple values in a tightly packed binary format.
```javascript
function encodeValue() public pure returns (bytes memory){
    bytes memory vals = abi.encode("Scofield course", "is easy to grasp");
    return vals;
    }
```
For example, we want to encode <code>"scofield course"</code> and <code>"is easy to grasp"</code> We create our function and set the memory to bytes memory, remembering anything stored on the memory is not retained, unlike storage that stores value.

We create a bytes variable, encode our value into it, and then return the value in vals

<img src="https://paper-attachments.dropboxusercontent.com/s_A4C5966713FCFDE7DA3520F5C8DFFC83E79B263E36594201E49253BC388273CC_1704788444174_Screenshot+2024-01-09+at+09.20.36.png" align="left" />

while <code>abi.encode</code> packs all the values together. There is quite many padding, and this is why the need for abi.encodePacked is needed
<h2>abi.encodePacked</h2>
Next is <code>abi.encodePacked</code> this function is specifically designed for tightly packing multiple values without adding any padding. It concatenates the raw binary data of each parameter.

An example
```javascript
function encodeValue2() public pure returns (bytes memory){
    bytes memory vals = abi.encodePacked("Scofield course", "is easy to grasp");
        return vals;

    }
```
Same example as above, but we only changed how it is packed, so here is the result.

<img src="https://paper-attachments.dropboxusercontent.com/s_A4C5966713FCFDE7DA3520F5C8DFFC83E79B263E36594201E49253BC388273CC_1704789897999_Screenshot+2024-01-09+at+09.44.50.png" align="left" />

The packed version removes all padding while we only get the value in return, saving us gas and allowing us to still use the byte's value retrieved.
<h2>TypeCasting</h2>
Typecasting refers to the explicit conversion of a variable from one data type to another.

If you know a bit about typecasting, you can argue, why don’t we just typecast and get the same result? If you are a beginner, check this <a class="attrlink" href="https://medium.com/coinmonks/learn-solidity-lesson-22-type-casting-656d164b9991" target="_blank" rel="noreferrer nofollow noopener">article</a> to learn more about typecasting,
```javascript
function encodeB() public pure returns(bytes memory) {
       bytes memory value = bytes("Scofield course", "is easy to grasp");
        return value;
    }
```
We tested that and got this error.

<pre><code class="language-solidity">TypeError: Exactly one argument expected for explicit type conversion.
  --&gt; encode.sol:18:30:
   |
18 |         bytes memory value = bytes("Scofield course", "is easy to grasp");
   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</code></pre>
<code> </code>

We could only take one argument at a time, which, if we still went to use this method, we might have to set more bytes memory like so
```javascript
function encodeB() public pure returns(bytes memory, bytes memory) {
    bytes memory value1 = bytes("Scofield course");
    bytes memory value2 = bytes("is easy to grasp");
    return (value1, value2);
```
Notice we still have to separate them, and the result, even if they are are same, but we have them in separate memory, which is not what we are after.

<img src="https://paper-attachments.dropboxusercontent.com/s_A4C5966713FCFDE7DA3520F5C8DFFC83E79B263E36594201E49253BC388273CC_1704790906371_Screenshot+2024-01-09+at+10.01.41.png" align="left" />
<h2>bytes.concat</h2>
bytes.concat specializes in concatenating together raw byte arrays, ensuring the result is a properly aligned byte array. It lacks abi.encodePacked's versatility around handling multiple data types.
```javascript
function encodB() public pure returns(bytes memory) {
        bytes memory value = bytes.concat("my name is ", "scofield");
            return value;
    }
```
<code>bytes.concat</code> joins byte arrays end-to-end, preserving alignment. It only works on byte arrays.

<img src="https://paper-attachments.dropboxusercontent.com/s_A4C5966713FCFDE7DA3520F5C8DFFC83E79B263E36594201E49253BC388273CC_1704792463645_Screenshot+2024-01-09+at+10.27.37.png" align="left" />

Remember, it can only work for certain data types and not for all, like encode
<h2>string.concat</h2>
The <code>string.concat</code> function in Solidity allows you to join multiple strings together into a new single string. This avoids having to add them together with basic string addition manually.
```javascript
function encodB() public pure returns(string memory) {
        string memory value = string.concat("my name is ", "scofield");
            return value;
    }
```
Here, we added ‘my name is” to “scofield and the result below is

<img src="https://www.dropbox.com/paper/ep/redirect/image?url=https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_A4C5966713FCFDE7DA3520F5C8DFFC83E79B263E36594201E49253BC388273CC_1704793843273_Screenshot%2B2024-01-09%2Bat%2B10.50.38.png&amp;hmac=W36JDWdfiW3L42jeURS5hCTScIuelFgnTUmbgiod4eI%3D&amp;width=1490" alt="User-uploaded image: Screenshot+2024-01-09+at+10.50.38.png" align="left" />
<h2>abi.decode</h2>
If you are wondering if we might be able to get our converted value back after conversion, then you are right; we can, with the <code>abi.decode</code>.

<code>abi.decode</code> allows you to decode encoded parameters from external contract calls. It unpacks encoded data so your Solidity contract can work with the original values again.

Decoding data parameters with <code>abi.decode</code> is essential for working with return values from external contract function calls. It also enables your contract to accept and process encoded input parameters from users and other contracts.

For example
```javascript
function decodeValue() public pure returns (string memory){
        string memory vals = abi.decode(encodeValue() , (string));
            return vals;
        }
```
we have to change memory from bytes to strings as we convert back to strings and then copy the function <code>encodeValue()</code> plus the <code>(string)</code>, which outputs this.

<img src="https://paper-attachments.dropboxusercontent.com/s_A4C5966713FCFDE7DA3520F5C8DFFC83E79B263E36594201E49253BC388273CC_1704791662519_Screenshot+2024-01-09+at+10.14.16.png" align="left" />

OH NO!!!!

We only get back half of our encoded value; what happened to the other half? if you can figure it out, leave a comment below to let me know.
<h2>Resource</h2>
<ul>
 	<li><a class="attrlink" href="https://blog.learnhub.africa/2023/12/19/getting-started-with-foundry-for-beginners-in-2024/" target="_blank" rel="noreferrer nofollow noopener">Getting Started with Foundry for Beginners in 2024</a></li>
 	<li><a class="attrlink" href="https://blog.learnhub.africa/2023/09/25/what-are-smart-contracts/" target="_blank" rel="noreferrer nofollow noopener">What are Smart Contracts?</a></li>
 	<li><a class="attrlink" href="https://blog.learnhub.africa/2023/12/27/create-a-raffle-draw-smart-contract-using-foundry-2024-part-1/" target="_blank" rel="noreferrer nofollow noopener">Create a Raffle Draw Smart Contract Using Foundry 2024 (Part 1)</a></li>
 	<li><a class="attrlink" href="https://blog.learnhub.africa/2024/01/08/create-an-nft-as-a-developer-deep-dive-into-smart-contracts/" target="_blank" rel="noreferrer nofollow noopener">Create an NFT as a Developer: Deep Dive into Smart Contracts</a></li>
</ul>
<a class="attrlink" href="https://www.buymeacoffee.com/Scofield" target="_blank" rel="noreferrer nofollow noopener">Gift us a cup of coffee if you are so kind. </a>