use sha3::{Digest, Keccak256};
use starknet_types_core::felt::{Felt, NonZeroFelt};
use starknet_types_core::hash::{Pedersen, StarkHash};
use crate::abi::constants;
use crate::core::{ContractAddress, EntryPointSelector, PatriciaKey, L2_ADDRESS_UPPER_BOUND};
use crate::state::StorageKey;
#[cfg(test)]
#[path = "abi_utils_test.rs"]
mod test;
pub fn starknet_keccak(data: &[u8]) -> Felt {
let mut hasher = Keccak256::new();
hasher.update(data);
let mut result: [u8; 32] = hasher.finalize().into();
*result.first_mut().unwrap() &= 3;
Felt::from_bytes_be(&result)
}
pub fn selector_from_name(entry_point_name: &str) -> EntryPointSelector {
static DEFAULT_ENTRY_POINTS: [&str; 2] =
[constants::DEFAULT_ENTRY_POINT_NAME, constants::DEFAULT_L1_ENTRY_POINT_NAME];
if DEFAULT_ENTRY_POINTS.contains(&entry_point_name) {
EntryPointSelector(Felt::from(constants::DEFAULT_ENTRY_POINT_SELECTOR))
} else {
EntryPointSelector(starknet_keccak(entry_point_name.as_bytes()))
}
}
pub fn get_storage_var_address(storage_var_name: &str, args: &[Felt]) -> StorageKey {
let storage_var_name_hash = starknet_keccak(storage_var_name.as_bytes());
let storage_key_hash =
args.iter().fold(storage_var_name_hash, |res, arg| Pedersen::hash(&res, arg));
let storage_key = storage_key_hash
.mod_floor(&NonZeroFelt::from_raw(Felt::from(*L2_ADDRESS_UPPER_BOUND).to_raw()));
StorageKey(
PatriciaKey::try_from(storage_key)
.expect("Should be within bounds as retrieved mod L2_ADDRESS_UPPER_BOUND."),
)
}
pub fn get_fee_token_var_address(contract_address: ContractAddress) -> StorageKey {
get_storage_var_address("ERC20_balances", &[*contract_address.0.key()])
}