use sha3::{Digest, Keccak256};
use std::convert::TryInto;
use std::{u64, usize};
use alloy_primitives::{Address, U256};
pub fn keccak256<T: AsRef<[u8]>>(v: T) -> [u8; 32] {
let mut hasher = Keccak256::new();
hasher.update(v);
hasher.finalize().as_slice().try_into().expect("Wrong length")
}
pub fn keccak256_concat(a: [u8; 32], b: [u8; 32]) -> [u8; 32] {
let mut hasher = Keccak256::new();
hasher.update(a);
hasher.update(b);
hasher.finalize().as_slice().try_into().expect("Wrong length")
}
pub fn ceil_div(a: usize, b: usize) -> usize {
(a + b - 1) / b
}
pub fn bool_to_bytes32(value: bool) -> [u8; 32] {
let mut bytes = [0u8; 32];
if value {
bytes[31] = 1;
}
bytes
}
pub fn u256_to_bytes32(num: U256) -> [u8; 32] {
num.to_be_bytes()
}
pub fn address_to_bytes32(address: Address) -> [u8; 32] {
let bytes20 = address.as_slice();
let mut bytes32 = [0u8; 32];
bytes32[12..32].copy_from_slice(&bytes20);
bytes32
}
pub fn bytes32_to_u256(bytes: [u8; 32]) -> U256 {
U256::from_be_bytes(bytes)
}
pub fn u256_to_u64(value: U256) -> u64 {
let bytes = value.to_be_bytes::<{ U256::BYTES }>();
if bytes[..24] == [0u8; 24] {
let lower_u64 = u64::from_be_bytes(bytes[24..32].try_into().expect("slice with incorrect length"));
lower_u64
} else {
panic!("Value does not fit in u64")
}
}
pub fn vec_u256_to_vec_bytes(vec_u256: &Vec<U256>, start: usize, end: usize) -> Vec<u8> {
let mut vec_bytes = Vec::with_capacity((end - start) * 32); for u256 in &vec_u256[start..end] {
vec_bytes.extend_from_slice(&u256.to_be_bytes::<{ U256::BYTES }>());
}
vec_bytes
}
pub fn index_to_position(index: usize, packing_ratio_n: usize, packing_ratio_d: usize) -> (U256, usize) {
let slot = index * packing_ratio_n / packing_ratio_d;
let offset = index * 32 * packing_ratio_n / packing_ratio_d % 32;
(U256::from(slot), offset)
}