Keccak256 is a cryptographic hash function that takes an input of an arbitrary length and produces a fixed-length output of 256 bits.
Keccak256 is a member of the SHA-3 family of hash functions.
keccak256 computes the Keccak-256 hash of the input.
Some use cases are:
Here we will use stylus-sdk::crypto::keccak
to calculate the keccak256 hash of the input data:
1pub fn keccak<T: AsRef<[u8]>>(bytes: T) -> B256
1pub fn keccak<T: AsRef<[u8]>>(bytes: T) -> B256
1// Only run this as a WASM if the export-abi feature is not set.
2#![cfg_attr(not(any(feature = "export-abi", test)), no_main)]
3extern crate alloc;
4
5/// Import items from the SDK. The prelude contains common traits and macros.
6use stylus_sdk::{alloy_primitives::{U256, Address, FixedBytes}, abi::Bytes, prelude::*, crypto::keccak};
7use alloc::string::String;
8use alloc::vec::Vec;
9// Becauce the naming of alloy_primitives and alloy_sol_types is the same, so we need to re-name the types in alloy_sol_types
10use alloy_sol_types::{sol_data::{Address as SOLAddress, String as SOLString, Bytes as SOLBytes, *}, SolType};
11use alloy_sol_types::sol;
12
13// Define error
14sol! {
15 error DecodedFailed();
16}
17
18// Error types for the MultiSig contract
19#[derive(SolidityError)]
20pub enum HasherError{
21 DecodedFailed(DecodedFailed)
22}
23
24#[solidity_storage]
25#[entrypoint]
26pub struct Hasher {
27}
28/// Declare that `Hasher` is a contract with the following external methods.
29#[public]
30impl Hasher {
31
32 // Encode the data and hash it
33 pub fn encode_and_hash(
34 &self,
35 target: Address,
36 value: U256,
37 func: String,
38 data: Bytes,
39 timestamp: U256
40 ) -> FixedBytes<32> {
41 // define sol types tuple
42 type TxIdHashType = (SOLAddress, Uint<256>, SOLString, SOLBytes, Uint<256>);
43 // set the tuple
44 let tx_hash_data = (target, value, func, data, timestamp);
45 // encode the tuple
46 let tx_hash_data_encode = TxIdHashType::abi_encode_sequence(&tx_hash_data);
47 // hash the encoded data
48 keccak(tx_hash_data_encode).into()
49 }
50
51 // This should always return true
52 pub fn encode_and_decode(
53 &self,
54 address: Address,
55 amount: U256
56 ) -> Result<bool, HasherError> {
57 // define sol types tuple
58 type TxIdHashType = (SOLAddress, Uint<256>);
59 // set the tuple
60 let tx_hash_data = (address, amount);
61 // encode the tuple
62 let tx_hash_data_encode = TxIdHashType::abi_encode_sequence(&tx_hash_data);
63
64 let validate = true;
65
66 // Check the result
67 match TxIdHashType::abi_decode_sequence(&tx_hash_data_encode, validate) {
68 Ok(res) => Ok(res == tx_hash_data),
69 Err(_) => {
70 return Err(HasherError::DecodedFailed(DecodedFailed{}));
71 },
72 }
73 }
74
75 // Packed encode the data and hash it, the same result with the following one
76 pub fn packed_encode_and_hash_1(
77 &self,
78 target: Address,
79 value: U256,
80 func: String,
81 data: Bytes,
82 timestamp: U256
83 )-> FixedBytes<32> {
84 // define sol types tuple
85 type TxIdHashType = (SOLAddress, Uint<256>, SOLString, SOLBytes, Uint<256>);
86 // set the tuple
87 let tx_hash_data = (target, value, func, data, timestamp);
88 // encode the tuple
89 let tx_hash_data_encode_packed = TxIdHashType::abi_encode_packed(&tx_hash_data);
90 // hash the encoded data
91 keccak(tx_hash_data_encode_packed).into()
92 }
93
94 // Packed encode the data and hash it, the same result with the above one
95 pub fn packed_encode_and_hash_2(
96 &self,
97 target: Address,
98 value: U256,
99 func: String,
100 data: Bytes,
101 timestamp: U256
102 )-> FixedBytes<32> {
103 // set the data to arrary and concat it directly
104 let tx_hash_data_encode_packed = [&target.to_vec(), &value.to_be_bytes_vec(), func.as_bytes(), &data.to_vec(), ×tamp.to_be_bytes_vec()].concat();
105 // hash the encoded data
106 keccak(tx_hash_data_encode_packed).into()
107 }
108
109
110 // The func example: "transfer(address,uint256)"
111 pub fn encode_with_signature(
112 &self,
113 func: String,
114 address: Address,
115 amount: U256
116 ) -> Vec<u8> {
117 type TransferType = (SOLAddress, Uint<256>);
118 let tx_data = (address, amount);
119 let data = TransferType::abi_encode_sequence(&tx_data);
120 // Get function selector
121 let hashed_function_selector: FixedBytes<32> = keccak(func.as_bytes().to_vec()).into();
122 // Combine function selector and input data (use abi_packed way)
123 let calldata = [&hashed_function_selector[..4], &data].concat();
124 calldata
125 }
126
127 // The func example: "transfer(address,uint256)"
128 pub fn encode_with_signature_and_hash(
129 &self,
130 func: String,
131 address: Address,
132 amount: U256
133 ) -> FixedBytes<32> {
134 type TransferType = (SOLAddress, Uint<256>);
135 let tx_data = (address, amount);
136 let data = TransferType::abi_encode_sequence(&tx_data);
137 // Get function selector
138 let hashed_function_selector: FixedBytes<32> = keccak(func.as_bytes().to_vec()).into();
139 // Combine function selector and input data (use abi_packed way)
140 let calldata = [&hashed_function_selector[..4], &data].concat();
141 keccak(calldata).into()
142 }
143}
1// Only run this as a WASM if the export-abi feature is not set.
2#![cfg_attr(not(any(feature = "export-abi", test)), no_main)]
3extern crate alloc;
4
5/// Import items from the SDK. The prelude contains common traits and macros.
6use stylus_sdk::{alloy_primitives::{U256, Address, FixedBytes}, abi::Bytes, prelude::*, crypto::keccak};
7use alloc::string::String;
8use alloc::vec::Vec;
9// Becauce the naming of alloy_primitives and alloy_sol_types is the same, so we need to re-name the types in alloy_sol_types
10use alloy_sol_types::{sol_data::{Address as SOLAddress, String as SOLString, Bytes as SOLBytes, *}, SolType};
11use alloy_sol_types::sol;
12
13// Define error
14sol! {
15 error DecodedFailed();
16}
17
18// Error types for the MultiSig contract
19#[derive(SolidityError)]
20pub enum HasherError{
21 DecodedFailed(DecodedFailed)
22}
23
24#[solidity_storage]
25#[entrypoint]
26pub struct Hasher {
27}
28/// Declare that `Hasher` is a contract with the following external methods.
29#[public]
30impl Hasher {
31
32 // Encode the data and hash it
33 pub fn encode_and_hash(
34 &self,
35 target: Address,
36 value: U256,
37 func: String,
38 data: Bytes,
39 timestamp: U256
40 ) -> FixedBytes<32> {
41 // define sol types tuple
42 type TxIdHashType = (SOLAddress, Uint<256>, SOLString, SOLBytes, Uint<256>);
43 // set the tuple
44 let tx_hash_data = (target, value, func, data, timestamp);
45 // encode the tuple
46 let tx_hash_data_encode = TxIdHashType::abi_encode_sequence(&tx_hash_data);
47 // hash the encoded data
48 keccak(tx_hash_data_encode).into()
49 }
50
51 // This should always return true
52 pub fn encode_and_decode(
53 &self,
54 address: Address,
55 amount: U256
56 ) -> Result<bool, HasherError> {
57 // define sol types tuple
58 type TxIdHashType = (SOLAddress, Uint<256>);
59 // set the tuple
60 let tx_hash_data = (address, amount);
61 // encode the tuple
62 let tx_hash_data_encode = TxIdHashType::abi_encode_sequence(&tx_hash_data);
63
64 let validate = true;
65
66 // Check the result
67 match TxIdHashType::abi_decode_sequence(&tx_hash_data_encode, validate) {
68 Ok(res) => Ok(res == tx_hash_data),
69 Err(_) => {
70 return Err(HasherError::DecodedFailed(DecodedFailed{}));
71 },
72 }
73 }
74
75 // Packed encode the data and hash it, the same result with the following one
76 pub fn packed_encode_and_hash_1(
77 &self,
78 target: Address,
79 value: U256,
80 func: String,
81 data: Bytes,
82 timestamp: U256
83 )-> FixedBytes<32> {
84 // define sol types tuple
85 type TxIdHashType = (SOLAddress, Uint<256>, SOLString, SOLBytes, Uint<256>);
86 // set the tuple
87 let tx_hash_data = (target, value, func, data, timestamp);
88 // encode the tuple
89 let tx_hash_data_encode_packed = TxIdHashType::abi_encode_packed(&tx_hash_data);
90 // hash the encoded data
91 keccak(tx_hash_data_encode_packed).into()
92 }
93
94 // Packed encode the data and hash it, the same result with the above one
95 pub fn packed_encode_and_hash_2(
96 &self,
97 target: Address,
98 value: U256,
99 func: String,
100 data: Bytes,
101 timestamp: U256
102 )-> FixedBytes<32> {
103 // set the data to arrary and concat it directly
104 let tx_hash_data_encode_packed = [&target.to_vec(), &value.to_be_bytes_vec(), func.as_bytes(), &data.to_vec(), ×tamp.to_be_bytes_vec()].concat();
105 // hash the encoded data
106 keccak(tx_hash_data_encode_packed).into()
107 }
108
109
110 // The func example: "transfer(address,uint256)"
111 pub fn encode_with_signature(
112 &self,
113 func: String,
114 address: Address,
115 amount: U256
116 ) -> Vec<u8> {
117 type TransferType = (SOLAddress, Uint<256>);
118 let tx_data = (address, amount);
119 let data = TransferType::abi_encode_sequence(&tx_data);
120 // Get function selector
121 let hashed_function_selector: FixedBytes<32> = keccak(func.as_bytes().to_vec()).into();
122 // Combine function selector and input data (use abi_packed way)
123 let calldata = [&hashed_function_selector[..4], &data].concat();
124 calldata
125 }
126
127 // The func example: "transfer(address,uint256)"
128 pub fn encode_with_signature_and_hash(
129 &self,
130 func: String,
131 address: Address,
132 amount: U256
133 ) -> FixedBytes<32> {
134 type TransferType = (SOLAddress, Uint<256>);
135 let tx_data = (address, amount);
136 let data = TransferType::abi_encode_sequence(&tx_data);
137 // Get function selector
138 let hashed_function_selector: FixedBytes<32> = keccak(func.as_bytes().to_vec()).into();
139 // Combine function selector and input data (use abi_packed way)
140 let calldata = [&hashed_function_selector[..4], &data].concat();
141 keccak(calldata).into()
142 }
143}
1[package]
2name = "stylus-encode-hashing"
3version = "0.1.0"
4edition = "2021"
5
6[dependencies]
7alloy-primitives = "=0.7.6"
8alloy-sol-types = "=0.7.6"
9mini-alloc = "0.4.2"
10stylus-sdk = "0.6.0"
11hex = "0.4.3"
12sha3 = "0.10.8"
13
14[features]
15export-abi = ["stylus-sdk/export-abi"]
16debug = ["stylus-sdk/debug"]
17
18[lib]
19crate-type = ["lib", "cdylib"]
20
21[profile.release]
22codegen-units = 1
23strip = true
24lto = true
25panic = "abort"
26opt-level = "s"
1[package]
2name = "stylus-encode-hashing"
3version = "0.1.0"
4edition = "2021"
5
6[dependencies]
7alloy-primitives = "=0.7.6"
8alloy-sol-types = "=0.7.6"
9mini-alloc = "0.4.2"
10stylus-sdk = "0.6.0"
11hex = "0.4.3"
12sha3 = "0.10.8"
13
14[features]
15export-abi = ["stylus-sdk/export-abi"]
16debug = ["stylus-sdk/debug"]
17
18[lib]
19crate-type = ["lib", "cdylib"]
20
21[profile.release]
22codegen-units = 1
23strip = true
24lto = true
25panic = "abort"
26opt-level = "s"