List Ops
A List Op is a structure used to encapsulate an operation performed on a List. It includes the following fields:
version: Auint8representing the version of the List Op. This byte defines the schema of the subsequent bytes for encoding/decoding. This is used to ensure compatibility and facilitate future upgrades.opcode: Auint8indicating the operation code. This defines the action to be taken using the List Op.data: Abytesarray which holds the operation-specific data. For instance, if the operation involves adding a List Record, this field would contain the encoded List Record.
The version is always 1.
Operation Codes
There are four operations defined at this time:
| Code | Operation | Data |
|---|---|---|
| 0 | Reserved | N/A |
| 1 | Add record | Encoded ListRecord |
| 2 | Remove record | Encoded ListRecord |
| 3 | Tag record | Encoded ListRecord followed by tag |
| 4 | Untag record | Encoded ListRecord followed by tag |
| 5 - 255 | Reserved | N/A |
Encoding
ListOps are encoded as byte arrays, starting with a one-byte version and a one-byte opcode, followed by the data of variable length.
+------------------+-----------------+-------------------------------+| version (1 byte) | opcode (1 byte) | data (variable length) |+------------------+-----------------+-------------------------------+The encoding of a ListOp is designed to be flexible, accommodating various types of operations and their corresponding data structures.
| Byte(s) | Description |
|---|---|
| 0 | ListOp version (1 byte) |
| 1 | Operation code (1 byte) |
| 2 - N | Encoded operation-specific data |
The 2 - N byte range is variable and depends on the operation being performed.
Example - Add Record
The following is an example of an encoded ListOp for adding a ListRecord of type 1 (address record) to a list:
| Byte(s) | Description | Value |
|---|---|---|
| 0 | ListOp version (1 byte) | 0x01 |
| 1 | Operation code (1 byte) | 0x01 |
| 2 | ListRecord version (1 byte) | 0x01 |
| 3 | ListRecord record type (1 byte) | 0x01 |
| 4 - 23 | ListRecord data (20 bytes) | 0x00000000000000000000000000000000DeaDBeef |
Example - Remove Record
The following is an example of an encoded ListOp for removing a ListRecord of type 1 (address record) from a list:
| Byte(s) | Description | Value |
|---|---|---|
| 0 | ListOp version (1 byte) | 0x01 |
| 1 | Operation code (1 byte) | 0x02 |
| 2 | ListRecord version (1 byte) | 0x01 |
| 3 | ListRecord record type (1 byte) | 0x01 |
| 4 - 23 | ListRecord data (20 bytes) | 0x00000000000000000000000000000000DeaDBeef |
Example - Tag Record
The following is an example of an encoded ListOp for tagging a ListRecord of type 1 (address record) in a list:
| Byte(s) | Description | Value |
|---|---|---|
| 0 | ListOp version (1 byte) | 0x01 |
| 1 | Operation code (1 byte) | 0x03 |
| 2 | ListRecord version (1 byte) | 0x01 |
| 3 | ListRecord record type (1 byte) | 0x01 |
| 4 - 23 | ListRecord data (20 bytes) | 0x00000000000000000000000000000000DeaDBeef |
| 24 - N | Tag (variable) (UTF-8) | 0x746167 (“tag”) |
The tag should be encoded as UTF-8.
Example - Untag Record
The following is an example of an encoded ListOp for untagging a ListRecord of type 1 (address record) in a list:
| Byte(s) | Description | Value |
|---|---|---|
| 0 | ListOp version (1 byte) | 0x01 |
| 1 | Operation code (1 byte) | 0x04 |
| 2 | ListRecord version (1 byte) | 0x01 |
| 3 | ListRecord record type (1 byte) | 0x01 |
| 4 - 23 | ListRecord data (20 bytes) | 0x00000000000000000000000000000000DeaDBeef |
| 24 - N | Tag (variable) (UTF-8) | 0x746167 (“tag”) |
The tag should be encoded as UTF-8.
Code
List Op can be represented as a type in any programming language. Here are some examples:
Go
type ListOp struct { Version uint8 Opcode uint8 Data []byte}Python
class ListOp: version: int # 0-255 opcode: int # 0-255 data: bytesRust
struct ListOp { version: u8, opcode: u8, data: Vec<u8>,}Solidity
/** * @dev The EFP contracts don't use this struct; they only store list ops * as `bytes` with the version, opcode, and data fields tightly packed * into a single `bytes` value. However, this struct can be useful for * offchain processing with foundry or other Solidity tooling */struct ListOp { uint8 version; uint8 opcode; bytes data;}TypeScript
type ListOp = { version: number // 0-255 opcode: number // 0-255 data: Uint8Array}