use alloy_primitives::{Address, B256, keccak256};
use alloy_rlp::Encodable;
const FEE_TOKEN_PREFIX_BYTES: [u8; 10] = [0xA1, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
pub fn compute_fee_token_address(creator: Address, salt: B256) -> (Address, u64) {
let mut buf = Vec::new();
creator.encode(&mut buf);
salt.encode(&mut buf);
let hash = keccak256(&buf);
let mut lower_bytes = [0u8; 8];
lower_bytes.copy_from_slice(&hash[..8]);
let lower_u64 = u64::from_be_bytes(lower_bytes);
let mut address_bytes = [0u8; 20];
address_bytes[..10].copy_from_slice(&FEE_TOKEN_PREFIX_BYTES);
address_bytes[10..].copy_from_slice(&hash[..10]);
(Address::from(address_bytes), lower_u64)
}
pub fn is_reserved_address(creator: Address, salt: B256) -> bool {
let (_, index) = compute_fee_token_address(creator, salt);
index < 256
}
pub fn compute_keccak256(data: &[u8]) -> B256 {
keccak256(data)
}
pub fn pad_hex(hex: &str, bytes: usize) -> String {
let clean = hex.trim_start_matches("0x");
let target_len = bytes * 2;
if clean.len() >= target_len {
return format!("0x{}", &clean[..target_len]);
}
let mut result = String::new();
for _ in 0..(target_len - clean.len()) {
result.push('0');
}
result.push_str(clean);
format!("0x{}", result)
}
pub fn num_to_hex(num: u64, bytes: usize) -> String {
let hex_str = format!("{:x}", num);
let target_len = bytes * 2;
if hex_str.len() >= target_len {
return format!("0x{}", &hex_str[..target_len]);
}
let mut result = String::new();
for _ in 0..(target_len - hex_str.len()) {
result.push('0');
}
result.push_str(&hex_str);
format!("0x{}", result)
}
pub fn is_fee_token_prefix(addr: Address) -> bool {
let bytes = addr.as_slice();
bytes.len() >= 2 && bytes[0] == 0xA1 && bytes[1] == 0x70
}
pub fn is_valid_fee_token_address(addr: Address) -> bool {
is_fee_token_prefix(addr) && !addr.is_zero()
}
pub fn is_index_reserved(index: u64) -> bool {
index < 256
}