use ethers::{
types::transaction::eip712::Eip712Error,
utils::rlp::{Encodable, RlpStream},
};
use sha2::Digest;
use std::num::TryFromIntError;
mod meta;
pub use meta::Eip712Meta;
mod transaction_request;
pub use transaction_request::Eip712TransactionRequest;
mod transaction;
pub use transaction::Eip712Transaction;
mod paymaster_params;
pub use paymaster_params::PaymasterParams;
pub fn hash_bytecode(bytecode: &[u8]) -> Result<[u8; 32], Eip712Error> {
let step_1: [u8; 2] = 0x0100_u16.to_be_bytes();
let bytecode_length: u16 = (bytecode.len() / 32)
.try_into()
.map_err(|e: TryFromIntError| Eip712Error::Message(e.to_string()))?;
let step_2: [u8; 2] = bytecode_length.to_be_bytes();
let step_3: [u8; 28] = sha2::Sha256::digest(bytecode)
.into_iter()
.skip(4)
.collect::<Vec<u8>>()
.try_into()
.map_err(|e| {
Eip712Error::Message(format!(
"Failed to digest last 28 bytes of bytecode's sha256 hash: {e:?}"
))
})?;
let contract_hash: [u8; 32] = [&step_1, &step_2, &step_3[..]]
.concat()
.try_into()
.map_err(|e| {
Eip712Error::Message(format!("Algorithm's steps concatenation failed: {e:?}"))
})?;
Ok(contract_hash)
}
pub(crate) fn rlp_append_option<T>(stream: &mut RlpStream, value: Option<T>)
where
T: Encodable,
{
if let Some(v) = value {
stream.append(&v);
} else {
stream.append(&"");
}
}