{"id":28380729,"url":"https://github.com/0xsequence/czip","last_synced_at":"2025-06-24T21:31:29.178Z","repository":{"id":222302110,"uuid":"755355942","full_name":"0xsequence/czip","owner":"0xsequence","description":"EVM Calldata Zip, aka czip","archived":false,"fork":false,"pushed_at":"2024-04-26T13:58:19.000Z","size":424,"stargazers_count":99,"open_issues_count":0,"forks_count":5,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-06-06T03:40:52.982Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/0xsequence.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-10T00:34:04.000Z","updated_at":"2025-04-11T12:56:15.000Z","dependencies_parsed_at":"2024-06-21T14:10:55.765Z","dependency_job_id":"04e279d2-ce94-4eae-8e60-c85de9aa5be0","html_url":"https://github.com/0xsequence/czip","commit_stats":null,"previous_names":["0xsequence/czip"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/0xsequence/czip","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xsequence%2Fczip","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xsequence%2Fczip/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xsequence%2Fczip/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xsequence%2Fczip/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/0xsequence","download_url":"https://codeload.github.com/0xsequence/czip/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xsequence%2Fczip/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261759110,"owners_count":23205497,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-30T03:09:09.635Z","updated_at":"2025-06-24T21:31:29.167Z","avatar_url":"https://github.com/0xsequence.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"CZIP: EVM Calldata Zip\n======================\n\n![CZIP 😈](./logo.png)\n\n**czip** is an engine for compressing and decompressing EVM calldata. It is designed to be used in L2s to trade off calldata size for computation cost.\n\nThe primary component of czip is the `decompressor.huff` contract, which is a Huff contract that inflates the calldata. It works by implementing a simple state machine that, in a single pass, decompresses the input. The operations of the state machine are specifically designed to work with EVM calldata.\n\nA companion `czip-compressor` tool is provided to compress calldata. It is a simple command-line tool that **does not** perform perfect compression but provides a good starting point for starting to use the `decompressor.huff` contract.\n\n## Install\n\n```\n$ brew tap 0xsequence/tap\n$ brew install czip-compressor\n$ czip-compressor\n```\n\nor\n\n`$ docker run ghcr.io/0xsequence/czip-compressor`\n\nor\n\n`$ go install github.com/0xsequence/czip/compressor/cmd/czip-compressor@latest`\n\n\n## Usage\n\nThe compressor has the following commands:\n\n- `encode-call \u003cdecode/call/call-return\u003e \u003chex_data\u003e \u003caddr\u003e` Compresses a call to `addr` with `hex_data`.\n- `encode-calls \u003cdecode/call\u003e \u003chex_data_1\u003e \u003caddr_1\u003e \u003chex_data_2\u003e \u003caddr_2\u003e ...` Compresses multiple calls into one payload.\n- `encode-any \u003cdata\u003e` Encodes any data into a compressed representation.\n- `encode-sequence-tx \u003cdecode/call\u003e \u003csequence_tx\u003e \u003csequence_wallet\u003e` Compresses a Sequence wallet transaction.\n\n```\nczip-compressor is a tool for compressing Ethereum calldata. The compressed data can be decompressed using the decompressor contract.\n\nUsage:\n  czip-compressor [command]\n\nAvailable Commands:\n  completion         Generate the autocompletion script for the specified shell\n  encode-any         Compress any calldata: \u003chex\u003e\n  encode-call        Compress a call to a contract: \u003cdata\u003e \u003cto\u003e\n  encode-calls       Compress multiple calls to many contracts: \u003cdata\u003e \u003cto\u003e \u003cdata\u003e \u003cto\u003e ... \u003cdata\u003e \u003cto\u003e\n  encode-sequence-tx Compress a Sequence Wallet transaction\n  extras             Additional encoding methods, used for testing and debugging.\n  help               Help about any command\n\nFlags:\n      --allow-opcodes strings      Will only encode using these operations, separated by commas.\n      --cache-dir string           Path to the cache dir for indexes. (default \"/tmp/czip-cache\")\n  -c, --contract string            Contract address of the decompressor contract.\n      --disallow-opcodes strings   Will not encode using these operations, separated by commas.\n  -h, --help                       help for czip-compressor\n  -p, --provider string            Ethereum RPC provider URL.\n  -s, --use-storage                Use stateful read/write storage during compression.\n\nUse \"czip-compressor [command] --help\" for more information about a command.\n```\n\n### Encode call\n\nIt encodes a single call to a contract, the subcommands are:\n\n- `decode` Generates a payload that, when sent to the `decompressor.huff` contract, will decompress the calldata and return the caller, without performing the call.\n- `call` Generates a payload that, when sent to the `decompressor.huff` contract, will decompress the calldata and perform the call, ignoring the return value.\n- `call-return` Generates a payload that, when sent to the `decompressor.huff` contract, will decompress the calldata and perform the call, returning the return value.\n\n```cmd\nczip-compressor encode-call decode \\\n0xa9059cbb0000000000000000000000008bf74fb902cdad5d2d8ca0d3bbc7bb16894b9c350000000000000000000000000000000000000000000000000000000006052340 \\\n0xdAC17F958D2ee523a2206206994597C13D831ec7\n\n\u003e 0x0b3701148bf74fb902cdad5d2d8ca0d3bbc7bb16894b9c35332bf214dac17f958d2ee523a2206206994597c13d831ec7\n```\n\n### Encode Calls\n\nIt encodes multiple calls to contracts, the subcommands are:\n\n- `decode` Generates a payload that, when sent to the `decompressor.huff` contract, will decompress all calls and return them decompressed, without performing the calls.\n- `call` Generates a payload that, when sent to the `decompressor.huff` contract, will decompress the calls and perform them, ignoring the return values.\n\nNotice that the `call-return` subcommand is not available in this mode.\n\n```cmd\nczip-compressor encode-calls decode \\\n  0xa9059cbb0000000000000000000000009813d80d0686406b79c29b2b8a672a13725facb300000000000000000000000000000000000000000000000ae56f730e6d840000 \\\n  0xdac17f958d2ee523a2206206994597c13d831ec7 \\\n  0x095ea7b30000000000000000000000007c56be0ad3128acc33190484cd1badebc8c76240ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff \\\n  0xdac17f958d2ee523a2206206994597c13d831ec7\n\n\u003e 0x0c023701149813d80d0686406b79c29b2b8a672a13725facb3338fda14dac17f958d2ee523a2206206994597c13d831ec73702147c56be0ad3128acc33190484cd1badebc8c7624031ff3d001c\n```\n\n\u003e Compressing multiple calls into one payload is more efficient than compressing each call individually, as data can be de-duplicated and the overhead of the decompressor is amortized over multiple calls.\n\n### Encode Any\n\nIt encodes any data into a compressed representation. Sending the payload to the `decompressor.huff` contract will return the original data.\n\n```cmd\nczip-compressor encode-any \\\n  0x0000000000000000000000000000000000000000000000012a5f58168ee60000\n\n\u003e 0x0d3388d7\n```\n\n### Encode Sequence Transaction\n\nIt works similarly to `encode-calls`, but it is specifically designed to compress a Sequence wallet transaction. It expects the data to be a Sequence Transaction ABI-encoded.\n\n## Using storage indexes\n\nBy default all commands run with `--use-storage false`, which means that the decompressor won't write any data to the storage, or read any addresses or bytes32 using indexes.\n\nStorage indexes can be enabled using the following flags:\n\n- `--use-storage true` Enables the use of storage indexes.\n- `--contract \u003caddress\u003e` An instance of the `decompressor.huff` contract to use for storage indexes.\n- `--provider \u003cprovider\u003e` The provider from which to fetch the pointers.\n\nNotice that a cache on `/tmp/czip-cache/czip-indexes-\u003cchain-id\u003e.json` is automatically created to avoid fetching the same pointers multiple times. The cache dir can be changed using the `--cache-dir` flag.\n\n### Example\n\n```cmd\nczip-compressor encode-call decode \\\n  0xa9059cbb000000000000000000000000963752cac40e583dea143d6262e24f89c9e1f91100000000000000000000000000000000000000000000000000000000000003fc \\\n  0x750ba8b76187092B0D1E87E28daaf484d1b5273b\n\n\u003e 0x0b370114963752cac40e583dea143d6262e24f89c9e1f9110203fc14750ba8b76187092b0d1e87e28daaf484d1b5273b\n\nczip-compressor encode-call decode \\\n  --contract 0x8C5CF0a201C1F0C1517a23699BE48070724e7a70 \\\n  --provider https://nodes.sequence.app/arbitrum-nova \\\n  --use-storage \\\n  0xa9059cbb000000000000000000000000963752cac40e583dea143d6262e24f89c9e1f91100000000000000000000000000000000000000000000000000000000000003fc \\\n  0x750ba8b76187092B0D1E87E28daaf484d1b5273b\n\n\u003e 0x0b37012700010203fc270002\n```\n\nSee it in action: https://nova.arbiscan.io/tx/0x86e7b4177c0d219a87cc58f93ae2ecf2f490a719119c283f61cdc88585cc7c7b\n\n## How to decompress\n\nSending the generated payload to the `decompressor.huff` will either return the decompressed data or perform the call (depending on the command used to generate the payload).\n\nThe `decompressor.huff` contract has no selectors; the data does not need to be re-encoded and can be sent directly to the contract.\n\n### Cast example\n\nTry running the following command; it will inflate the data and return the original call data. You can do the same thing on-chain.\n\n```cmd\ncast call \\\n  --rpc-url https://nodes.sequence.app/arbitrum-nova \\\n  0x8C5CF0a201C1F0C1517a23699BE48070724e7a70 \\\n  0x0b37012700010203fc270002\n\n\u003e 0xa9059cbb000000000000000000000000963752cac40e583dea143d6262e24f89c9e1f91100000000000000000000000000000000000000000000000000000000000003fc000000000000000000000000750ba8b76187092b0d1e87e28daaf484d1b5273b\n```\n\n### Solidity example\n\nDecompressing on-chain is as simple as calling the decompressor contract with the payload.\n\n```solidity\ncontract YourContract {\n  event WeGotData(bytes data);\n\n  function doSomething(bytes calldata _compressed) external {\n    (bool ok, bytes memory data) = address(0x8C5CF0a201C1F0C1517a23699BE48070724e7a70).call(_compressed);\n    require(ok, \"Decompression failed\");\n    emit WeGotData(data);\n  }\n}\n```\n\nNotice that if the data was compressed using the `call` command, the compressor will not return the decompressed data; it will perform the call. In this example, we used the `decode` command, so the data will be returned.\n\n## Compression gains\n\nThe compression gains are highly dependent on the ratio of computation cost to calldata cost of a given network. It is most effective on \"rollup\" style L2s, but it can also achieve some small gains on some other networks.\n\n| Network       | Decompressor Address                       | Savings  |\n|---------------|--------------------------------------------|----------|\n| Arbitrum      | 0x8C5CF0a201C1F0C1517a23699BE48070724e7a70 | ~50%     |\n| Optimism      | 0x8C5CF0a201C1F0C1517a23699BE48070724e7a70 | ~50%     |\n| Base          | 0x8C5CF0a201C1F0C1517a23699BE48070724e7a70 | ~50%     |\n| Arbitrum Nova | 0x8C5CF0a201C1F0C1517a23699BE48070724e7a70 | ~15%     |\n| Polygon       | --                                         | Negative |\n| Ethereum      | --                                         | Negative |\n| Polygon zkEVM | --                                         | Negative |\n\nThe following benchmarking transactions are from the Arbitrum network, they show savings of ~50% in gas costs. The savings account for the cost of the decompressor contract, notice that they use an older version of the compressor, but the inner workings are the same.\n\n![Sending ETH cost comparison](https://ipfs.io/ipfs/QmbJ3rZRdUyie8bpF7tbDHK5acqU7ncigsNLqJvW6qZViu?filename=Compressed%20ETH%20transactions%20-%20Sequence%20wallet.svg)\n\nThe transaction cost for sending ETH using a smart contract wallet, with a 2/2 configuration, goes from **0.76 USD** to **0.38 USD**.\n\nSend ETH uncompressed (1st):\u003cbr\u003e\n[0xa0efbb458309f1ccc14035a53e20c36155d722b1c5d991bfa7c43a21174ec468](https://arbiscan.io/tx/0xa0efbb458309f1ccc14035a53e20c36155d722b1c5d991bfa7c43a21174ec468)\n\nSend ETH compressed + write storage (1st):\u003cbr\u003e\n[0x9a34d5787b0dd6fba248ebeb407d51526445b496f45f2b4f6ff1d56875f04f7c](https://arbiscan.io/tx/0x9a34d5787b0dd6fba248ebeb407d51526445b496f45f2b4f6ff1d56875f04f7c)\n\nSend ETH compressed (1st):\u003cbr\u003e\n[0x6197b0770cdb3efcdb252bf3932ff9964e3467906a7ac1de6361e2d9fe1bb84e](https://arbiscan.io/tx/0x6197b0770cdb3efcdb252bf3932ff9964e3467906a7ac1de6361e2d9fe1bb84e)\n\nSend ETH uncompressed (2nd):\u003cbr\u003e\n[0x7b519df3f10a0e0ae507d6d18d775f1ed80e65c76df06e5632f402903cd9afb8](https://arbiscan.io/tx/0x7b519df3f10a0e0ae507d6d18d775f1ed80e65c76df06e5632f402903cd9afb8)\n\nSend ETH compressed + write storage (2nd):\u003cbr\u003e\n[0x1680bae9b790bb54d522ebc033da92cb5261b73c27058767c55011957083ea41](https://arbiscan.io/tx/0x1680bae9b790bb54d522ebc033da92cb5261b73c27058767c55011957083ea41)\n\nSend ETH compressed (2nd):\u003cbr\u003e\n[0x1ccc93227065df0b9d6acc64504280ad7e55b5823b90111a0b6477c881291de4](https://arbiscan.io/tx/0x1ccc93227065df0b9d6acc64504280ad7e55b5823b90111a0b6477c881291de4)\n\n![Sending ERC20 cost comparison](https://ipfs.io/ipfs/QmNXyKPgcba7a4bFAMzRsQS3GSgykSD2FkpD9Qpk2FE2oV?filename=Compressed%20ERC20%20transactions%20-%20Sequence%20wallet.svg)\n\nThe transaction cost of sending ERC20 tokens using a smart contract wallet, with a 2/2 configuration, goes from **0.69 USD** to **0.31 USD**.\n\nSend ERC20 uncompressed:\u003cbr\u003e\n[0x0559ea8161e9cfed3298091d1f7626fe551bd40a38d2ff65d2340a52203e582a](https://arbiscan.io/tx/0x0559ea8161e9cfed3298091d1f7626fe551bd40a38d2ff65d2340a52203e582a)\n\nSend ERC20 compressed + write storage:\u003cbr\u003e\n[0xbbf1d0250c37155f2da1d72cc01ff68fb5ccd4b4834a4accf53caf9374e64e3b](https://arbiscan.io/tx/0xbbf1d0250c37155f2da1d72cc01ff68fb5ccd4b4834a4accf53caf9374e64e3b)\n\nSend ERC20 compressed:\u003cbr\u003e\n[0x07e3b4de0b2cd3c8c531e90f32afc7a5dc3691b399ae4ab33d833b3e10741d05](https://arbiscan.io/tx/0x07e3b4de0b2cd3c8c531e90f32afc7a5dc3691b399ae4ab33d833b3e10741d05)\n\nApprove ERC20 uncompressed:\u003cbr\u003e\n[0x03c5f3d5c5a556439215c751a0d84b838266e9ec2481f862a912943e1bc309d6](https://arbiscan.io/tx/0x03c5f3d5c5a556439215c751a0d84b838266e9ec2481f862a912943e1bc309d6)\n\nApprove ERC20 compressed:\u003cbr\u003e\n[0x7186dcf623d6bf5436691d28c649215900c4c71c2061863b0388786e07299428](https://arbiscan.io/tx/0x7186dcf623d6bf5436691d28c649215900c4c71c2061863b0388786e07299428)\n\n## Decompressor contract\n\nThe `decompressor.huff` serves as the decompressor for all data. It has been carefully designed to be as efficient as possible. It also serves the role of a \"repository\"; it can store `address` and `bytes32` values that can later be referenced using a pointer.\n\nThe contract **does not** follow the Solidity ABI convention. The contract uses a single byte for the function selector. The following functions are available:\n\n- `0x00` Execute sequence transaction.\n- `0x01` Execute many sequence transactions.\n- `0x02` Fetch one address using a pointer.\n- `0x03` Fetch one `bytes32` using a pointer.\n- `0x04` Fetch the total number of addresses and `bytes32` stored.\n- `0x05` Fetch a list of storage slots.\n- `0x06` Decompress a sequence transaction and return the data.\n- `0x07` Decompress many sequence transactions and return the data.\n- `0x08` Execute a call and ignore the return value.\n- `0x09` Execute a call and return the return value.\n- `0x0a` Execute many calls and ignore the return values.\n- `0x0b` Decompress a call and return the data.\n- `0x0c` Decompress many calls and return the data.\n- `0x0d` Decompress any data and return the data.\n\n\u003e The `czip-compressor` tool is designed to generate the payloads for the `0x08`, `0x09`, `0x0a`, `0x0b`, `0x0c`, and `0x0d` functions automatically; there is no need to manually prefix the payload with the function selector.\n\n### State machine\n\nThe state machine used by the `decompressor.huff` contract allows for a single-pass decompression of the calldata. It reads a single `operation`, but operations can be composed of multiple operations.\n\nThe operations are 1 byte long, they may contain any number of arguments, there are 89 operations available. The leftover space is used to express literal values. \n\nThe operations are:\n\n| Code          | Name          | Args   | Description                                                                                  |\n|---------------|---------------|--------|----------------------------------------------------------------------------------------------|\n| `0x00`          | `NO_OP`         |        | It writes an empty array of bytes to the buffer.                                             |\n| `0x01` ... `0x20` | `READ_WORD_*`   | \u003cu*: word\u003e | It reads a word of N bytes, the word is written to the buffer as a left-padded 32 byte word. |\n| `0x21`          | `READ_WORD_INV` | \u003cop: READ_WORD\u003e| Reads a (following) READ_WORD operation, but it pads the word to the right.           |\n| `0x22`          | `READ_N_BYTES`  | \u003cop: *\u003e   | Reads N bytes from the calldata and writes them to the buffer, the arg is another operation. |\n| `0x23`          | `WRITE_ZEROS`   | \u003cu8: size\u003e   | Writes N zeros to the buffer.                                                                 |\n| `0x24`          | `NESTED_FLAGS_S` | \u003cu8: len\u003e \u003c...op\u003e   | Executes N operations (max 255). |\n| `0x25`          | `NESTED_FLAGS_L` | \u003cu16: len\u003e \u003c...op\u003e   | Executes N operations. |\n| `0x26`          | `SAVE_ADDRESS`  | \u003cu160: addr\u003e | Saves an address on the repository, it writes the address to the buffer (padding to 32 bytes). |\n| `0x27`          | `READ_ADDRESS_2` | \u003cu16: pointer\u003e | Reads an address from the repository into the buffer, it uses 2 bytes for the pointer. |\n| `0x28`          | `READ_ADDRESS_3` | \u003cu24: pointer\u003e | Reads an address from the repository into the buffer, it uses 3 bytes for the pointer. |\n| `0x29`          | `READ_ADDRESS_4` | \u003cu32: pointer\u003e | Reads an address from the repository into the buffer, it uses 4 bytes for the pointer. |\n| `0x2a`          | `SAVE_BYTES32`  | \u003cu256: bytes32\u003e | Saves a bytes32 on the repository, it writes the value to the buffer. |\n| `0x2b`          | `READ_BYTES32_2` | \u003cu16: pointer\u003e | Reads a bytes32 from the repository into the buffer, it uses 2 bytes for the pointer. |\n| `0x2c`          | `READ_BYTES32_3` | \u003cu24: pointer\u003e | Reads a bytes32 from the repository into the buffer, it uses 3 bytes for the pointer. |\n| `0x2d`          | `READ_BYTES32_4` | \u003cu32: pointer\u003e | Reads a bytes32 from the repository into the buffer, it uses 4 bytes for the pointer. |\n| `0x2e`          | `READ_STORE_FLAG_S` | \u003cu16: calldata_pointer\u003e | Reads an \"storage\" flag, the pointer is absolute, it only writes the value to the buffer. |\n| `0x2f`          | `READ_STORE_FLAG_L` | \u003cu24: calldata_pointer\u003e | Reads an \"storage\" flag, the pointer is absolute, it only writes the value to the buffer. |\n| `0x30`          | `POW_2` | \u003cu8: exponent\u003e | Writes 2^N to the buffer, padded left to 32 bytes. |\n| `0x31`          | `POW_2_MINUS_1` | \u003cu8: exponent\u003e | Writes (2^(N + 1)) - 1 to the buffer, padded left to 32 bytes. |\n| `0x32`          | `POW_10` | \u003cu8: exponent\u003e | Writes 10^N to the buffer, padded left to 32 bytes. |\n| `0x33`          | `POW_10_MANTISSA_S` | \u003cu5: exponent\u003e \u003cu11: mantissa\u003e | Writes 10^N * M to the buffer, padded left to 32 bytes. |\n| `0x34`          | `POW_10_MANTISSA_L` | \u003cu6: exponent\u003e \u003cu18: mantissa\u003e | Writes 10^N * M to the buffer, padded left to 32 bytes. |\n| `0x35`          | `ABI_0_PARAM` | \\\u003cselector\\\u003e | Writes the ABI-encoded selector for a function with 0 parameters to the buffer. |\n| `0x36` ... `0x3b` | `ABI_*_PARAM` | \\\u003cselector\\\u003e \u003cop: arg_1\u003e ... | Writes the ABI-encoded selector for a function with N parameters to the buffer. |\n| `0x3c`          | `ABI_DYNAMIC` | \\\u003cselector\\\u003e \u003cu8: size\u003e \u003cu8: dynamic_bitmap\u003e \u003cop: arg_1\u003e ... | Writes the ABI-encoded selector for a function with dynamic parameters to the buffer, the bitmap determines what arguments are dynamic in size. |\n| `0x3d`          | `MIRROR_FLAG_S` | \u003cu16: calldata_pointer\u003e | Re-reads the flag at the given pointer and writes it to the buffer. |\n| `0x3e`          | `MIRROR_FLAG_L` | \u003cu24: calldata_pointer\u003e | Re-reads the flag at the given pointer and writes it to the buffer. |\n| `0x3f`          | `CALLDATA_S` | \u003cu16: calldata_pointer\u003e \u003cu8: size\u003e | Writes N bytes from the calldata to the buffer, the pointer is absolute. |\n| `0x40`          | `CALLDATA_L` | \u003cu24: calldata_pointer\u003e \u003cu8: size\u003e | Writes N bytes from the calldata to the buffer, the pointer is absolute. |\n| `0x40`          | `CALLDATA_XL` | \u003cu24: calldata_pointer\u003e \u003cu16: size\u003e | Writes N bytes from the calldata to the buffer, the pointer is absolute. |\n\n#### Sequence Specific Operations\n\n| Code          | Name          | Args   | Description                                                                                  |\n|---------------|---------------|--------|----------------------------------------------------------------------------------------------|\n| `0x42`        | `SEQUENCE_EXECUTE` | View detail | Writes an ABI encoded Sequence transaction to the buffer. |\n| `0x43`        | `SEQUENCE_SELF_EXECUTE` | View detail | Writes an ABI encoded Sequence self execute transaction to the buffer. |\n| `0x44` | `SEQUENCE_SIGNATURE_W0` | \u003cu8: weight\u003e \u003cbytes[66]: sig\u003e | Writes a Sequence signature part to the buffer. |\n| `0x45` | `SEQUENCE_SIGNATURE_W1` | \u003cbytes[66]: sig\u003e | Writes a Sequence Signature part to the buffer, with static weight 1. |\n| `0x46` | `SEQUENCE_SIGNATURE_W2` | \u003cbytes[66]: sig\u003e | Writes a Sequence Signature part to the buffer, with static weight 2. |\n| `0x47` | `SEQUENCE_SIGNATURE_W3` | \u003cbytes[66]: sig\u003e | Writes a Sequence Signature part to the buffer, with static weight 3. |\n| `0x48` | `SEQUENCE_SIGNATURE_W4` | \u003cbytes[66]: sig\u003e | Writes a Sequence Signature part to the buffer, with static weight 4. |\n| `0x49` | `SEQUENCE_ADDRESS_W0` | \u003cu8: weight\u003e \u003cu16: pointer\u003e | Writes a Sequence address flag to the buffer. |\n| `0x4a` | `SEQUENCE_ADDRESS_W1` | \u003cu16: pointer\u003e | Writes a Sequence address flag to the buffer, with static weight 1. |\n| `0x4b` | `SEQUENCE_ADDRESS_W2` | \u003cu16: pointer\u003e | Writes a Sequence address flag to the buffer, with static weight 2. |\n| `0x4c` | `SEQUENCE_ADDRESS_W3` | \u003cu16: pointer\u003e | Writes a Sequence address flag to the buffer, with static weight 3. |\n| `0x4d` | `SEQUENCE_ADDRESS_W4` | \u003cu16: pointer\u003e | Writes a Sequence address flag to the buffer, with static weight 4. |\n| `0x4e` | `SEQUENCE_NODE` | \u003cop: node\u003e | Writes a Sequence node to the buffer. |\n| `0x4f` | `SEQUENCE_BRANCH` | \u003cop: content\u003e | Writes a Sequence branch to the buffer. |\n| `0x50` | `SEQUENCE_SUBDIGEST` | \u003cop: subdigest\u003e | Writes a Sequence subdigest to the buffer. |\n| `0x51` | `SEQUENCE_NESTED` | \u003cu8: weight\u003e \u003cu8: threshold\u003e \u003cop: content\u003e | Writes a Sequence nested signature part to the buffer. |\n| `0x52` | `SEQUENCE_DYNAMIC_SIGNATURE` | \u003cu8: weight\u003e \u003cop: signer\u003e \u003cop: signature\u003e | Writes a Sequence EIP1271 dynamic signature to the buffer. |\n| `0x53` | `SEQUENCE_S_SIG_NO_CHAIN` | \u003cu8: weight\u003e \u003cop: checkpoint\u003e \u003cop: signature\u003e | Writes a Sequence signature (chain id 0) to the buffer. |\n| `0x54` | `SEQUENCE_S_SIG` | \u003cu8: weight\u003e \u003cop: checkpoint\u003e \u003cop: signature\u003e | Writes a Sequence signature to the buffer. |\n| `0x55` | `SEQUENCE_S_L_SIG_NO_CHAIN` | \u003cu16: weight\u003e \u003cop: checkpoint\u003e \u003cop: signature\u003e | Writes a Sequence signature (chain id 0) to the buffer. |\n| `0x56` | `SEQUENCE_S_L_SIG` | \u003cu16: weight\u003e \u003cop: checkpoint\u003e \u003cop: signature\u003e | Writes a Sequence signature to the buffer. |\n| `0x57` | `SEQUENCE_READ_CHAINED_S` | \u003cu8: size\u003e \u003cop: sig_1\u003e ... | Reads a chained Sequence signature. |\n| `0x58` | `SEQUENCE_READ_CHAINED_L` | \u003cu16: size\u003e \u003cop: sig_1\u003e ... | Reads a chained Sequence signature. |\n\n#### Literals\n\nThe highest defined operation is `0x58`, the remaining space is used to express literal values. Any operation with a code higher than `0x58` is a literal value.\n\nThe first literal flag is `0x59`, which is the literal `0x00`. The next literal flag is `0x5a`, which is the literal `0x01`, and so on. Literals are written to the buffer left-padded to 32 bytes.\n\n#### Array operations\n\nAll operations that accept an array of operations **MUST** be used with non-zero arrays, as the decompressor will not handle zero-length arrays correctly. If you need to write a zero-length array, use the `NO_OP` operation.\n\n#### Function selectors\n\nThe `decompressor.huff` contract contains a pre-defined set of function selectors, this list has been generated from common selectors used in the Ethereum network. It should account for ~90% of the cases.\n\nIf a selector is not in the list, it can be provided as a literal value by prefixing it with `00`, all operations that use selectors accept both indexed and literal values.\n\n#### Sequence Execute\n\nThe Sequence Execute operation is the same one used by the Sequence call and decode top level functions, it encodes a Sequence transaction to the buffer, ABI encoded.\n\nIt reads the following values:\n\n- `op: nonce_space` The nonce space for the transaction.\n- `op: nonce_value` The nonce value for the transaction.\n- `u8: len_transactions` The number of transactions in the Sequence transaction.\n- `\u003ctransactions\u003e` The transactions in the Sequence transaction (see Sequence Transactions).\n- `op: signature` The signature of the transaction.\n\n#### Sequence Self Execute\n\nIt works similarly to the Sequence Execute operation, but it encodes a Sequence self execute transaction to the buffer, ABI encoded. This operation only has the `\u003ctransactions\u003e` value.\n\n#### Sequence Transactions\n\nA Sequence transaction is prefixed by a bitmap byte, this byte determines which values are non-default. The bitmap is as follows:\n\n- `1000 0000` - 1 if it uses delegate call\n- `0100 0000` - 1 if it uses revert on error\n- `0010 0000` - 1 if it has a defined gas limit\n- `0001 0000` - 1 if it has a defined value\n- `0000 1000` - Unused\n- `0000 0100` - Unused\n- `0000 0010` - Unused\n- `0000 0001` - 1 if it has a defined data\n\n Afterwards, the each value is read (only if the corresponding bit is set):\n \n- `op: gas_limit` The gas limit for the transaction.\n- `op: target` The target for the transaction.\n- `op: value` The value for the transaction.\n- `op: data` The data for the transaction.\n\n## FAQs\n\n### Can the Huff code be optimized?\n\nIt probably can. This is my first time working with Huff, and this is a big contract. I am sure it can be gas-golfed further, but the gains should be minimal.\n\n### Does the compressor always generate the most efficient payload?\n\nNo, the compressor is a bit naive in its current form. It should work well for most \"common\" cases, but it may not pick the best compression for all cases. If you want to improve this tool, I think the biggest gains can be made here.\n\n### Why doesn't it compress using X/Y/Z method?\n\nBecause it didn't occur to me. The opcode set has a lot of room left for new operations. If you have a good idea for a new operation, please open an issue.\n\n### Why `callvalue` and not `push0`?\n\nI wanted to support all networks with the same code, and there is no reason to be sending funds to the decompressor contract. Notice that the behavior if `msg.value != 0` is undefined, expect the decompresor to fail if `msg.value != 0`.\n\n### Why not a built-in list of common contracts too?\n\nAgain, I wanted the same code for all networks, and \"common contracts\" will look different on different networks. But it is something that could be added if a single network is the main target.\n\n### Can I reuse the decompressor indexes?\n\nYes! The decompressor has the `0x05` \"function\" that allows you to fetch any storage slots from itself. If you build a similar contract, you can use it to fetch the indexes that the decompressor has stored.\n\n### Has this been audited?\n\nNo, but it can still be used safely. See the next question.\n\n### How should I use this in my project?\n\nThe contract is quite big and could have vulnerabilities, so I would not recommend \"trusting\" it in your setup. However, you can use it as long as it acts as a \"router\" or \"entrypoint\" to some other contract that validates the data, just make sure to have an alternative path for uncompressed data.\n\n---\n\n## Setup dev environment\n\nIf you'd like to setup the dev environment to run tests:\n\n1. Install [foundry](https://getfoundry.sh/)\n2. Install [huff](https://docs.huff.sh/get-started/installing/)\n3. Install [go](https://go.dev/)\n4. `make bootstrap`\n## Development\n\nIf you'd like to develop on the repo, here are some useful commands:\n\n1. `make forge`\n2. `make build`\n3. `make test`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0xsequence%2Fczip","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F0xsequence%2Fczip","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0xsequence%2Fczip/lists"}