zksync_web3_rs/eip712/
mod.rs

1use ethers::{
2    types::transaction::eip712::Eip712Error,
3    utils::rlp::{Encodable, RlpStream},
4};
5use sha2::Digest;
6use std::num::TryFromIntError;
7
8mod meta;
9pub use meta::Eip712Meta;
10
11mod transaction_request;
12pub use transaction_request::Eip712TransactionRequest;
13
14mod transaction;
15pub use transaction::Eip712Transaction;
16
17mod paymaster_params;
18pub use paymaster_params::PaymasterParams;
19
20/// The 32-byte hash of the bytecode of a zkSync contract is calculated in the following way:
21///
22/// * The first 2 bytes denote the version of bytecode hash format and are currently equal to [1,0].
23/// * The second 2 bytes denote the length of the bytecode in 32-byte words.
24/// * The rest of the 28-byte (i.e. 28 low big-endian bytes) are equal to the last 28 bytes of the sha256 hash of the contract's bytecode.
25pub fn hash_bytecode(bytecode: &[u8]) -> Result<[u8; 32], Eip712Error> {
26    let step_1: [u8; 2] = 0x0100_u16.to_be_bytes();
27    let bytecode_length: u16 = (bytecode.len() / 32)
28        .try_into()
29        .map_err(|e: TryFromIntError| Eip712Error::Message(e.to_string()))?;
30    let step_2: [u8; 2] = bytecode_length.to_be_bytes();
31    let step_3: [u8; 28] = sha2::Sha256::digest(bytecode)
32        .into_iter()
33        .skip(4)
34        .collect::<Vec<u8>>()
35        .try_into()
36        .map_err(|e| {
37            Eip712Error::Message(format!(
38                "Failed to digest last 28 bytes of bytecode's sha256 hash: {e:?}"
39            ))
40        })?;
41
42    let contract_hash: [u8; 32] = [&step_1, &step_2, &step_3[..]]
43        .concat()
44        .try_into()
45        .map_err(|e| {
46            Eip712Error::Message(format!("Algorithm's steps concatenation failed: {e:?}"))
47        })?;
48
49    Ok(contract_hash)
50}
51
52pub(crate) fn rlp_append_option<T>(stream: &mut RlpStream, value: Option<T>)
53where
54    T: Encodable,
55{
56    if let Some(v) = value {
57        stream.append(&v);
58    } else {
59        stream.append(&"");
60    }
61}