> For the complete documentation index, see [llms.txt](https://mau-eth.gitbook.io/mau/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mau-eth.gitbook.io/mau/abi-encode/examples.md).

# Examples

The example given is a simple Ethereum smart contract named `Foo` written in Solidity. It has three functions: `bar`, `baz`, and `sam`.

```solidity
contract Foo {
    function bar(bytes3[2] memory) public pure {}
    function baz(uint32 x, bool y) public pure returns (bool r) { r = x > 32 || y; }
    function sam(bytes memory, bool, uint[] memory) public pure {}
}
```

**Calling `baz` Function:**

If we want to call the `baz` function with arguments `69` (a `uint32`) and `true` (a `bool`), the ABI encoded data would be:

1. **Method ID** (`0xcdcd77c0`): The first 4 bytes of the Keccak-256 hash of the ASCII form of the signature `baz(uint32,bool)`.
2. **First Parameter** (`0x...45`): `uint32` value 69, but ABI-encoded to be right-aligned within a 32-byte word.
3. **Second Parameter** (`0x...01`): `bool` value true, ABI-encoded as a `uint256` (0 for false, 1 for true) and again right-aligned within a 32-byte word.

**Calling `bar` Function:**

To call the `bar` function with a 2-element `bytes3` array \["abc", "def"], the ABI encoded data would be:

1. **Method ID** (`0xfce353f6`): Derived from the signature `bar(bytes3[2])`.
2. **First and Second Parameters**: The `bytes3` values "abc" and "def", right-aligned within their respective 32-byte words.

**Calling `sam` Function:**

For the `sam` function, if we use arguments "dave" (a `bytes` string), `true` (a `bool`), and an array `[1,2,3]` (a `uint[]` array), the ABI encoded data would be:

1. **Method ID** (`0xa5643bf2`): Derived from the signature `sam(bytes,bool,uint256[])`.
2. **Dynamic Type Offset for First Parameter**: Points to the location of the data for the first parameter (since it's a dynamic type).
3. **Second Parameter** (`bool`): As before, 0 or 1 represented as a `uint256`.
4. **Dynamic Type Offset for Third Parameter**: Points to the location of the data for the third parameter.
5. **Data for First Parameter**: Starts with the length of the byte array and then the data itself.
6. **Data for Third Parameter**: Starts with the length of the array and then each of the array elements (in this case, the numbers 1, 2, and 3).

**Important Note:** The way Ethereum ABI works is by distinguishing between fixed-size and dynamic-sized types. For fixed-size types, it directly encodes the values. For dynamic-sized types (like `bytes` or arrays), it first specifies the offset (or location) where the actual data starts, then later on in the encoded payload, you'd find the actual data.

To be proficient at understanding and constructing ABI-encoded data, it often requires practice and a solid understanding of the ABI encoding rules. Many developers use libraries or tools to help with this encoding, but understanding the underlying process can be very beneficial for debugging and advanced usage.

#### Encoding Steps

1. **Static Types**: For static types, you just take the value and pad it to 32 bytes if it's not already.

   Example: The value `0x123` for `uint256` is encoded as `0x000...123` (padded to 32 bytes).
2. **Dynamic Types**: A bit trickier. For dynamic types, you don't immediately put the value. Instead, you put a "pointer" indicating where the actual value starts in the encoded data. This "pointer" is an offset in bytes from the start of the value encoding.
3. **The Actual Data**: After encoding all the function parameters, you then put the actual data of the dynamic types in the order they appear.

#### Detailed Breakdown

Let's break down the example given:

Function: `f(uint256,uint32[],bytes10,bytes)` with values `(0x123, [0x456, 0x789], "1234567890", "Hello, world!")`.

1. **Function Selector**: `0x8be65246`
2. **First Argument (Static)**: `0x123` becomes `0x000...123`.
3. **Second Argument (Dynamic, Array)**: Instead of directly putting `[0x456, 0x789]`, we put a pointer where this data will later be placed. That pointer is `0x80` which means "skip 128 bytes from the start of this encoding to find the data for me". Why 128? Because we've already consumed 4 bytes for the function selector and will consume 32 bytes for each of the next 4 parameters (128 bytes in total).
4. **Third Argument (Static)**: The string "1234567890" becomes `0x313233343536373839300000...`
5. **Fourth Argument (Dynamic, String)**: Similarly, a pointer. But note the pointer is now `0xE0`, indicating where "Hello, world!" will be.
6. **Second Argument's Data**:
   * First, the length of the array: `0x2`.
   * Elements: `0x456` and `0x789`.
7. **Fourth Argument's Data**:
   * Length: `0xD` (13 in decimal, because "Hello, world!" is 13 characters).
   * The string itself.

For the next example with function `g(uint256[][],string[])` and values `([[1, 2], [3]], ["one", "two", "three"])`, the same principles are applied, but with an added complexity because of the nested arrays.

#### Key Takeaways

* Ethereum uses a specific encoding mechanism to ensure that data and function calls are correctly understood and processed.
* Static types are straightforward to encode.
* Dynamic types involve placing pointers first and then adding the actual data later in the sequence.
* Nested dynamic types, like arrays of arrays, follow the same principle but require careful calculation of where each inner array's data is placed.
