SkillAgentSearch skills...

Czip

EVM Calldata Zip, aka czip

Install / Use

/learn @0xsequence/Czip
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

CZIP: EVM Calldata Zip

CZIP 😈

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.

The 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.

A 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.

Install

$ brew tap 0xsequence/tap
$ brew install czip-compressor
$ czip-compressor

or

$ docker run ghcr.io/0xsequence/czip-compressor

or

$ go install github.com/0xsequence/czip/compressor/cmd/czip-compressor@latest

Usage

The compressor has the following commands:

  • encode-call <decode/call/call-return> <hex_data> <addr> Compresses a call to addr with hex_data.
  • encode-calls <decode/call> <hex_data_1> <addr_1> <hex_data_2> <addr_2> ... Compresses multiple calls into one payload.
  • encode-any <data> Encodes any data into a compressed representation.
  • encode-sequence-tx <decode/call> <sequence_tx> <sequence_wallet> Compresses a Sequence wallet transaction.
czip-compressor is a tool for compressing Ethereum calldata. The compressed data can be decompressed using the decompressor contract.

Usage:
  czip-compressor [command]

Available Commands:
  completion         Generate the autocompletion script for the specified shell
  encode-any         Compress any calldata: <hex>
  encode-call        Compress a call to a contract: <data> <to>
  encode-calls       Compress multiple calls to many contracts: <data> <to> <data> <to> ... <data> <to>
  encode-sequence-tx Compress a Sequence Wallet transaction
  extras             Additional encoding methods, used for testing and debugging.
  help               Help about any command

Flags:
      --allow-opcodes strings      Will only encode using these operations, separated by commas.
      --cache-dir string           Path to the cache dir for indexes. (default "/tmp/czip-cache")
  -c, --contract string            Contract address of the decompressor contract.
      --disallow-opcodes strings   Will not encode using these operations, separated by commas.
  -h, --help                       help for czip-compressor
  -p, --provider string            Ethereum RPC provider URL.
  -s, --use-storage                Use stateful read/write storage during compression.

Use "czip-compressor [command] --help" for more information about a command.

Encode call

It encodes a single call to a contract, the subcommands are:

  • decode Generates a payload that, when sent to the decompressor.huff contract, will decompress the calldata and return the caller, without performing the call.
  • call Generates a payload that, when sent to the decompressor.huff contract, will decompress the calldata and perform the call, ignoring the return value.
  • 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.
czip-compressor encode-call decode \
0xa9059cbb0000000000000000000000008bf74fb902cdad5d2d8ca0d3bbc7bb16894b9c350000000000000000000000000000000000000000000000000000000006052340 \
0xdAC17F958D2ee523a2206206994597C13D831ec7

> 0x0b3701148bf74fb902cdad5d2d8ca0d3bbc7bb16894b9c35332bf214dac17f958d2ee523a2206206994597c13d831ec7

Encode Calls

It encodes multiple calls to contracts, the subcommands are:

  • decode Generates a payload that, when sent to the decompressor.huff contract, will decompress all calls and return them decompressed, without performing the calls.
  • call Generates a payload that, when sent to the decompressor.huff contract, will decompress the calls and perform them, ignoring the return values.

Notice that the call-return subcommand is not available in this mode.

czip-compressor encode-calls decode \
  0xa9059cbb0000000000000000000000009813d80d0686406b79c29b2b8a672a13725facb300000000000000000000000000000000000000000000000ae56f730e6d840000 \
  0xdac17f958d2ee523a2206206994597c13d831ec7 \
  0x095ea7b30000000000000000000000007c56be0ad3128acc33190484cd1badebc8c76240ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff \
  0xdac17f958d2ee523a2206206994597c13d831ec7

> 0x0c023701149813d80d0686406b79c29b2b8a672a13725facb3338fda14dac17f958d2ee523a2206206994597c13d831ec73702147c56be0ad3128acc33190484cd1badebc8c7624031ff3d001c

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.

Encode Any

It encodes any data into a compressed representation. Sending the payload to the decompressor.huff contract will return the original data.

czip-compressor encode-any \
  0x0000000000000000000000000000000000000000000000012a5f58168ee60000

> 0x0d3388d7

Encode Sequence Transaction

It 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.

Using storage indexes

By 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.

Storage indexes can be enabled using the following flags:

  • --use-storage true Enables the use of storage indexes.
  • --contract <address> An instance of the decompressor.huff contract to use for storage indexes.
  • --provider <provider> The provider from which to fetch the pointers.

Notice that a cache on /tmp/czip-cache/czip-indexes-<chain-id>.json is automatically created to avoid fetching the same pointers multiple times. The cache dir can be changed using the --cache-dir flag.

Example

czip-compressor encode-call decode \
  0xa9059cbb000000000000000000000000963752cac40e583dea143d6262e24f89c9e1f91100000000000000000000000000000000000000000000000000000000000003fc \
  0x750ba8b76187092B0D1E87E28daaf484d1b5273b

> 0x0b370114963752cac40e583dea143d6262e24f89c9e1f9110203fc14750ba8b76187092b0d1e87e28daaf484d1b5273b

czip-compressor encode-call decode \
  --contract 0x8C5CF0a201C1F0C1517a23699BE48070724e7a70 \
  --provider https://nodes.sequence.app/arbitrum-nova \
  --use-storage \
  0xa9059cbb000000000000000000000000963752cac40e583dea143d6262e24f89c9e1f91100000000000000000000000000000000000000000000000000000000000003fc \
  0x750ba8b76187092B0D1E87E28daaf484d1b5273b

> 0x0b37012700010203fc270002

See it in action: https://nova.arbiscan.io/tx/0x86e7b4177c0d219a87cc58f93ae2ecf2f490a719119c283f61cdc88585cc7c7b

How to decompress

Sending 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).

The decompressor.huff contract has no selectors; the data does not need to be re-encoded and can be sent directly to the contract.

Cast example

Try running the following command; it will inflate the data and return the original call data. You can do the same thing on-chain.

cast call \
  --rpc-url https://nodes.sequence.app/arbitrum-nova \
  0x8C5CF0a201C1F0C1517a23699BE48070724e7a70 \
  0x0b37012700010203fc270002

> 0xa9059cbb000000000000000000000000963752cac40e583dea143d6262e24f89c9e1f91100000000000000000000000000000000000000000000000000000000000003fc000000000000000000000000750ba8b76187092b0d1e87e28daaf484d1b5273b

Solidity example

Decompressing on-chain is as simple as calling the decompressor contract with the payload.

contract YourContract {
  event WeGotData(bytes data);

  function doSomething(bytes calldata _compressed) external {
    (bool ok, bytes memory data) = address(0x8C5CF0a201C1F0C1517a23699BE48070724e7a70).call(_compressed);
    require(ok, "Decompression failed");
    emit WeGotData(data);
  }
}

Notice 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.

Compression gains

The 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.

| Network | Decompressor Address | Savings | |---------------|--------------------------------------------|----------| | Arbitrum | 0x8C5CF0a201C1F0C1517a23699BE48070724e7a70 | ~50% | | Optimism | 0x8C5CF0a201C1F0C1517a23699BE48070724e7a70 | ~50% | | Base | 0x8C5CF0a201C1F0C1517a23699BE48070724e7a70 | ~50% | | Arbitrum Nova | 0x8C5CF0a201C1F0C1517a23699BE48070724e7a70 | ~15% | | Polygon | -- | Negative | | Ethereum | -- | Negative | | Polygon zkEVM | -- | Negative |

The 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.

Sending ETH cost comparison

The transaction cost for sending ETH using a smart contract wallet, with a 2/2 configuration, goes from

View on GitHub
GitHub Stars106
CategoryDevelopment
Updated2mo ago
Forks5

Languages

Go

Security Score

80/100

Audited on Jan 4, 2026

No findings