Arbitrum Stylus logo

Stylus by Example

ABI Encode

The ABI Encode has 2 types: (encode)[https://docs.soliditylang.org/en/latest/abi-spec.html#strict-encoding-mode] and (encode_packed)[https://docs.soliditylang.org/en/latest/abi-spec.html#non-standard-packed-mode].

  • encode concatenates values with 32-byte word padding for each value.
  • encode_packed concatenates the exact byte representations with no padding. (Example: encode_packed("a","bc") == encode_packed("ab","c").)

Suppose we have a tuple (target, value, func, data, timestamp) with Alloy types (Address, U256, String, Bytes, U256).

Imports

First, import the primitives and ABI Bytes, plus String from alloc:

1use stylus_sdk::{
2    abi::Bytes,
3    alloy_primitives::{Address, U256, FixedBytes},
4    prelude::*,
5};
6use alloc::string::String;
1use stylus_sdk::{
2    abi::Bytes,
3    alloy_primitives::{Address, U256, FixedBytes},
4    prelude::*,
5};
6use alloc::string::String;

Because type names overlap between alloy_primitives and alloy_sol_types, alias the Solidity types you’ll encode with:

1use alloy_sol_types::{
2    sol_data::{Address as SOLAddress, String as SOLString, Bytes as SOLBytes, *},
3    SolType,
4};
1use alloy_sol_types::{
2    sol_data::{Address as SOLAddress, String as SOLString, Bytes as SOLBytes, *},
3    SolType,
4};

encode

Use the SolType tuple and abi_encode_params (standard ABI encoding with padding):

1// define the Sol types tuple
2type TxIdHashType = (SOLAddress, Uint<256>, SOLString, SOLBytes, Uint<256>);
3
4// set the tuple
5let tx_hash_data = (target, value, func, data, timestamp);
6
7// encode the tuple (padded ABI encoding)
8let tx_hash_bytes = TxIdHashType::abi_encode_params(&tx_hash_data);
1// define the Sol types tuple
2type TxIdHashType = (SOLAddress, Uint<256>, SOLString, SOLBytes, Uint<256>);
3
4// set the tuple
5let tx_hash_data = (target, value, func, data, timestamp);
6
7// encode the tuple (padded ABI encoding)
8let tx_hash_bytes = TxIdHashType::abi_encode_params(&tx_hash_data);

encode_packed

Two ways to do packed encoding (no padding):

A) Using abi_encode_packed:

1type TxIdHashType = (SOLAddress, Uint<256>, SOLString, SOLBytes, Uint<256>);
2let tx_hash_data = (target, value, func, data, timestamp);
3let tx_hash_data_encode_packed = TxIdHashType::abi_encode_packed(&tx_hash_data);
1type TxIdHashType = (SOLAddress, Uint<256>, SOLString, SOLBytes, Uint<256>);
2let tx_hash_data = (target, value, func, data, timestamp);
3let tx_hash_data_encode_packed = TxIdHashType::abi_encode_packed(&tx_hash_data);

B) Manual concat of byte slices:

1let tx_hash_data_encode_packed = [
2    &target.to_vec(),
3    &value.to_be_bytes_vec(),
4    func.as_bytes(),
5    &data.to_vec(),
6    &timestamp.to_be_bytes_vec(),
7].concat();
1let tx_hash_data_encode_packed = [
2    &target.to_vec(),
3    &value.to_be_bytes_vec(),
4    func.as_bytes(),
5    &data.to_vec(),
6    &timestamp.to_be_bytes_vec(),
7].concat();

Full Example code:

src/lib.rs

1Loading...
1Loading...

src/main.rs

1Loading...
1Loading...

Cargo.toml

1Loading...
1Loading...