Arbitrum Stylus logo

Stylus by Example

Arrays

Like solidity, Array can have a compile-time fixed size or a dynamic size. Here, we will guide you on how to use arrays in Stylus, we provide 3 examples here:

  1. Dynamic-size array
  2. Fixed-size array
  3. Custome struct element array

Dynamic-size array

Dynamic-size array is an array that can change its size at runtime.

Declare a dynamic-size array in Stylus is similar to Solidity, you can use the following code to declare a dynamic-size array:

1sol_storage! {
2    #[entrypoint]
3    pub struct Arrays {
4        uint256[] arr;
5    }
6}
1sol_storage! {
2    #[entrypoint]
3    pub struct Arrays {
4        uint256[] arr;
5    }
6}

Then you can use the following code to push/get an element of the array and get the length of the array:

1#[public]
2impl Arrays {
3    // dynamic array
4    // push an element to the dynamic array
5    pub fn push(&mut self, i: U256) {
6        self.arr.push(i);
7    }
8
9    // get the element at the index
10    pub fn get_element(&self, index: U256) -> U256 {
11        self.arr.get(index).unwrap()
12    }
13
14    // get the length of the array
15    pub fn get_arr_length(&self) -> U256 {
16        U256::from(self.arr.len())
17    }
18
19    // remove will not change the length of the array
20    pub fn remove(&mut self, index: U256) {
21        let mut last_element = self.arr.setter(index).unwrap();
22        last_element.erase()
23    }
24}
1#[public]
2impl Arrays {
3    // dynamic array
4    // push an element to the dynamic array
5    pub fn push(&mut self, i: U256) {
6        self.arr.push(i);
7    }
8
9    // get the element at the index
10    pub fn get_element(&self, index: U256) -> U256 {
11        self.arr.get(index).unwrap()
12    }
13
14    // get the length of the array
15    pub fn get_arr_length(&self) -> U256 {
16        U256::from(self.arr.len())
17    }
18
19    // remove will not change the length of the array
20    pub fn remove(&mut self, index: U256) {
21        let mut last_element = self.arr.setter(index).unwrap();
22        last_element.erase()
23    }
24}

Fixed-size array

Fixed-size array is an array that has a fixed size at compile time.

Declare a fixed-size array in Stylus is similar to Solidity, you can use the following code to declare a fixed-size array:

1sol_storage! {
2    #[entrypoint]
3    pub struct Arrays {
4        uint256[3] arr2;
5    }
6}
1sol_storage! {
2    #[entrypoint]
3    pub struct Arrays {
4        uint256[3] arr2;
5    }
6}

Then you can use the following code to get an element of the array and get the length of the array:

1#[public]
2impl Arrays {
3    // fixed length array
4    // get an element from the fixed length array
5    pub fn get_arr2_element(&self, index: U256) -> U256 {
6        self.arr2.get(index).unwrap()
7    }
8
9    // get the fixed length array size
10    pub fn get_arr2_length(&self) -> U256 {
11        U256::from(self.arr2.len())
12    }
13
14    // set an element in the fixed length array
15    pub fn set_arr2_value(&mut self, index: U256, value: U256) {
16        self.arr2.setter(index).unwrap().set(value);
17    }
18}
1#[public]
2impl Arrays {
3    // fixed length array
4    // get an element from the fixed length array
5    pub fn get_arr2_element(&self, index: U256) -> U256 {
6        self.arr2.get(index).unwrap()
7    }
8
9    // get the fixed length array size
10    pub fn get_arr2_length(&self) -> U256 {
11        U256::from(self.arr2.len())
12    }
13
14    // set an element in the fixed length array
15    pub fn set_arr2_value(&mut self, index: U256, value: U256) {
16        self.arr2.setter(index).unwrap().set(value);
17    }
18}

Note that the fixed-size array can't push new elements.

Custom struct element array

Custom struct element array is an array that can store custom struct elements.

You can use the following code to declare a custom struct element array:

1sol_storage! {
2    #[entrypoint]
3    pub struct Arrays {
4        Info[] arr3; // struct array
5    }
6
7    pub struct Info {
8        address setter;
9        uint256 value;
10    }
11}
1sol_storage! {
2    #[entrypoint]
3    pub struct Arrays {
4        Info[] arr3; // struct array
5    }
6
7    pub struct Info {
8        address setter;
9        uint256 value;
10    }
11}

Then you can use the following code to push/get an element of the array and get the length of the array:

1#[public]
2impl Arrays {
3    // struct array
4    // push an element to the struct array
5    pub fn push_arr3_info(&mut self, value: U256) {
6        let mut new_info = self.arr3.grow();
7        new_info.setter.set(msg::sender());
8        new_info.value.set(value);
9    }
10
11    // get the length of the struct array
12    pub fn get_arr3_length(&self) -> U256 {
13        U256::from(self.arr3.len())
14    }
15
16    // get the value of the struct array at the index
17    pub fn get_arr3_info(&self, index: U256) -> (Address, U256) {
18        let info = self.arr3.get(index).unwrap();
19        (info.setter.get(), info.value.get())
20    }
21
22    // Find the first index of the expected value in the array
23    pub fn find_arr3_first_expected_value(&self, expected_value: U256) -> U256 {
24        for i in 0..self.arr3.len() {
25            let (_, value) = self.get_arr3_info(U256::from(i));
26            if value == expected_value {
27                return U256::from(i);
28            }
29        }
30        // if not found, return the size of arr
31        U256::from(self.arr3.len())
32    }
33}
1#[public]
2impl Arrays {
3    // struct array
4    // push an element to the struct array
5    pub fn push_arr3_info(&mut self, value: U256) {
6        let mut new_info = self.arr3.grow();
7        new_info.setter.set(msg::sender());
8        new_info.value.set(value);
9    }
10
11    // get the length of the struct array
12    pub fn get_arr3_length(&self) -> U256 {
13        U256::from(self.arr3.len())
14    }
15
16    // get the value of the struct array at the index
17    pub fn get_arr3_info(&self, index: U256) -> (Address, U256) {
18        let info = self.arr3.get(index).unwrap();
19        (info.setter.get(), info.value.get())
20    }
21
22    // Find the first index of the expected value in the array
23    pub fn find_arr3_first_expected_value(&self, expected_value: U256) -> U256 {
24        for i in 0..self.arr3.len() {
25            let (_, value) = self.get_arr3_info(U256::from(i));
26            if value == expected_value {
27                return U256::from(i);
28            }
29        }
30        // if not found, return the size of arr
31        U256::from(self.arr3.len())
32    }
33}

Full example code:

src/lib.rs

1// Allow `cargo stylus export-abi` to generate a main function.
2#![cfg_attr(not(feature = "export-abi"), no_main)]
3extern crate alloc;
4
5/// Import items from the SDK. The prelude contains common traits and macros.
6use stylus_sdk::{alloy_primitives::{Address, U256}, prelude::*, msg};
7
8// Define some persistent storage using the Solidity ABI.
9// `Arrays` will be the entrypoint.
10sol_storage! {
11    #[entrypoint]
12    pub struct Arrays {
13        uint256[] arr;
14        uint256[10] arr2; // fixed length array
15        Info[] arr3; // struct array
16    }
17
18    pub struct Info {
19        address setter;
20        uint256 value;
21    }
22}
23
24/// Declare that `Arrays` is a contract with the following external methods.
25#[public]
26impl Arrays {
27    // dynamic array
28    // push an element to the dynamic array
29    pub fn push(&mut self, i: U256) {
30        self.arr.push(i);
31    }
32
33    // get the element at the index
34    pub fn get_element(&self, index: U256) -> U256 {
35        self.arr.get(index).unwrap()
36    }
37
38    // get the length of the array
39    pub fn get_arr_length(&self) -> U256 {
40        U256::from(self.arr.len())
41    }
42
43    // remove will not change the length of the array
44    pub fn remove(&mut self, index: U256) {
45        let mut last_element = self.arr.setter(index).unwrap();
46        last_element.erase()
47    }
48
49    // fixed length array
50    // get an element from the fixed length array
51    pub fn get_arr2_element(&self, index: U256) -> U256 {
52        self.arr2.get(index).unwrap()
53    }
54
55    // get the fixed length array size
56    pub fn get_arr2_length(&self) -> U256 {
57        U256::from(self.arr2.len())
58    }
59
60    // set an element in the fixed length array
61    pub fn set_arr2_value(&mut self, index: U256, value: U256) {
62        self.arr2.setter(index).unwrap().set(value);
63    }
64
65    // struct array
66    // push an element to the struct array
67    pub fn push_arr3_info(&mut self, value: U256) {
68        let mut new_info = self.arr3.grow();
69        new_info.setter.set(msg::sender());
70        new_info.value.set(value);
71    }
72
73    // get the length of the struct array
74    pub fn get_arr3_length(&self) -> U256 {
75        U256::from(self.arr3.len())
76    }
77
78    // get the value of the struct array at the index
79    pub fn get_arr3_info(&self, index: U256) -> (Address, U256) {
80        let info = self.arr3.get(index).unwrap();
81        (info.setter.get(), info.value.get())
82    }
83
84    // Find the first index of the expected value in the array
85    pub fn find_arr3_first_expected_value(&self, expected_value: U256) -> U256 {
86        for i in 0..self.arr3.len() {
87            let (_, value) = self.get_arr3_info(U256::from(i));
88            if value == expected_value {
89                return U256::from(i);
90            }
91        }
92        // if not found, return the size of arr
93        U256::from(self.arr3.len())
94    }
95}
1// Allow `cargo stylus export-abi` to generate a main function.
2#![cfg_attr(not(feature = "export-abi"), no_main)]
3extern crate alloc;
4
5/// Import items from the SDK. The prelude contains common traits and macros.
6use stylus_sdk::{alloy_primitives::{Address, U256}, prelude::*, msg};
7
8// Define some persistent storage using the Solidity ABI.
9// `Arrays` will be the entrypoint.
10sol_storage! {
11    #[entrypoint]
12    pub struct Arrays {
13        uint256[] arr;
14        uint256[10] arr2; // fixed length array
15        Info[] arr3; // struct array
16    }
17
18    pub struct Info {
19        address setter;
20        uint256 value;
21    }
22}
23
24/// Declare that `Arrays` is a contract with the following external methods.
25#[public]
26impl Arrays {
27    // dynamic array
28    // push an element to the dynamic array
29    pub fn push(&mut self, i: U256) {
30        self.arr.push(i);
31    }
32
33    // get the element at the index
34    pub fn get_element(&self, index: U256) -> U256 {
35        self.arr.get(index).unwrap()
36    }
37
38    // get the length of the array
39    pub fn get_arr_length(&self) -> U256 {
40        U256::from(self.arr.len())
41    }
42
43    // remove will not change the length of the array
44    pub fn remove(&mut self, index: U256) {
45        let mut last_element = self.arr.setter(index).unwrap();
46        last_element.erase()
47    }
48
49    // fixed length array
50    // get an element from the fixed length array
51    pub fn get_arr2_element(&self, index: U256) -> U256 {
52        self.arr2.get(index).unwrap()
53    }
54
55    // get the fixed length array size
56    pub fn get_arr2_length(&self) -> U256 {
57        U256::from(self.arr2.len())
58    }
59
60    // set an element in the fixed length array
61    pub fn set_arr2_value(&mut self, index: U256, value: U256) {
62        self.arr2.setter(index).unwrap().set(value);
63    }
64
65    // struct array
66    // push an element to the struct array
67    pub fn push_arr3_info(&mut self, value: U256) {
68        let mut new_info = self.arr3.grow();
69        new_info.setter.set(msg::sender());
70        new_info.value.set(value);
71    }
72
73    // get the length of the struct array
74    pub fn get_arr3_length(&self) -> U256 {
75        U256::from(self.arr3.len())
76    }
77
78    // get the value of the struct array at the index
79    pub fn get_arr3_info(&self, index: U256) -> (Address, U256) {
80        let info = self.arr3.get(index).unwrap();
81        (info.setter.get(), info.value.get())
82    }
83
84    // Find the first index of the expected value in the array
85    pub fn find_arr3_first_expected_value(&self, expected_value: U256) -> U256 {
86        for i in 0..self.arr3.len() {
87            let (_, value) = self.get_arr3_info(U256::from(i));
88            if value == expected_value {
89                return U256::from(i);
90            }
91        }
92        // if not found, return the size of arr
93        U256::from(self.arr3.len())
94    }
95}

Cargo.toml

1[package]
2name = "stylus-arrays-example"
3version = "0.1.0"
4edition = "2021"
5description = "Stylus arrays example"
6
7[dependencies]
8alloy-primitives = "=0.7.6"
9alloy-sol-types = "=0.7.6"
10mini-alloc = "0.4.2"
11stylus-sdk = "0.6.0"
12hex = "0.4.3"
13dotenv = "0.15.0"
14
15[dev-dependencies]
16tokio = { version = "1.12.0", features = ["full"] }
17ethers = "2.0"
18eyre = "0.6.8"
19
20[features]
21export-abi = ["stylus-sdk/export-abi"]
22debug = ["stylus-sdk/debug"]
23
24[[bin]]
25name = "stylus-arrays-example"
26path = "src/main.rs"
27
28[lib]
29crate-type = ["lib", "cdylib"]
30
31[profile.release]
32codegen-units = 1
33strip = true
34lto = true
35panic = "abort"
36opt-level = "s"
1[package]
2name = "stylus-arrays-example"
3version = "0.1.0"
4edition = "2021"
5description = "Stylus arrays example"
6
7[dependencies]
8alloy-primitives = "=0.7.6"
9alloy-sol-types = "=0.7.6"
10mini-alloc = "0.4.2"
11stylus-sdk = "0.6.0"
12hex = "0.4.3"
13dotenv = "0.15.0"
14
15[dev-dependencies]
16tokio = { version = "1.12.0", features = ["full"] }
17ethers = "2.0"
18eyre = "0.6.8"
19
20[features]
21export-abi = ["stylus-sdk/export-abi"]
22debug = ["stylus-sdk/debug"]
23
24[[bin]]
25name = "stylus-arrays-example"
26path = "src/main.rs"
27
28[lib]
29crate-type = ["lib", "cdylib"]
30
31[profile.release]
32codegen-units = 1
33strip = true
34lto = true
35panic = "abort"
36opt-level = "s"