From 1691750928ed6e3e6595f25226bac9b990ba8bbf Mon Sep 17 00:00:00 2001 From: enitrat Date: Wed, 11 Sep 2024 15:09:01 +0200 Subject: [PATCH 1/5] feat: remove distinctions between KakarotZero and KakarotSSJ --- .../src/evm_sequencer/account/mod.rs | 134 ++++-- .../src/evm_sequencer/account/v0.rs | 115 ----- .../src/evm_sequencer/account/v1.rs | 114 ----- .../ef-testing/src/evm_sequencer/constants.rs | 5 +- .../src/evm_sequencer/evm_state/mod.rs | 392 +++++++++++++++- .../src/evm_sequencer/evm_state/v0.rs | 372 --------------- .../src/evm_sequencer/evm_state/v1.rs | 424 ------------------ .../src/evm_sequencer/sequencer/mod.rs | 129 +++++- .../src/evm_sequencer/sequencer/v0.rs | 74 --- .../src/evm_sequencer/sequencer/v1.rs | 61 --- crates/ef-testing/src/evm_sequencer/utils.rs | 113 ++--- crates/ef-testing/src/models/case.rs | 16 - 12 files changed, 651 insertions(+), 1298 deletions(-) delete mode 100644 crates/ef-testing/src/evm_sequencer/account/v0.rs delete mode 100644 crates/ef-testing/src/evm_sequencer/account/v1.rs delete mode 100644 crates/ef-testing/src/evm_sequencer/evm_state/v0.rs delete mode 100644 crates/ef-testing/src/evm_sequencer/evm_state/v1.rs delete mode 100644 crates/ef-testing/src/evm_sequencer/sequencer/v0.rs delete mode 100644 crates/ef-testing/src/evm_sequencer/sequencer/v1.rs diff --git a/crates/ef-testing/src/evm_sequencer/account/mod.rs b/crates/ef-testing/src/evm_sequencer/account/mod.rs index fddbd93d..6978d5fd 100644 --- a/crates/ef-testing/src/evm_sequencer/account/mod.rs +++ b/crates/ef-testing/src/evm_sequencer/account/mod.rs @@ -1,11 +1,20 @@ -#[cfg(feature = "v0")] -pub mod v0; -#[cfg(feature = "v1")] -pub mod v1; - use starknet::core::utils::cairo_short_string_to_felt; use starknet_api::{core::Nonce, state::StorageKey}; use starknet_crypto::{poseidon_permute_comp, Felt}; +use blockifier::abi::{abi_utils::get_storage_var_address, sierra_types::next_storage_key}; +use reth_primitives::alloy_primitives::keccak256; +use reth_primitives::KECCAK_EMPTY; +use reth_primitives::{Address, U256}; + +use revm_interpreter::analysis::to_analysed; +use revm_primitives::{Bytecode, Bytes}; +use starknet_api::{StarknetApiError}; +use crate::evm_sequencer::constants::storage_variables::{ + ACCOUNT_BYTECODE_LEN, ACCOUNT_CODE_HASH, ACCOUNT_EVM_ADDRESS, ACCOUNT_IS_INITIALIZED, + ACCOUNT_NONCE, ACCOUNT_STORAGE, ACCOUNT_VALID_JUMPDESTS, +}; +use crate::evm_sequencer::{types::felt::FeltSequencer, utils::split_u256}; +use crate::starknet_storage; #[macro_export] macro_rules! starknet_storage { @@ -59,30 +68,105 @@ pub enum AccountType { Contract = 2, } -#[cfg(not(any(feature = "v0", feature = "v1")))] -pub mod kkrt_account { - use super::KakarotAccount; - use reth_primitives::{Address, Bytes, U256}; - use starknet::core::types::Felt; - use starknet_api::{core::Nonce, StarknetApiError}; - - impl KakarotAccount { - pub fn new( - _evm_address: &Address, - _code: &Bytes, - _nonce: U256, - _balance: U256, - _evm_storage: &[(U256, U256)], - ) -> Result { - Ok(Self { - evm_address: Felt::default(), - nonce: Nonce::default(), - storage: vec![], +impl KakarotAccount { + pub fn new( + evm_address: &Address, + code: &Bytes, + nonce: U256, + balance: U256, + evm_storage: &[(U256, U256)], + ) -> Result { + let nonce = Felt::from(TryInto::::try_into(nonce).map_err(|err| { + StarknetApiError::OutOfRange { + string: err.to_string(), + } + })?); + + let evm_address = TryInto::::try_into(*evm_address) + .unwrap() // infallible + .into(); + + let mut storage = vec![ + starknet_storage!(ACCOUNT_EVM_ADDRESS, evm_address), + starknet_storage!(ACCOUNT_IS_INITIALIZED, 1u8), + starknet_storage!(ACCOUNT_BYTECODE_LEN, code.len() as u32), + ]; + + // Write the nonce of the account is written to storage after each tx. + storage.append(&mut vec![starknet_storage!(ACCOUNT_NONCE, nonce)]); + + // Initialize the bytecode storage var. + let mut bytecode_storage = pack_byte_array_to_starkfelt_array(code) + .enumerate() + .map(|(i, bytes)| (StorageKey::from(i as u32), bytes)) + .collect(); + storage.append(&mut bytecode_storage); + + // Initialize the code hash var + let account_is_empty = + code.is_empty() && nonce == Felt::from(0) && balance == U256::from(0); + let code_hash = if account_is_empty { + U256::from(0) + } else if code.is_empty() { + U256::from_be_slice(KECCAK_EMPTY.as_slice()) + } else { + U256::from_be_slice(keccak256(code).as_slice()) + }; + + let code_hash_values = split_u256(code_hash); + let code_hash_low_key = get_storage_var_address(ACCOUNT_CODE_HASH, &[]); + let code_hash_high_key = next_storage_key(&code_hash_low_key)?; + storage.extend([ + (code_hash_low_key, Felt::from(code_hash_values[0])), + (code_hash_high_key, Felt::from(code_hash_values[1])), + ]); + + // Initialize the bytecode jumpdests. + let bytecode = to_analysed(Bytecode::new_raw(code.clone())); + let valid_jumpdests: Vec = match bytecode { + Bytecode::LegacyAnalyzed(legacy_analyzed_bytecode) => legacy_analyzed_bytecode + .jump_table() + .0 + .iter() + .enumerate() + .filter_map(|(index, bit)| bit.as_ref().then(|| index)) + .collect(), + _ => unreachable!("Bytecode should be analysed"), + }; + + let jumdpests_storage_address = get_storage_var_address(ACCOUNT_VALID_JUMPDESTS, &[]); + let jumdpests_storage_address = Felt::from(jumdpests_storage_address); + valid_jumpdests.into_iter().for_each(|index| { + storage.push(( + (jumdpests_storage_address + Felt::from(index)) + .try_into() + .unwrap(), + Felt::ONE, + )) + }); + + // Initialize the storage vars. + let mut evm_storage_storage: Vec<(StorageKey, Felt)> = evm_storage + .iter() + .flat_map(|(k, v)| { + let keys = split_u256(*k).map(Into::into); + let values = split_u256(*v).map(Into::::into); + let low_key = get_storage_var_address(ACCOUNT_STORAGE, &keys); + let high_key = next_storage_key(&low_key).unwrap(); // can fail only if low is the max key + vec![(low_key, values[0]), (high_key, values[1])] }) - } + .collect(); + storage.append(&mut evm_storage_storage); + + Ok(Self { + storage, + evm_address, + nonce: Nonce(nonce), + }) } } + /// Splits a byte array into 31-byte chunks and converts each chunk to a Felt. pub fn pack_byte_array_to_starkfelt_array(bytes: &[u8]) -> impl Iterator + '_ { bytes.chunks(31).map(Felt::from_bytes_be_slice) diff --git a/crates/ef-testing/src/evm_sequencer/account/v0.rs b/crates/ef-testing/src/evm_sequencer/account/v0.rs deleted file mode 100644 index e66485e0..00000000 --- a/crates/ef-testing/src/evm_sequencer/account/v0.rs +++ /dev/null @@ -1,115 +0,0 @@ -use blockifier::abi::{abi_utils::get_storage_var_address, sierra_types::next_storage_key}; -use reth_primitives::alloy_primitives::keccak256; -use reth_primitives::KECCAK_EMPTY; -use reth_primitives::{Address, U256}; - -use revm_interpreter::analysis::to_analysed; -use revm_primitives::{Bytecode, Bytes}; -use starknet_api::{core::Nonce, state::StorageKey, StarknetApiError}; -use starknet_crypto::Felt; - -use super::{pack_byte_array_to_starkfelt_array, KakarotAccount}; -use crate::evm_sequencer::constants::storage_variables::{ - ACCOUNT_BYTECODE_LEN, ACCOUNT_CODE_HASH, ACCOUNT_EVM_ADDRESS, ACCOUNT_IS_INITIALIZED, - ACCOUNT_NONCE, ACCOUNT_STORAGE, ACCOUNT_VALID_JUMPDESTS, -}; -use crate::evm_sequencer::{types::felt::FeltSequencer, utils::split_u256}; -use crate::starknet_storage; - -impl KakarotAccount { - pub fn new( - evm_address: &Address, - code: &Bytes, - nonce: U256, - balance: U256, - evm_storage: &[(U256, U256)], - ) -> Result { - let nonce = Felt::from(TryInto::::try_into(nonce).map_err(|err| { - StarknetApiError::OutOfRange { - string: err.to_string(), - } - })?); - - let evm_address = TryInto::::try_into(*evm_address) - .unwrap() // infallible - .into(); - - let mut storage = vec![ - starknet_storage!(ACCOUNT_EVM_ADDRESS, evm_address), - starknet_storage!(ACCOUNT_IS_INITIALIZED, 1u8), - starknet_storage!(ACCOUNT_BYTECODE_LEN, code.len() as u32), - ]; - - // Write the nonce of the account is written to storage after each tx. - storage.append(&mut vec![starknet_storage!(ACCOUNT_NONCE, nonce)]); - - // Initialize the bytecode storage var. - let mut bytecode_storage = pack_byte_array_to_starkfelt_array(code) - .enumerate() - .map(|(i, bytes)| (StorageKey::from(i as u32), bytes)) - .collect(); - storage.append(&mut bytecode_storage); - - // Initialize the code hash var - let account_is_empty = - code.is_empty() && nonce == Felt::from(0) && balance == U256::from(0); - let code_hash = if account_is_empty { - U256::from(0) - } else if code.is_empty() { - U256::from_be_slice(KECCAK_EMPTY.as_slice()) - } else { - U256::from_be_slice(keccak256(code).as_slice()) - }; - - let code_hash_values = split_u256(code_hash); - let code_hash_low_key = get_storage_var_address(ACCOUNT_CODE_HASH, &[]); - let code_hash_high_key = next_storage_key(&code_hash_low_key)?; - storage.extend([ - (code_hash_low_key, Felt::from(code_hash_values[0])), - (code_hash_high_key, Felt::from(code_hash_values[1])), - ]); - - // Initialize the bytecode jumpdests. - let bytecode = to_analysed(Bytecode::new_raw(code.clone())); - let valid_jumpdests: Vec = match bytecode { - Bytecode::LegacyAnalyzed(legacy_analyzed_bytecode) => legacy_analyzed_bytecode - .jump_table() - .0 - .iter() - .enumerate() - .filter_map(|(index, bit)| bit.as_ref().then(|| index)) - .collect(), - _ => unreachable!("Bytecode should be analysed"), - }; - - let jumdpests_storage_address = get_storage_var_address(ACCOUNT_VALID_JUMPDESTS, &[]); - let jumdpests_storage_address = Felt::from(jumdpests_storage_address); - valid_jumpdests.into_iter().for_each(|index| { - storage.push(( - (jumdpests_storage_address + Felt::from(index)) - .try_into() - .unwrap(), - Felt::ONE, - )) - }); - - // Initialize the storage vars. - let mut evm_storage_storage: Vec<(StorageKey, Felt)> = evm_storage - .iter() - .flat_map(|(k, v)| { - let keys = split_u256(*k).map(Into::into); - let values = split_u256(*v).map(Into::::into); - let low_key = get_storage_var_address(ACCOUNT_STORAGE, &keys); - let high_key = next_storage_key(&low_key).unwrap(); // can fail only if low is the max key - vec![(low_key, values[0]), (high_key, values[1])] - }) - .collect(); - storage.append(&mut evm_storage_storage); - - Ok(Self { - storage, - evm_address, - nonce: Nonce(nonce), - }) - } -} diff --git a/crates/ef-testing/src/evm_sequencer/account/v1.rs b/crates/ef-testing/src/evm_sequencer/account/v1.rs deleted file mode 100644 index 2a2dad65..00000000 --- a/crates/ef-testing/src/evm_sequencer/account/v1.rs +++ /dev/null @@ -1,114 +0,0 @@ -use blockifier::abi::abi_utils::get_storage_var_address; -use blockifier::abi::sierra_types::next_storage_key; -use reth_primitives::{keccak256, Address, Bytes, KECCAK_EMPTY, U256}; -use revm_interpreter::analysis::to_analysed; -use revm_primitives::Bytecode; -use starknet::core::types::Felt; -use starknet_api::{core::Nonce, state::StorageKey, StarknetApiError}; - -use super::pack_byte_array_to_starkfelt_array; -use super::KakarotAccount; -use crate::evm_sequencer::constants::storage_variables::{ - ACCOUNT_BYTECODE_LEN, ACCOUNT_CODE_HASH, ACCOUNT_EVM_ADDRESS, ACCOUNT_IS_INITIALIZED, - ACCOUNT_NONCE, ACCOUNT_STORAGE, ACCOUNT_VALID_JUMPDESTS, -}; -use crate::evm_sequencer::{types::felt::FeltSequencer, utils::split_u256}; -use crate::starknet_storage; - -impl KakarotAccount { - pub fn new( - evm_address: &Address, - code: &Bytes, - nonce: U256, - balance: U256, - evm_storage: &[(U256, U256)], - ) -> Result { - let nonce = Felt::from(TryInto::::try_into(nonce).map_err(|err| { - StarknetApiError::OutOfRange { - string: err.to_string(), - } - })?); - - let evm_address = TryInto::::try_into(*evm_address) - .unwrap() // infallible - .into(); - - let mut storage = vec![ - starknet_storage!(ACCOUNT_EVM_ADDRESS, evm_address), - starknet_storage!(ACCOUNT_IS_INITIALIZED, 1u8), - starknet_storage!(ACCOUNT_BYTECODE_LEN, code.len() as u32), - ]; - - // Write the nonce of the account is written to storage after each tx. - storage.append(&mut vec![starknet_storage!(ACCOUNT_NONCE, nonce)]); - - // Initialize the bytecode storage var. - let mut bytecode_storage = pack_byte_array_to_starkfelt_array(code) - .enumerate() - .map(|(i, bytes)| (StorageKey::from(i as u32), bytes)) - .collect(); - storage.append(&mut bytecode_storage); - - // Initialize the code hash var - let account_is_empty = - code.is_empty() && nonce == Felt::from(0) && balance == U256::from(0); - let code_hash = if account_is_empty { - U256::from(0) - } else if code.is_empty() { - U256::from_be_slice(KECCAK_EMPTY.as_slice()) - } else { - U256::from_be_slice(keccak256(code).as_slice()) - }; - - let code_hash_values = split_u256(code_hash); - let code_hash_low_key = get_storage_var_address(ACCOUNT_CODE_HASH, &[]); - let code_hash_high_key = next_storage_key(&code_hash_low_key)?; - storage.extend([ - (code_hash_low_key, Felt::from(code_hash_values[0])), - (code_hash_high_key, Felt::from(code_hash_values[1])), - ]); - - // Initialize the bytecode jumpdests. - let bytecode = to_analysed(Bytecode::new_raw(code.clone())); - let valid_jumpdests: Vec = match bytecode { - Bytecode::LegacyAnalyzed(legacy_analyzed_bytecode) => legacy_analyzed_bytecode - .jump_table() - .0 - .iter() - .enumerate() - .filter_map(|(index, bit)| bit.as_ref().then(|| index)) - .collect(), - _ => unreachable!("Bytecode should be analysed"), - }; - - let jumdpests_storage_address = get_storage_var_address(ACCOUNT_VALID_JUMPDESTS, &[]); - let jumdpests_storage_address = Felt::from(jumdpests_storage_address); - valid_jumpdests.into_iter().for_each(|index| { - storage.push(( - (jumdpests_storage_address + Felt::from(index)) - .try_into() - .unwrap(), - Felt::ONE, - )) - }); - - // Initialize the storage vars. - let mut evm_storage_storage: Vec<(StorageKey, Felt)> = evm_storage - .iter() - .flat_map(|(k, v)| { - let keys = split_u256(*k).map(Into::into); - let values = split_u256(*v).map(Into::::into); - let low_key = get_storage_var_address(ACCOUNT_STORAGE, &keys); - let high_key = next_storage_key(&low_key).unwrap(); // can fail only if low is the max key - vec![(low_key, values[0]), (high_key, values[1])] - }) - .collect(); - storage.append(&mut evm_storage_storage); - - Ok(Self { - storage, - evm_address, - nonce: Nonce(nonce), - }) - } -} diff --git a/crates/ef-testing/src/evm_sequencer/constants.rs b/crates/ef-testing/src/evm_sequencer/constants.rs index 823e8d1c..ad7ea038 100644 --- a/crates/ef-testing/src/evm_sequencer/constants.rs +++ b/crates/ef-testing/src/evm_sequencer/constants.rs @@ -60,6 +60,9 @@ lazy_static! { pub static ref CAIRO1_HELPERS_CLASS: CompiledClass = load_contract_class("../../build/common/cairo1_helpers.json").expect("Failed to load precompiles contract class"); pub static ref CAIRO1_HELPERS_CLASS_HASH: ClassHash = ClassHash(CAIRO1_HELPERS_CLASS.class_hash().unwrap()); + pub static ref OPENZEPPELIN_ACCOUNT_CLASS_HASH: ClassHash = ClassHash(OPENZEPPELIN_ACCOUNT_CLASS.class_hash().unwrap()); + pub static ref OPENZEPPELIN_ACCOUNT_CLASS: LegacyContractClass = load_contract_class("../../build/v0/OpenzeppelinAccount.json").expect("Failed to load openzeppelin account contract class"); + pub static ref RELAYER_SIGNING_KEY: SigningKey = SigningKey::from_random(); pub static ref RELAYER_VERIFYING_KEY: VerifyingKey = RELAYER_SIGNING_KEY.verifying_key(); pub static ref RELAYER_BALANCE: Felt = Felt::from(1_000_000_000_000_000_000_000_000u128); @@ -72,13 +75,11 @@ lazy_static! { pub static ref KAKAROT_CLASS: LegacyContractClass = load_contract_class("../../build/v0/kakarot.json").expect("Failed to load Kakarot contract class"); pub static ref ACCOUNT_CONTRACT_CLASS: LegacyContractClass = load_contract_class("../../build/v0/account_contract.json").expect("Failed to load ContractAccount contract class"); pub static ref UNINITIALIZED_ACCOUNT_CLASS: LegacyContractClass = load_contract_class("../../build/v0/uninitialized_account.json").expect("Failed to load uninitialized account c contract class"); - pub static ref OPENZEPPELIN_ACCOUNT_CLASS: LegacyContractClass = load_contract_class("../../build/v0/OpenzeppelinAccount.json").expect("Failed to load openzeppelin account contract class"); // Main class hashes pub static ref KAKAROT_CLASS_HASH: ClassHash = ClassHash(KAKAROT_CLASS.class_hash().unwrap()); pub static ref ACCOUNT_CONTRACT_CLASS_HASH: ClassHash = ClassHash(ACCOUNT_CONTRACT_CLASS.class_hash().unwrap()); pub static ref UNINITIALIZED_ACCOUNT_CLASS_HASH: ClassHash = ClassHash(UNINITIALIZED_ACCOUNT_CLASS.class_hash().unwrap()); - pub static ref OPENZEPPELIN_ACCOUNT_CLASS_HASH: ClassHash = ClassHash(OPENZEPPELIN_ACCOUNT_CLASS.class_hash().unwrap()); } #[cfg(feature = "v1")] diff --git a/crates/ef-testing/src/evm_sequencer/evm_state/mod.rs b/crates/ef-testing/src/evm_sequencer/evm_state/mod.rs index e211c0cc..642dc4fd 100644 --- a/crates/ef-testing/src/evm_sequencer/evm_state/mod.rs +++ b/crates/ef-testing/src/evm_sequencer/evm_state/mod.rs @@ -1,15 +1,41 @@ -#[cfg(feature = "v0")] -pub mod v0; -#[cfg(feature = "v1")] -pub mod v1; - use blockifier::{ - state::state_api::StateResult, - transaction::objects::{TransactionExecutionInfo, TransactionExecutionResult}, + abi::{ + abi_utils::{get_fee_token_var_address, get_storage_var_address}, + sierra_types::next_storage_key, + }, + execution::errors::EntryPointExecutionError, + state::state_api::{State as _, StateReader as _, StateResult}, + transaction::{ + errors::TransactionExecutionError, + objects::{TransactionExecutionInfo, TransactionExecutionResult}, + }, }; use reth_primitives::{Address, Bytes, TransactionSigned, U256}; +use sequencer::{execution::Execution as _, transaction::BroadcastedTransactionWrapper}; +use starknet::core::types::BroadcastedTransaction; +use starknet_api::state::StorageKey; +use starknet_crypto::Felt; +use crate::evm_sequencer::constants::storage_variables::ACCOUNT_BYTECODE_LEN; +use crate::evm_sequencer::utils::felt_to_bytes; +use crate::{ + evm_sequencer::{ + account::KakarotAccount, + constants::{ + storage_variables::{ + ACCOUNT_IMPLEMENTATION, ACCOUNT_NONCE, ACCOUNT_STORAGE, KAKAROT_BASE_FEE, + KAKAROT_BLOCK_GAS_LIMIT, KAKAROT_COINBASE, KAKAROT_EVM_TO_STARKNET_ADDRESS, + KAKAROT_PREV_RANDAO, OWNABLE_OWNER, + }, + ETH_FEE_TOKEN_ADDRESS, KAKAROT_ADDRESS, + }, + sequencer::KakarotSequencer, + types::felt::FeltSequencer, + utils::{split_u256, to_broadcasted_starknet_transaction}, + }, + starknet_storage, +}; +use crate::evm_sequencer::constants::RELAYER_ADDRESS; -use super::account::KakarotAccount; /// EVM state interface. Used to setup the evm state, EOA and contract accounts, /// fund them and get their state (balance, nonce, code, storage). @@ -58,5 +84,351 @@ pub trait Evm { } } -#[cfg(not(any(feature = "v0", feature = "v1")))] -impl Evm for super::sequencer::KakarotSequencer {} +impl Evm for KakarotSequencer { + /// Sets up the evm state (coinbase, block number, etc.) + fn setup_state( + &mut self, + base_fee: U256, + prev_randao: U256, + block_gas_limit: U256, + ) -> StateResult<()> { + let kakarot_address = self.environment.kakarot_address; + let coinbase_address: FeltSequencer = (*self.address()).try_into().unwrap(); // infallible + + // Set the coinbase address. + self.state_mut().set_storage_at( + kakarot_address, + get_storage_var_address(KAKAROT_COINBASE, &[]), + coinbase_address.into(), + )?; + + // Set the base fee. + let [low_fee, high_fee] = split_u256(base_fee); + let basefee_address = get_storage_var_address(KAKAROT_BASE_FEE, &[]); + self.state_mut() + .set_storage_at(kakarot_address, basefee_address, low_fee.into())?; + self.state_mut().set_storage_at( + kakarot_address, + next_storage_key(&basefee_address)?, + high_fee.into(), + )?; + + // Set the previous randao. + let [low_prev_randao, high_prev_randao] = split_u256(prev_randao); + let prev_randao_address = get_storage_var_address(KAKAROT_PREV_RANDAO, &[]); + self.state_mut().set_storage_at( + kakarot_address, + prev_randao_address, + low_prev_randao.into(), + )?; + self.state_mut().set_storage_at( + kakarot_address, + next_storage_key(&prev_randao_address)?, + high_prev_randao.into(), + )?; + + // Set the block gas limit, considering it fits in a felt. + let [block_gas_limit, _] = split_u256(block_gas_limit); + let block_gas_limit_address = get_storage_var_address(KAKAROT_BLOCK_GAS_LIMIT, &[]); + self.state_mut().set_storage_at( + kakarot_address, + block_gas_limit_address, + block_gas_limit.into(), + )?; + + Ok(()) + } + + /// Sets up an EOA or contract account. Writes nonce, code and storage to the sequencer storage. + fn setup_account(&mut self, account: KakarotAccount) -> StateResult<()> { + let evm_address = &account.evm_address().to_bytes_be()[12..]; + let evm_address = Address::from_slice(evm_address); + let mut storage = account.storage; + let starknet_address = self.compute_starknet_address(&evm_address)?; + + self.state_mut().set_nonce(starknet_address, account.nonce); + + storage.append(&mut vec![ + starknet_storage!( + ACCOUNT_IMPLEMENTATION, + self.environment.account_contract_class_hash.0 + ), + starknet_storage!(OWNABLE_OWNER, *self.environment.kakarot_address.0.key()), + ]); + + // Write all the storage vars to the sequencer state. + for (k, v) in storage { + self.state_mut().set_storage_at(starknet_address, k, v)?; + } + + let class_hash = self.environment.account_contract_class_hash; + // Set up the contract class hash + self.state_mut() + .set_class_hash_at(starknet_address, class_hash)?; + + // Add the address to the Kakarot evm to starknet mapping + let kakarot_address = self.environment.kakarot_address; + self.state_mut().set_storage_at( + kakarot_address, + get_storage_var_address(KAKAROT_EVM_TO_STARKNET_ADDRESS, &[account.evm_address]), + *starknet_address.0.key(), + )?; + Ok(()) + } + + /// Funds an EOA or contract account. Also gives allowance to the Kakarot contract. + fn fund(&mut self, evm_address: &Address, balance: U256) -> StateResult<()> { + let starknet_address = self.compute_starknet_address(evm_address)?; + let balance_values = split_u256(balance); + let mut storage = vec![]; + + // Initialize the balance storage var. + let balance_key_low = get_fee_token_var_address(starknet_address); + let balance_key_high = next_storage_key(&balance_key_low)?; + storage.append(&mut vec![ + (balance_key_low, balance_values[0].into()), + (balance_key_high, balance_values[1].into()), + ]); + + // Initialize the allowance storage var. + let allowance_key_low = get_storage_var_address( + "ERC20_allowances", + &[*starknet_address.0.key(), *KAKAROT_ADDRESS.0.key()], + ); + let allowance_key_high = next_storage_key(&allowance_key_low)?; + storage.append(&mut vec![ + (allowance_key_low, u128::MAX.into()), + (allowance_key_high, u128::MAX.into()), + ]); + + // Write all the storage vars to the sequencer state. + for (k, v) in storage { + self.state_mut() + .set_storage_at(*ETH_FEE_TOKEN_ADDRESS, k, v)?; + } + Ok(()) + } + + /// Returns the storage value at the given key evm storage key. + fn storage_at(&mut self, evm_address: &Address, key: U256) -> StateResult { + let keys = split_u256(key).map(Into::into); + let key_low = get_storage_var_address(ACCOUNT_STORAGE, &keys); + let key_high = next_storage_key(&key_low)?; + + let starknet_address = self.compute_starknet_address(evm_address)?; + + let low = self.state_mut().get_storage_at(starknet_address, key_low)?; + let high = self + .state_mut() + .get_storage_at(starknet_address, key_high)?; + + let low = U256::from_be_bytes(low.to_bytes_be()); + let high = U256::from_be_bytes(high.to_bytes_be()); + + Ok(high << 128 | low) + } + + /// Returns the nonce of the given address. + /// Uses the Kakarot managed nonce stored in the contract account's storage. + fn nonce_at(&mut self, evm_address: &Address) -> StateResult { + let starknet_address = self.compute_starknet_address(evm_address)?; + + let key = get_storage_var_address(ACCOUNT_NONCE, &[]); + let nonce = self.state_mut().get_storage_at(starknet_address, key)?; + + Ok(U256::from_be_bytes(nonce.to_bytes_be())) + } + + /// Returns the bytecode of the given address. For an EOA, the bytecode_len_ storage variable will return 0, + /// and the function will return an empty vector. For a contract account, the function will return the bytecode + /// stored in the contract_account_bytecode storage variables. The function assumes that the bytecode is stored + /// in 31 byte big-endian chunks. + fn code_at(&mut self, evm_address: &Address) -> StateResult { + // Get all storage addresses. + let starknet_address = self.compute_starknet_address(evm_address)?; + + let bytecode_len = self.state_mut().get_storage_at( + starknet_address, + get_storage_var_address(ACCOUNT_BYTECODE_LEN, &[]), + )?; + let bytecode_len: u64 = bytecode_len.to_biguint().try_into()?; + + if bytecode_len == 0 { + return Ok(Bytes::default()); + } + + // Assumes that the bytecode is stored in 31 byte chunks. + let num_chunks = bytecode_len / 31; + let mut bytecode: Vec = Vec::with_capacity(bytecode_len as usize); + + for chunk_index in 0..num_chunks { + let key = StorageKey::from(chunk_index); + let code = self.state_mut().get_storage_at(starknet_address, key)?; + bytecode.append(&mut felt_to_bytes(&code, 1).to_vec()); + } + + let remainder = bytecode_len % 31; + let key = StorageKey::from(num_chunks); + let code = self.state_mut().get_storage_at(starknet_address, key)?; + bytecode.append(&mut felt_to_bytes(&code, (32 - remainder) as usize).to_vec()); + + Ok(Bytes::from(bytecode)) + } + + /// Returns the balance of native tokens at the given address. + /// Makes use of the default StateReader implementation from Blockifier. + fn balance_at(&mut self, evm_address: &Address) -> StateResult { + let starknet_address = self.compute_starknet_address(evm_address)?; + let (low, high) = self + .state_mut() + .get_fee_token_balance(starknet_address, *ETH_FEE_TOKEN_ADDRESS)?; + + let low = U256::from_be_bytes(low.to_bytes_be()); + let high = U256::from_be_bytes(high.to_bytes_be()); + + Ok(high << 128 | low) + } + + /// Converts the given signed transaction to a Starknet-rs transaction and executes it. + // Since we are still missing the validate for the EOA, the signature is not added + // to the transaction. + fn execute_transaction( + &mut self, + transaction: TransactionSigned, + ) -> TransactionExecutionResult { + let evm_address = transaction.recover_signer().ok_or_else(|| { + TransactionExecutionError::ValidateTransactionError { + error: EntryPointExecutionError::InvalidExecutionInput { + input_descriptor: String::from("Signed transaction"), + info: "Missing signer in signed transaction".to_string(), + }, + class_hash: Default::default(), + storage_address: Default::default(), + selector: Default::default(), + } + })?; + let starknet_address = self.compute_starknet_address(&evm_address)?; + let relayer_nonce = self.state_mut().get_nonce_at(*RELAYER_ADDRESS).unwrap(); + + let starknet_transaction = + BroadcastedTransactionWrapper::new(BroadcastedTransaction::Invoke( + to_broadcasted_starknet_transaction( + &transaction, + Felt::from(starknet_address), + relayer_nonce.0.into(), + ) + .map_err(|err| { + TransactionExecutionError::ValidateTransactionError { + error: EntryPointExecutionError::InvalidExecutionInput { + input_descriptor: String::from("Failed to convert transaction"), + info: err.to_string(), + }, + class_hash: Default::default(), + storage_address: Default::default(), + selector: Default::default(), + } + })?, + )); + + let chain_id = self.chain_id(); + self.execute( + starknet_transaction + .try_into_execution_transaction(Felt::from(chain_id)) + .unwrap(), + ) + } +} + + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + evm_sequencer::{ + constants::{ + tests::{PRIVATE_KEY, PUBLIC_KEY, TEST_CONTRACT_ADDRESS}, + ACCOUNT_CONTRACT_CLASS_HASH, CAIRO1_HELPERS_CLASS_HASH, CHAIN_ID, KAKAROT_ADDRESS, + UNINITIALIZED_ACCOUNT_CLASS_HASH, + }, + sequencer::{INITIAL_SEQUENCER_STATE, KakarotEnvironment}, + }, + models::result::extract_output_and_log_execution_result, + }; + use reth_primitives::{ + sign_message, AccessList, Signature, TransactionSigned, TxEip1559, B256, + }; + + #[test] + fn test_execute_simple_contract() { + // Given + let kakarot_environment = KakarotEnvironment::new( + *KAKAROT_ADDRESS, + *UNINITIALIZED_ACCOUNT_CLASS_HASH, + *CAIRO1_HELPERS_CLASS_HASH, + *ACCOUNT_CONTRACT_CLASS_HASH, + ); + let coinbase_address = Address::left_padding_from(&0xC01BA5Eu64.to_be_bytes()); + let mut sequencer = KakarotSequencer::new( + INITIAL_SEQUENCER_STATE.clone(), + kakarot_environment, + coinbase_address, + CHAIN_ID, + 0, + 1, + ); + + let mut transaction = TransactionSigned { + hash: B256::default(), + signature: Signature::default(), + transaction: reth_primitives::Transaction::Eip1559(TxEip1559 { + chain_id: CHAIN_ID, + nonce: 0, + gas_limit: 1_000_000, + max_fee_per_gas: 0, + max_priority_fee_per_gas: 0, + to: reth_primitives::TxKind::Call(*TEST_CONTRACT_ADDRESS), + value: U256::ZERO, + access_list: AccessList::default(), + input: Bytes::default(), + }), + }; + let signature = + sign_message(*PRIVATE_KEY, transaction.transaction.signature_hash()).unwrap(); + transaction.signature = signature; + let eoa_nonce = U256::from(0); + let contract_bytecode = Bytes::from(vec![96, 1, 96, 0, 85]); // PUSH 01 PUSH 00 SSTORE + let contract_nonce = U256::from(1); + + // When + let contract = KakarotAccount::new( + &TEST_CONTRACT_ADDRESS, + &contract_bytecode, + contract_nonce, + U256::ZERO, + &[], + ) + .unwrap(); + let eoa = KakarotAccount::new(&PUBLIC_KEY, &Bytes::default(), eoa_nonce, U256::ZERO, &[]) + .unwrap(); + sequencer.setup_account(contract).unwrap(); + sequencer.setup_account(eoa).unwrap(); + let execution_result = sequencer.execute_transaction(transaction); + + // Update the output with the execution result of the current transaction + let tx_output = extract_output_and_log_execution_result( + &execution_result, + "test_case", + "test_category", + ) + .unwrap_or_default(); + + assert!(tx_output.success); + + // Then + let storage = sequencer + .storage_at(&TEST_CONTRACT_ADDRESS, U256::ZERO) + .unwrap(); + + assert_eq!(storage, U256::from(1_u64)); + } +} diff --git a/crates/ef-testing/src/evm_sequencer/evm_state/v0.rs b/crates/ef-testing/src/evm_sequencer/evm_state/v0.rs deleted file mode 100644 index 3f965974..00000000 --- a/crates/ef-testing/src/evm_sequencer/evm_state/v0.rs +++ /dev/null @@ -1,372 +0,0 @@ -use blockifier::abi::abi_utils::{get_fee_token_var_address, get_storage_var_address}; -use blockifier::abi::sierra_types::next_storage_key; -use blockifier::execution::errors::EntryPointExecutionError; -use blockifier::state::state_api::{State, StateReader, StateResult}; -use blockifier::transaction::errors::TransactionExecutionError; -use blockifier::transaction::objects::{TransactionExecutionInfo, TransactionExecutionResult}; -use reth_primitives::{Address, Bytes, TransactionSigned, U256}; -use sequencer::execution::Execution as _; -use sequencer::transaction::BroadcastedTransactionWrapper; -use starknet::core::types::{BroadcastedTransaction, Felt}; -use starknet_api::state::StorageKey; - -use super::Evm; -use crate::evm_sequencer::account::KakarotAccount; -use crate::evm_sequencer::constants::storage_variables::{ - ACCOUNT_BYTECODE_LEN, ACCOUNT_IMPLEMENTATION, ACCOUNT_NONCE, ACCOUNT_STORAGE, KAKAROT_BASE_FEE, - KAKAROT_BLOCK_GAS_LIMIT, KAKAROT_COINBASE, KAKAROT_EVM_TO_STARKNET_ADDRESS, - KAKAROT_PREV_RANDAO, OWNABLE_OWNER, -}; -use crate::evm_sequencer::constants::{ETH_FEE_TOKEN_ADDRESS, RELAYER_ADDRESS}; -use crate::evm_sequencer::sequencer::KakarotSequencer; -use crate::evm_sequencer::types::felt::FeltSequencer; -use crate::evm_sequencer::utils::{felt_to_bytes, split_u256, to_broadcasted_starknet_transaction}; -use crate::starknet_storage; - -impl Evm for KakarotSequencer { - /// Sets up the evm state (coinbase, block number, etc.) - fn setup_state( - &mut self, - base_fee: U256, - prev_randao: U256, - block_gas_limit: U256, - ) -> StateResult<()> { - let kakarot_address = self.environment.kakarot_address; - let coinbase_address: FeltSequencer = (*self.address()).try_into().unwrap(); // infallible - - // Set the coinbase address. - self.state_mut().set_storage_at( - kakarot_address, - get_storage_var_address(KAKAROT_COINBASE, &[]), - coinbase_address.into(), - )?; - - // Set the base fee. - let [low_fee, high_fee] = split_u256(base_fee); - let basefee_address = get_storage_var_address(KAKAROT_BASE_FEE, &[]); - self.state_mut() - .set_storage_at(kakarot_address, basefee_address, low_fee.into())?; - self.state_mut().set_storage_at( - kakarot_address, - next_storage_key(&basefee_address)?, - high_fee.into(), - )?; - - // Set the previous randao. - let [low_prev_randao, high_prev_randao] = split_u256(prev_randao); - let prev_randao_address = get_storage_var_address(KAKAROT_PREV_RANDAO, &[]); - self.state_mut().set_storage_at( - kakarot_address, - prev_randao_address, - low_prev_randao.into(), - )?; - self.state_mut().set_storage_at( - kakarot_address, - next_storage_key(&prev_randao_address)?, - high_prev_randao.into(), - )?; - - // Set the block gas limit, considering it fits in a felt. - let [block_gas_limit, _] = split_u256(block_gas_limit); - let block_gas_limit_address = get_storage_var_address(KAKAROT_BLOCK_GAS_LIMIT, &[]); - self.state_mut().set_storage_at( - kakarot_address, - block_gas_limit_address, - block_gas_limit.into(), - )?; - - Ok(()) - } - - /// Sets up an EOA or contract account. Writes nonce, code and storage to the sequencer storage. - /// Uses the KakarotSequencer environment to set the class hash, contract owner and Kakarot address. - fn setup_account(&mut self, account: KakarotAccount) -> StateResult<()> { - let evm_address = &account.evm_address().to_bytes_be()[12..]; - let evm_address = Address::from_slice(evm_address); - let mut storage = account.storage; - let starknet_address = self.compute_starknet_address(&evm_address)?; - - self.state_mut().set_nonce(starknet_address, account.nonce); - - storage.append(&mut vec![ - starknet_storage!( - ACCOUNT_IMPLEMENTATION, - self.environment.account_contract_class_hash.0 - ), - starknet_storage!(OWNABLE_OWNER, *self.environment.kakarot_address.0.key()), - ]); - - // Write all the storage vars to the sequencer state. - for (k, v) in storage { - self.state_mut().set_storage_at(starknet_address, k, v)?; - } - - let class_hash = self.environment.account_contract_class_hash; - // Set up the contract class hash - self.state_mut() - .set_class_hash_at(starknet_address, class_hash)?; - - // Add the address to the Kakarot evm to starknet mapping - let kakarot_address = self.environment.kakarot_address; - self.state_mut().set_storage_at( - kakarot_address, - get_storage_var_address(KAKAROT_EVM_TO_STARKNET_ADDRESS, &[account.evm_address]), - *starknet_address.0.key(), - )?; - Ok(()) - } - - /// Funds an EOA or contract account. Also gives allowance to the Kakarot contract. - fn fund(&mut self, evm_address: &Address, balance: U256) -> StateResult<()> { - let starknet_address = self.compute_starknet_address(evm_address)?; - let balance_values = split_u256(balance); - let mut storage = vec![]; - - // Initialize the balance storage var. - let balance_low_key = get_fee_token_var_address(starknet_address); - let balance_high_key = next_storage_key(&balance_low_key)?; - storage.append(&mut vec![ - (balance_low_key, balance_values[0].into()), - (balance_high_key, balance_values[1].into()), - ]); - - // Initialize the allowance storage var. - let allowance_key_low = get_storage_var_address( - "ERC20_allowances", - &[ - *starknet_address.0.key(), - *self.environment.kakarot_address.0.key(), - ], - ); - let allowance_key_high = next_storage_key(&allowance_key_low)?; - storage.append(&mut vec![ - (allowance_key_low, u128::MAX.into()), - (allowance_key_high, u128::MAX.into()), - ]); - - // Write all the storage vars to the sequencer state. - for (k, v) in storage { - self.state_mut() - .set_storage_at(*ETH_FEE_TOKEN_ADDRESS, k, v)?; - } - Ok(()) - } - - /// Returns the storage value at the given key evm storage key. - fn storage_at(&mut self, evm_address: &Address, key: U256) -> StateResult { - let keys = split_u256(key).map(Into::into); - let key_low = get_storage_var_address(ACCOUNT_STORAGE, &keys); - let key_high = next_storage_key(&key_low)?; - - let starknet_address = self.compute_starknet_address(evm_address)?; - - let low = self.state_mut().get_storage_at(starknet_address, key_low)?; - let high = self - .state_mut() - .get_storage_at(starknet_address, key_high)?; - - let low = U256::from_be_bytes(low.to_bytes_be()); - let high = U256::from_be_bytes(high.to_bytes_be()); - - Ok(high << 128 | low) - } - - /// Returns the nonce of the given address. - fn nonce_at(&mut self, evm_address: &Address) -> StateResult { - let starknet_address = self.compute_starknet_address(evm_address)?; - - let key = get_storage_var_address(ACCOUNT_NONCE, &[]); - let nonce = self.state_mut().get_storage_at(starknet_address, key)?; - - Ok(U256::from_be_bytes(nonce.to_bytes_be())) - } - - /// Returns the bytecode of the given address. For an EOA, the bytecode_len_ storage variable will return 0, - /// and the function will return an empty vector. For a contract account, the function will return the bytecode - /// stored in the bytecode_ storage variables. The function assumes that the bytecode is stored in 31 byte big-endian chunks. - fn code_at(&mut self, evm_address: &Address) -> StateResult { - let starknet_address = self.compute_starknet_address(evm_address)?; - - let bytecode_len = self.state_mut().get_storage_at( - starknet_address, - get_storage_var_address(ACCOUNT_BYTECODE_LEN, &[]), - )?; - - let bytecode_len: u64 = bytecode_len.to_biguint().try_into()?; - - if bytecode_len == 0 { - return Ok(Bytes::default()); - } - - // Assumes that the bytecode is stored in 31 byte chunks. - let num_chunks = bytecode_len / 31; - let mut bytecode: Vec = Vec::with_capacity(bytecode_len as usize); - - for chunk_index in 0..num_chunks { - let key = StorageKey::from(chunk_index); - let code = self.state_mut().get_storage_at(starknet_address, key)?; - bytecode.append(&mut felt_to_bytes(&code, 1).to_vec()); - } - - let remainder = bytecode_len % 31; - let key = StorageKey::from(num_chunks); - let code = self.state_mut().get_storage_at(starknet_address, key)?; - bytecode.append(&mut felt_to_bytes(&code, (32 - remainder) as usize).to_vec()); - - Ok(Bytes::from(bytecode)) - } - - /// Returns the balance of native tokens at the given address. - /// Makes use of the default StateReader implementation from Blockifier. - fn balance_at(&mut self, evm_address: &Address) -> StateResult { - let starknet_address = self.compute_starknet_address(evm_address)?; - let (low, high) = self - .state_mut() - .get_fee_token_balance(starknet_address, *ETH_FEE_TOKEN_ADDRESS)?; - - let low = U256::from_be_bytes(low.to_bytes_be()); - let high = U256::from_be_bytes(high.to_bytes_be()); - - Ok(high << 128 | low) - } - - /// Converts the given signed transaction to a Starknet-rs transaction and executes it. - fn execute_transaction( - &mut self, - transaction: TransactionSigned, - ) -> TransactionExecutionResult { - let evm_address = transaction.recover_signer().ok_or_else(|| { - TransactionExecutionError::ValidateTransactionError { - error: EntryPointExecutionError::InvalidExecutionInput { - input_descriptor: String::from("Signed transaction"), - info: "Missing signer in signed transaction".to_string(), - }, - class_hash: Default::default(), - storage_address: Default::default(), - selector: Default::default(), - } - })?; - let starknet_address = self.compute_starknet_address(&evm_address)?; - let relayer_nonce = self.state_mut().get_nonce_at(*RELAYER_ADDRESS).unwrap(); - - let starknet_transaction = - BroadcastedTransactionWrapper::new(BroadcastedTransaction::Invoke( - to_broadcasted_starknet_transaction( - &transaction, - Felt::from(starknet_address), - relayer_nonce.0.into(), - ) - .map_err(|err| { - TransactionExecutionError::ValidateTransactionError { - error: EntryPointExecutionError::InvalidExecutionInput { - input_descriptor: String::from("Signed transaction"), - info: err.to_string(), - }, - class_hash: Default::default(), - storage_address: Default::default(), - selector: Default::default(), - } - })?, - )); - - let chain_id = self.chain_id(); - self.execute( - starknet_transaction - .try_into_execution_transaction(Felt::from(chain_id)) - .unwrap(), - ) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - evm_sequencer::{ - constants::{ - tests::{PRIVATE_KEY, PUBLIC_KEY, TEST_CONTRACT_ADDRESS}, - ACCOUNT_CONTRACT_CLASS_HASH, CAIRO1_HELPERS_CLASS_HASH, CHAIN_ID, KAKAROT_ADDRESS, - UNINITIALIZED_ACCOUNT_CLASS_HASH, - }, - sequencer::{v0::INITIAL_SEQUENCER_STATE, KakarotEnvironment}, - }, - models::result::extract_output_and_log_execution_result, - }; - use reth_primitives::{ - sign_message, AccessList, Signature, TransactionSigned, TxEip1559, B256, - }; - - #[test] - fn test_execute_simple_contract() { - // Given - let kakarot_environment = KakarotEnvironment::new( - *KAKAROT_ADDRESS, - *UNINITIALIZED_ACCOUNT_CLASS_HASH, - *CAIRO1_HELPERS_CLASS_HASH, - *ACCOUNT_CONTRACT_CLASS_HASH, - ); - let coinbase_address = Address::left_padding_from(&0xC01BA5Eu64.to_be_bytes()); - let mut sequencer = KakarotSequencer::new( - INITIAL_SEQUENCER_STATE.clone(), - kakarot_environment, - coinbase_address, - CHAIN_ID, - 0, - 1, - ); - - let mut transaction = TransactionSigned { - hash: B256::default(), - signature: Signature::default(), - transaction: reth_primitives::Transaction::Eip1559(TxEip1559 { - chain_id: CHAIN_ID, - nonce: 0, - gas_limit: 1_000_000, - max_fee_per_gas: 0, - max_priority_fee_per_gas: 0, - to: reth_primitives::TxKind::Call(*TEST_CONTRACT_ADDRESS), - value: U256::ZERO, - access_list: AccessList::default(), - input: Bytes::default(), - }), - }; - let signature = - sign_message(*PRIVATE_KEY, transaction.transaction.signature_hash()).unwrap(); - transaction.signature = signature; - let eoa_nonce = U256::from(0); - let contract_bytecode = Bytes::from(vec![96, 1, 96, 0, 85]); // PUSH 01 PUSH 00 SSTORE - let contract_nonce = U256::from(1); - - // When - let contract = KakarotAccount::new( - &TEST_CONTRACT_ADDRESS, - &contract_bytecode, - contract_nonce, - U256::ZERO, - &[], - ) - .unwrap(); - let eoa = KakarotAccount::new(&PUBLIC_KEY, &Bytes::default(), eoa_nonce, U256::ZERO, &[]) - .unwrap(); - sequencer.setup_account(contract).unwrap(); - sequencer.setup_account(eoa).unwrap(); - let execution_result = sequencer.execute_transaction(transaction); - - // Update the output with the execution result of the current transaction - let tx_output = extract_output_and_log_execution_result( - &execution_result, - "test_case", - "test_category", - ) - .unwrap_or_default(); - - assert!(tx_output.success); - - // Then - let storage = sequencer - .storage_at(&TEST_CONTRACT_ADDRESS, U256::ZERO) - .unwrap(); - - assert_eq!(storage, U256::from(1_u64)); - } -} diff --git a/crates/ef-testing/src/evm_sequencer/evm_state/v1.rs b/crates/ef-testing/src/evm_sequencer/evm_state/v1.rs deleted file mode 100644 index d59336fa..00000000 --- a/crates/ef-testing/src/evm_sequencer/evm_state/v1.rs +++ /dev/null @@ -1,424 +0,0 @@ -use blockifier::{ - abi::{ - abi_utils::{get_fee_token_var_address, get_storage_var_address}, - sierra_types::next_storage_key, - }, - execution::errors::EntryPointExecutionError, - state::state_api::{State as _, StateReader as _, StateResult}, - transaction::{ - errors::TransactionExecutionError, - objects::{TransactionExecutionInfo, TransactionExecutionResult}, - }, -}; -use reth_primitives::{Address, Bytes, TransactionSigned, U256}; -use sequencer::{execution::Execution as _, transaction::BroadcastedTransactionWrapper}; -use starknet::core::types::BroadcastedTransaction; -use starknet_api::state::StorageKey; -use starknet_crypto::Felt; - -use super::Evm; -use crate::evm_sequencer::constants::storage_variables::ACCOUNT_BYTECODE_LEN; -use crate::evm_sequencer::utils::felt_to_bytes; -use crate::{ - evm_sequencer::{ - account::KakarotAccount, - constants::{ - storage_variables::{ - ACCOUNT_IMPLEMENTATION, ACCOUNT_NONCE, ACCOUNT_STORAGE, KAKAROT_BASE_FEE, - KAKAROT_BLOCK_GAS_LIMIT, KAKAROT_COINBASE, KAKAROT_EVM_TO_STARKNET_ADDRESS, - KAKAROT_PREV_RANDAO, OWNABLE_OWNER, - }, - ETH_FEE_TOKEN_ADDRESS, KAKAROT_ADDRESS, - }, - sequencer::KakarotSequencer, - types::felt::FeltSequencer, - utils::{split_u256, to_broadcasted_starknet_transaction}, - }, - starknet_storage, -}; - -impl Evm for KakarotSequencer { - /// Sets up the evm state (coinbase, block number, etc.) - fn setup_state( - &mut self, - base_fee: U256, - prev_randao: U256, - block_gas_limit: U256, - ) -> StateResult<()> { - let kakarot_address = self.environment.kakarot_address; - let coinbase_address: FeltSequencer = (*self.address()).try_into().unwrap(); // infallible - - // Set the coinbase address. - self.state_mut().set_storage_at( - kakarot_address, - get_storage_var_address(KAKAROT_COINBASE, &[]), - coinbase_address.into(), - )?; - - // Set the base fee. - let [low_fee, high_fee] = split_u256(base_fee); - let basefee_address = get_storage_var_address(KAKAROT_BASE_FEE, &[]); - self.state_mut() - .set_storage_at(kakarot_address, basefee_address, low_fee.into())?; - self.state_mut().set_storage_at( - kakarot_address, - next_storage_key(&basefee_address)?, - high_fee.into(), - )?; - - // Set the previous randao. - let [low_prev_randao, high_prev_randao] = split_u256(prev_randao); - let prev_randao_address = get_storage_var_address(KAKAROT_PREV_RANDAO, &[]); - self.state_mut().set_storage_at( - kakarot_address, - prev_randao_address, - low_prev_randao.into(), - )?; - self.state_mut().set_storage_at( - kakarot_address, - next_storage_key(&prev_randao_address)?, - high_prev_randao.into(), - )?; - - // Set the block gas limit, considering it fits in a felt. - let [block_gas_limit, _] = split_u256(block_gas_limit); - let block_gas_limit_address = get_storage_var_address(KAKAROT_BLOCK_GAS_LIMIT, &[]); - self.state_mut().set_storage_at( - kakarot_address, - block_gas_limit_address, - block_gas_limit.into(), - )?; - - Ok(()) - } - - /// Sets up an EOA or contract account. Writes nonce, code and storage to the sequencer storage. - fn setup_account(&mut self, account: KakarotAccount) -> StateResult<()> { - let evm_address = &account.evm_address().to_bytes_be()[12..]; - let evm_address = Address::from_slice(evm_address); - let mut storage = account.storage; - let starknet_address = self.compute_starknet_address(&evm_address)?; - - self.state_mut().set_nonce(starknet_address, account.nonce); - - storage.append(&mut vec![ - starknet_storage!( - ACCOUNT_IMPLEMENTATION, - self.environment.account_contract_class_hash.0 - ), - starknet_storage!(OWNABLE_OWNER, *self.environment.kakarot_address.0.key()), - ]); - - // Write all the storage vars to the sequencer state. - for (k, v) in storage { - self.state_mut().set_storage_at(starknet_address, k, v)?; - } - - let class_hash = self.environment.account_contract_class_hash; - // Set up the contract class hash - self.state_mut() - .set_class_hash_at(starknet_address, class_hash)?; - - // Add the address to the Kakarot evm to starknet mapping - let kakarot_address = self.environment.kakarot_address; - self.state_mut().set_storage_at( - kakarot_address, - get_storage_var_address(KAKAROT_EVM_TO_STARKNET_ADDRESS, &[account.evm_address]), - *starknet_address.0.key(), - )?; - Ok(()) - } - - /// Funds an EOA or contract account. Also gives allowance to the Kakarot contract. - fn fund(&mut self, evm_address: &Address, balance: U256) -> StateResult<()> { - let starknet_address = self.compute_starknet_address(evm_address)?; - let balance_values = split_u256(balance); - let mut storage = vec![]; - - // Initialize the balance storage var. - let balance_key_low = get_fee_token_var_address(starknet_address); - let balance_key_high = next_storage_key(&balance_key_low)?; - storage.append(&mut vec![ - (balance_key_low, balance_values[0].into()), - (balance_key_high, balance_values[1].into()), - ]); - - // Initialize the allowance storage var. - let allowance_key_low = get_storage_var_address( - "ERC20_allowances", - &[*starknet_address.0.key(), *KAKAROT_ADDRESS.0.key()], - ); - let allowance_key_high = next_storage_key(&allowance_key_low)?; - storage.append(&mut vec![ - (allowance_key_low, u128::MAX.into()), - (allowance_key_high, u128::MAX.into()), - ]); - - // Write all the storage vars to the sequencer state. - for (k, v) in storage { - self.state_mut() - .set_storage_at(*ETH_FEE_TOKEN_ADDRESS, k, v)?; - } - Ok(()) - } - - /// Returns the storage value at the given key evm storage key. - fn storage_at(&mut self, evm_address: &Address, key: U256) -> StateResult { - let keys = split_u256(key).map(Into::into); - let key_low = get_storage_var_address(ACCOUNT_STORAGE, &keys); - let key_high = next_storage_key(&key_low)?; - - let starknet_address = self.compute_starknet_address(evm_address)?; - - let low = self.state_mut().get_storage_at(starknet_address, key_low)?; - let high = self - .state_mut() - .get_storage_at(starknet_address, key_high)?; - - let low = U256::from_be_bytes(low.to_bytes_be()); - let high = U256::from_be_bytes(high.to_bytes_be()); - - Ok(high << 128 | low) - } - - /// Returns the nonce of the given address. - /// Uses the Kakarot managed nonce stored in the contract account's storage. - fn nonce_at(&mut self, evm_address: &Address) -> StateResult { - let starknet_address = self.compute_starknet_address(evm_address)?; - - let key = get_storage_var_address(ACCOUNT_NONCE, &[]); - let nonce = self.state_mut().get_storage_at(starknet_address, key)?; - - Ok(U256::from_be_bytes(nonce.to_bytes_be())) - } - - /// Returns the bytecode of the given address. For an EOA, the bytecode_len_ storage variable will return 0, - /// and the function will return an empty vector. For a contract account, the function will return the bytecode - /// stored in the contract_account_bytecode storage variables. The function assumes that the bytecode is stored - /// in 31 byte big-endian chunks. - fn code_at(&mut self, evm_address: &Address) -> StateResult { - // Get all storage addresses. - let starknet_address = self.compute_starknet_address(evm_address)?; - - let bytecode_len = self.state_mut().get_storage_at( - starknet_address, - get_storage_var_address(ACCOUNT_BYTECODE_LEN, &[]), - )?; - let bytecode_len: u64 = bytecode_len.to_biguint().try_into()?; - - if bytecode_len == 0 { - return Ok(Bytes::default()); - } - - // Assumes that the bytecode is stored in 31 byte chunks. - let num_chunks = bytecode_len / 31; - let mut bytecode: Vec = Vec::with_capacity(bytecode_len as usize); - - for chunk_index in 0..num_chunks { - let key = StorageKey::from(chunk_index); - let code = self.state_mut().get_storage_at(starknet_address, key)?; - bytecode.append(&mut felt_to_bytes(&code, 1).to_vec()); - } - - let remainder = bytecode_len % 31; - let key = StorageKey::from(num_chunks); - let code = self.state_mut().get_storage_at(starknet_address, key)?; - bytecode.append(&mut felt_to_bytes(&code, (32 - remainder) as usize).to_vec()); - - Ok(Bytes::from(bytecode)) - } - - /// Returns the balance of native tokens at the given address. - /// Makes use of the default StateReader implementation from Blockifier. - fn balance_at(&mut self, evm_address: &Address) -> StateResult { - let starknet_address = self.compute_starknet_address(evm_address)?; - let (low, high) = self - .state_mut() - .get_fee_token_balance(starknet_address, *ETH_FEE_TOKEN_ADDRESS)?; - - let low = U256::from_be_bytes(low.to_bytes_be()); - let high = U256::from_be_bytes(high.to_bytes_be()); - - Ok(high << 128 | low) - } - - /// Converts the given signed transaction to a Starknet-rs transaction and executes it. - // Since we are still missing the validate for the EOA, the signature is not added - // to the transaction. - fn execute_transaction( - &mut self, - transaction: TransactionSigned, - ) -> TransactionExecutionResult { - let evm_address = transaction.recover_signer().ok_or_else(|| { - TransactionExecutionError::ValidateTransactionError { - error: EntryPointExecutionError::InvalidExecutionInput { - input_descriptor: String::from("Signed transaction"), - info: "Missing signer in signed transaction".to_string(), - }, - class_hash: Default::default(), - storage_address: Default::default(), - selector: Default::default(), - } - })?; - let starknet_address = self.compute_starknet_address(&evm_address)?; - - let starknet_transaction = - BroadcastedTransactionWrapper::new(BroadcastedTransaction::Invoke( - to_broadcasted_starknet_transaction( - &transaction, - Felt::from(starknet_address), - None, - ) - .map_err(|err| { - TransactionExecutionError::ValidateTransactionError { - error: EntryPointExecutionError::InvalidExecutionInput { - input_descriptor: String::from("Failed to convert transaction"), - info: err.to_string(), - }, - class_hash: Default::default(), - storage_address: Default::default(), - selector: Default::default(), - } - })?, - )); - - let chain_id = self.chain_id(); - self.execute( - starknet_transaction - .try_into_execution_transaction(Felt::from(chain_id)) - .unwrap(), - ) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - evm_sequencer::{ - constants::{ - tests::{PRIVATE_KEY, PUBLIC_KEY, TEST_CONTRACT_ADDRESS}, - ACCOUNT_CONTRACT_CLASS_HASH, CAIRO1_HELPERS_CLASS_HASH, CHAIN_ID, - UNINITIALIZED_ACCOUNT_CLASS_HASH, - }, - sequencer::{KakarotEnvironment, INITIAL_SEQUENCER_STATE}, - }, - models::result::extract_output_and_log_execution_result, - }; - use reth_primitives::{sign_message, Signature, TransactionSigned, TxLegacy, B256}; - - #[test] - fn test_store_bytecode() { - // Given - let kakarot_environment = KakarotEnvironment::new( - *KAKAROT_ADDRESS, - *UNINITIALIZED_ACCOUNT_CLASS_HASH, - *CAIRO1_HELPERS_CLASS_HASH, - *ACCOUNT_CONTRACT_CLASS_HASH, - ); - let coinbase_address = Address::left_padding_from(&1234u64.to_be_bytes()); - let mut sequencer = KakarotSequencer::new( - INITIAL_SEQUENCER_STATE.clone(), - kakarot_environment, - coinbase_address, - CHAIN_ID, - 0, - 0, - ); - let bytecode = Bytes::from(vec![ - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - ]); - - // When - let account = KakarotAccount::new( - &TEST_CONTRACT_ADDRESS, - &bytecode, - U256::ZERO, - U256::ZERO, - &[], - ) - .unwrap(); - sequencer.setup_account(account).unwrap(); - - // Then - let code = sequencer.code_at(&TEST_CONTRACT_ADDRESS).unwrap(); - assert_eq!(code, bytecode); - } - - #[test] - fn test_execute_simple_contract() { - // Given - let kakarot_environment = KakarotEnvironment::new( - *KAKAROT_ADDRESS, - *UNINITIALIZED_ACCOUNT_CLASS_HASH, - *CAIRO1_HELPERS_CLASS_HASH, - *ACCOUNT_CONTRACT_CLASS_HASH, - ); - let coinbase_address = Address::left_padding_from(&0xC01BA5Eu64.to_be_bytes()); - let mut sequencer = KakarotSequencer::new( - INITIAL_SEQUENCER_STATE.clone(), - kakarot_environment, - coinbase_address, - CHAIN_ID, - 0, - 0, - ); - - let mut transaction = TransactionSigned { - hash: B256::default(), - signature: Signature::default(), - transaction: reth_primitives::Transaction::Legacy(TxLegacy { - chain_id: Some(CHAIN_ID), - gas_limit: 1_000_000, - to: reth_primitives::TxKind::Call(*TEST_CONTRACT_ADDRESS), - ..Default::default() - }), - }; - let signature = - sign_message(*PRIVATE_KEY, transaction.transaction.signature_hash()).unwrap(); - transaction.signature = signature; - let eoa_nonce = U256::from(0); - let contract_bytecode = Bytes::from(vec![96, 1, 96, 0, 85]); // PUSH 01 PUSH 00 SSTORE - let contract_nonce = U256::from(1); - - // When - let contract = KakarotAccount::new( - &TEST_CONTRACT_ADDRESS, - &contract_bytecode, - contract_nonce, - U256::ZERO, - &[], - ) - .unwrap(); - let eoa = KakarotAccount::new(&PUBLIC_KEY, &Bytes::default(), eoa_nonce, U256::ZERO, &[]) - .unwrap(); - sequencer.setup_account(contract).unwrap(); - sequencer.setup_account(eoa).unwrap(); - let execution_result = sequencer.execute_transaction(transaction); - - // Update the output with the execution result of the current transaction - let tx_output = extract_output_and_log_execution_result( - &execution_result, - "test_case", - "test_category", - ) - .unwrap_or_default(); - - assert!(tx_output.success); - - // Then - let storage = sequencer - .storage_at(&TEST_CONTRACT_ADDRESS, U256::ZERO) - .unwrap(); - - assert_eq!(storage, U256::from(1_u64)); - } -} diff --git a/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs b/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs index 4ec82d02..97294361 100644 --- a/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs +++ b/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs @@ -1,22 +1,4 @@ -#[cfg(feature = "v0")] -pub mod v0; -#[cfg(feature = "v1")] -pub mod v1; - use blockifier::bouncer::BouncerConfig; -#[cfg(feature = "v0")] -pub use v0::INITIAL_SEQUENCER_STATE; - -#[cfg(feature = "v1")] -pub use v1::INITIAL_SEQUENCER_STATE; - -#[cfg(not(any(feature = "v0", feature = "v1")))] -use lazy_static::lazy_static; -#[cfg(not(any(feature = "v0", feature = "v1")))] -lazy_static! { - pub static ref INITIAL_SEQUENCER_STATE: State = State::default(); -} - use starknet::core::types::Felt; use std::ops::{Deref, DerefMut}; @@ -39,13 +21,34 @@ use starknet_api::{ core::{ChainId, ClassHash, ContractAddress}, }; use std::num::NonZeroU128; - -use super::{ - constants::{ETH_FEE_TOKEN_ADDRESS, STRK_FEE_TOKEN_ADDRESS}, +use crate::evm_sequencer::{ + constants::{ + storage_variables::{ + ACCOUNT_PUBLIC_KEY, ERC20_BALANCES, KAKAROT_ACCOUNT_CONTRACT_CLASS_HASH, + KAKAROT_BLOCK_GAS_LIMIT, + KAKAROT_NATIVE_TOKEN_ADDRESS, KAKAROT_UNINITIALIZED_ACCOUNT_CLASS_HASH, OWNABLE_OWNER, + }, + ACCOUNT_CONTRACT_CLASS, ACCOUNT_CONTRACT_CLASS_HASH, BLOCK_GAS_LIMIT, ETH_FEE_TOKEN_ADDRESS, FEE_TOKEN_CLASS, FEE_TOKEN_CLASS_HASH, + KAKAROT_ADDRESS, KAKAROT_CLASS, KAKAROT_CLASS_HASH, KAKAROT_OWNER_ADDRESS, + OPENZEPPELIN_ACCOUNT_CLASS, OPENZEPPELIN_ACCOUNT_CLASS_HASH, RELAYER_ADDRESS, + RELAYER_BALANCE, RELAYER_VERIFYING_KEY, UNINITIALIZED_ACCOUNT_CLASS, + UNINITIALIZED_ACCOUNT_CLASS_HASH, STRK_FEE_TOKEN_ADDRESS, + }, types::contract_class::CasmContractClassWrapper, utils::compute_starknet_address, }; +#[cfg(feature = "v0")] +use crate::evm_sequencer::constants::{CAIRO1_HELPERS_CLASS, CAIRO1_HELPERS_CLASS_HASH, storage_variables::KAKAROT_CAIRO1_HELPERS_CLASS_HASH}; + +use blockifier::abi::abi_utils::get_storage_var_address; +#[allow(unused_imports)] +use blockifier::state::state_api::{ + State as BlockifierState, StateReader as BlockifierStateReader, +}; +use lazy_static::lazy_static; +use sequencer::state::State as SequencerState; + /// Kakarot wrapper around a sequencer. #[derive(Clone)] pub struct KakarotSequencer { @@ -197,3 +200,87 @@ pub fn convert_contract_class_v1(class: &CompiledClass) -> Result Date: Wed, 11 Sep 2024 15:45:48 +0200 Subject: [PATCH 2/5] make clippy happy --- .../src/evm_sequencer/account/mod.rs | 13 +-- .../ef-testing/src/evm_sequencer/constants.rs | 8 ++ .../src/evm_sequencer/evm_state/mod.rs | 40 ++++--- .../src/evm_sequencer/sequencer/mod.rs | 37 +++--- crates/ef-testing/src/evm_sequencer/utils.rs | 105 +++++++++--------- 5 files changed, 105 insertions(+), 98 deletions(-) diff --git a/crates/ef-testing/src/evm_sequencer/account/mod.rs b/crates/ef-testing/src/evm_sequencer/account/mod.rs index 6978d5fd..93a48d58 100644 --- a/crates/ef-testing/src/evm_sequencer/account/mod.rs +++ b/crates/ef-testing/src/evm_sequencer/account/mod.rs @@ -1,20 +1,20 @@ -use starknet::core::utils::cairo_short_string_to_felt; -use starknet_api::{core::Nonce, state::StorageKey}; -use starknet_crypto::{poseidon_permute_comp, Felt}; use blockifier::abi::{abi_utils::get_storage_var_address, sierra_types::next_storage_key}; use reth_primitives::alloy_primitives::keccak256; use reth_primitives::KECCAK_EMPTY; use reth_primitives::{Address, U256}; +use starknet::core::utils::cairo_short_string_to_felt; +use starknet_api::{core::Nonce, state::StorageKey}; +use starknet_crypto::{poseidon_permute_comp, Felt}; -use revm_interpreter::analysis::to_analysed; -use revm_primitives::{Bytecode, Bytes}; -use starknet_api::{StarknetApiError}; use crate::evm_sequencer::constants::storage_variables::{ ACCOUNT_BYTECODE_LEN, ACCOUNT_CODE_HASH, ACCOUNT_EVM_ADDRESS, ACCOUNT_IS_INITIALIZED, ACCOUNT_NONCE, ACCOUNT_STORAGE, ACCOUNT_VALID_JUMPDESTS, }; use crate::evm_sequencer::{types::felt::FeltSequencer, utils::split_u256}; use crate::starknet_storage; +use revm_interpreter::analysis::to_analysed; +use revm_primitives::{Bytecode, Bytes}; +use starknet_api::StarknetApiError; #[macro_export] macro_rules! starknet_storage { @@ -166,7 +166,6 @@ impl KakarotAccount { } } - /// Splits a byte array into 31-byte chunks and converts each chunk to a Felt. pub fn pack_byte_array_to_starkfelt_array(bytes: &[u8]) -> impl Iterator + '_ { bytes.chunks(31).map(Felt::from_bytes_be_slice) diff --git a/crates/ef-testing/src/evm_sequencer/constants.rs b/crates/ef-testing/src/evm_sequencer/constants.rs index ad7ea038..753cf37b 100644 --- a/crates/ef-testing/src/evm_sequencer/constants.rs +++ b/crates/ef-testing/src/evm_sequencer/constants.rs @@ -106,6 +106,14 @@ lazy_static! { panic!("Proxy class hash not defined, use features flag \"v0\" or \"v1\""); pub static ref UNINITIALIZED_ACCOUNT_CLASS_HASH: ClassHash = panic!("Uninitialized account class hash not defined, use features flag \"v0\" or \"v1\""); + pub static ref ACCOUNT_CONTRACT_CLASS: LegacyContractClass = + panic!("Account contract class not defined, use features flag \"v0\" or \"v1\""); + pub static ref KAKAROT_CLASS: LegacyContractClass = + panic!("Kakarot contract class not defined, use features flag \"v0\" or \"v1\""); + pub static ref KAKAROT_CLASS_HASH: ClassHash = + panic!("Kakarot class hash not defined, use features flag \"v0\" or \"v1\""); + pub static ref UNINITIALIZED_ACCOUNT_CLASS: LegacyContractClass = + panic!("Uninitialized account class not defined, use features flag \"v0\" or \"v1\""); } pub mod storage_variables { diff --git a/crates/ef-testing/src/evm_sequencer/evm_state/mod.rs b/crates/ef-testing/src/evm_sequencer/evm_state/mod.rs index 642dc4fd..096522a4 100644 --- a/crates/ef-testing/src/evm_sequencer/evm_state/mod.rs +++ b/crates/ef-testing/src/evm_sequencer/evm_state/mod.rs @@ -1,21 +1,5 @@ -use blockifier::{ - abi::{ - abi_utils::{get_fee_token_var_address, get_storage_var_address}, - sierra_types::next_storage_key, - }, - execution::errors::EntryPointExecutionError, - state::state_api::{State as _, StateReader as _, StateResult}, - transaction::{ - errors::TransactionExecutionError, - objects::{TransactionExecutionInfo, TransactionExecutionResult}, - }, -}; -use reth_primitives::{Address, Bytes, TransactionSigned, U256}; -use sequencer::{execution::Execution as _, transaction::BroadcastedTransactionWrapper}; -use starknet::core::types::BroadcastedTransaction; -use starknet_api::state::StorageKey; -use starknet_crypto::Felt; use crate::evm_sequencer::constants::storage_variables::ACCOUNT_BYTECODE_LEN; +use crate::evm_sequencer::constants::RELAYER_ADDRESS; use crate::evm_sequencer::utils::felt_to_bytes; use crate::{ evm_sequencer::{ @@ -34,8 +18,23 @@ use crate::{ }, starknet_storage, }; -use crate::evm_sequencer::constants::RELAYER_ADDRESS; - +use blockifier::{ + abi::{ + abi_utils::{get_fee_token_var_address, get_storage_var_address}, + sierra_types::next_storage_key, + }, + execution::errors::EntryPointExecutionError, + state::state_api::{State as _, StateReader as _, StateResult}, + transaction::{ + errors::TransactionExecutionError, + objects::{TransactionExecutionInfo, TransactionExecutionResult}, + }, +}; +use reth_primitives::{Address, Bytes, TransactionSigned, U256}; +use sequencer::{execution::Execution as _, transaction::BroadcastedTransactionWrapper}; +use starknet::core::types::BroadcastedTransaction; +use starknet_api::state::StorageKey; +use starknet_crypto::Felt; /// EVM state interface. Used to setup the evm state, EOA and contract accounts, /// fund them and get their state (balance, nonce, code, storage). @@ -339,7 +338,6 @@ impl Evm for KakarotSequencer { } } - #[cfg(test)] mod tests { use super::*; @@ -350,7 +348,7 @@ mod tests { ACCOUNT_CONTRACT_CLASS_HASH, CAIRO1_HELPERS_CLASS_HASH, CHAIN_ID, KAKAROT_ADDRESS, UNINITIALIZED_ACCOUNT_CLASS_HASH, }, - sequencer::{INITIAL_SEQUENCER_STATE, KakarotEnvironment}, + sequencer::{KakarotEnvironment, INITIAL_SEQUENCER_STATE}, }, models::result::extract_output_and_log_execution_result, }; diff --git a/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs b/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs index 97294361..66fe67cf 100644 --- a/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs +++ b/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs @@ -3,6 +3,22 @@ use starknet::core::types::Felt; use std::ops::{Deref, DerefMut}; use crate::evm_sequencer::types::felt::FeltSequencer; +use crate::evm_sequencer::{ + constants::{ + storage_variables::{ + ACCOUNT_PUBLIC_KEY, ERC20_BALANCES, KAKAROT_ACCOUNT_CONTRACT_CLASS_HASH, + KAKAROT_BLOCK_GAS_LIMIT, KAKAROT_NATIVE_TOKEN_ADDRESS, + KAKAROT_UNINITIALIZED_ACCOUNT_CLASS_HASH, OWNABLE_OWNER, + }, + ACCOUNT_CONTRACT_CLASS, ACCOUNT_CONTRACT_CLASS_HASH, BLOCK_GAS_LIMIT, + ETH_FEE_TOKEN_ADDRESS, FEE_TOKEN_CLASS, FEE_TOKEN_CLASS_HASH, KAKAROT_ADDRESS, + KAKAROT_CLASS, KAKAROT_CLASS_HASH, KAKAROT_OWNER_ADDRESS, OPENZEPPELIN_ACCOUNT_CLASS, + OPENZEPPELIN_ACCOUNT_CLASS_HASH, RELAYER_ADDRESS, RELAYER_BALANCE, RELAYER_VERIFYING_KEY, + STRK_FEE_TOKEN_ADDRESS, UNINITIALIZED_ACCOUNT_CLASS, UNINITIALIZED_ACCOUNT_CLASS_HASH, + }, + types::contract_class::CasmContractClassWrapper, + utils::compute_starknet_address, +}; use blockifier::blockifier::block::{BlockInfo, GasPrices}; use blockifier::context::ChainInfo; use blockifier::context::{BlockContext, FeeTokenAddresses}; @@ -21,25 +37,12 @@ use starknet_api::{ core::{ChainId, ClassHash, ContractAddress}, }; use std::num::NonZeroU128; -use crate::evm_sequencer::{ - constants::{ - storage_variables::{ - ACCOUNT_PUBLIC_KEY, ERC20_BALANCES, KAKAROT_ACCOUNT_CONTRACT_CLASS_HASH, - KAKAROT_BLOCK_GAS_LIMIT, - KAKAROT_NATIVE_TOKEN_ADDRESS, KAKAROT_UNINITIALIZED_ACCOUNT_CLASS_HASH, OWNABLE_OWNER, - }, - ACCOUNT_CONTRACT_CLASS, ACCOUNT_CONTRACT_CLASS_HASH, BLOCK_GAS_LIMIT, ETH_FEE_TOKEN_ADDRESS, FEE_TOKEN_CLASS, FEE_TOKEN_CLASS_HASH, - KAKAROT_ADDRESS, KAKAROT_CLASS, KAKAROT_CLASS_HASH, KAKAROT_OWNER_ADDRESS, - OPENZEPPELIN_ACCOUNT_CLASS, OPENZEPPELIN_ACCOUNT_CLASS_HASH, RELAYER_ADDRESS, - RELAYER_BALANCE, RELAYER_VERIFYING_KEY, UNINITIALIZED_ACCOUNT_CLASS, - UNINITIALIZED_ACCOUNT_CLASS_HASH, STRK_FEE_TOKEN_ADDRESS, - }, - types::contract_class::CasmContractClassWrapper, - utils::compute_starknet_address, -}; #[cfg(feature = "v0")] -use crate::evm_sequencer::constants::{CAIRO1_HELPERS_CLASS, CAIRO1_HELPERS_CLASS_HASH, storage_variables::KAKAROT_CAIRO1_HELPERS_CLASS_HASH}; +use crate::evm_sequencer::constants::{ + storage_variables::KAKAROT_CAIRO1_HELPERS_CLASS_HASH, CAIRO1_HELPERS_CLASS, + CAIRO1_HELPERS_CLASS_HASH, +}; use blockifier::abi::abi_utils::get_storage_var_address; #[allow(unused_imports)] diff --git a/crates/ef-testing/src/evm_sequencer/utils.rs b/crates/ef-testing/src/evm_sequencer/utils.rs index 153814ad..3e38b031 100644 --- a/crates/ef-testing/src/evm_sequencer/utils.rs +++ b/crates/ef-testing/src/evm_sequencer/utils.rs @@ -1,4 +1,5 @@ use super::{constants::KAKAROT_ADDRESS, types::felt::FeltSequencer}; +use crate::evm_sequencer::constants::RELAYER_ADDRESS; use bytes::BytesMut; use reth_primitives::{Address, Bytes, TransactionSigned, TxType, U256}; use starknet::core::{ @@ -6,7 +7,6 @@ use starknet::core::{ utils::get_contract_address, }; use starknet::macros::selector; -use crate::evm_sequencer::constants::RELAYER_ADDRESS; /// Computes the Starknet address of a contract given its EVM address. pub fn compute_starknet_address( @@ -82,52 +82,51 @@ pub fn to_broadcasted_starknet_transaction( v.into(), ]; - let mut execute_from_outside_calldata = - if cfg!(feature = "v0") { - let mut execute_from_outside_calldata = vec![ - *RELAYER_ADDRESS.0.key(), // OutsideExecution caller - Felt::ZERO, // OutsideExecution nonce - Felt::ZERO, // OutsideExecution execute_after - Felt::from(10_000_000_000_000u128), // OutsideExecution execute_before - Felt::ONE, // call_array_len - *KAKAROT_ADDRESS.0.key(), // CallArray to - selector!("eth_send_transaction"), // CallArray selector - Felt::ZERO, // CallArray data_offset - calldata.len().into(), // CallArray data_len - calldata.len().into(), // calldata_len - ]; - execute_from_outside_calldata.append(&mut calldata); - execute_from_outside_calldata.push(signature.len().into()); - execute_from_outside_calldata.append(&mut signature); - execute_from_outside_calldata - } else if cfg!(feature = "v1") { - let mut execute_from_outside_calldata = vec![ - *RELAYER_ADDRESS.0.key(), // OutsideExecution caller - Felt::ZERO, // OutsideExecution nonce - Felt::ZERO, // OutsideExecution execute_after - Felt::from(10_000_000_000_000u128), // OutsideExecution execute_before - Felt::ONE, // call_array_len - *KAKAROT_ADDRESS.0.key(), // CallArray to - selector!("eth_send_transaction"), // CallArray selector - calldata.len().into(), // CallArray data_len - ]; - execute_from_outside_calldata.append(&mut calldata); - execute_from_outside_calldata.push(signature.len().into()); - execute_from_outside_calldata.append(&mut signature); - execute_from_outside_calldata - } else { - panic!("Either 'v0' or 'v1' feature must be enabled") - }; - - let mut execute_entrypoint_calldata = vec![ - Felt::ONE, // call_array_len - starknet_address, // CallArray to - selector!("execute_from_outside"), // CallArray selector - Felt::ZERO, // CallArray data_offset - (execute_from_outside_calldata.len()).into(), // CallArraydata data_len - (execute_from_outside_calldata.len()).into(), // calldata length + let mut execute_from_outside_calldata = if cfg!(feature = "v0") { + let mut execute_from_outside_calldata = vec![ + *RELAYER_ADDRESS.0.key(), // OutsideExecution caller + Felt::ZERO, // OutsideExecution nonce + Felt::ZERO, // OutsideExecution execute_after + Felt::from(10_000_000_000_000u128), // OutsideExecution execute_before + Felt::ONE, // call_array_len + *KAKAROT_ADDRESS.0.key(), // CallArray to + selector!("eth_send_transaction"), // CallArray selector + Felt::ZERO, // CallArray data_offset + calldata.len().into(), // CallArray data_len + calldata.len().into(), // calldata_len ]; - execute_entrypoint_calldata.append(&mut execute_from_outside_calldata); + execute_from_outside_calldata.append(&mut calldata); + execute_from_outside_calldata.push(signature.len().into()); + execute_from_outside_calldata.append(&mut signature); + execute_from_outside_calldata + } else if cfg!(feature = "v1") { + let mut execute_from_outside_calldata = vec![ + *RELAYER_ADDRESS.0.key(), // OutsideExecution caller + Felt::ZERO, // OutsideExecution nonce + Felt::ZERO, // OutsideExecution execute_after + Felt::from(10_000_000_000_000u128), // OutsideExecution execute_before + Felt::ONE, // call_array_len + *KAKAROT_ADDRESS.0.key(), // CallArray to + selector!("eth_send_transaction"), // CallArray selector + calldata.len().into(), // CallArray data_len + ]; + execute_from_outside_calldata.append(&mut calldata); + execute_from_outside_calldata.push(signature.len().into()); + execute_from_outside_calldata.append(&mut signature); + execute_from_outside_calldata + } else { + panic!("Either 'v0' or 'v1' feature must be enabled") + }; + + let mut execute_entrypoint_calldata = vec![ + Felt::ONE, // call_array_len + starknet_address, // CallArray to + selector!("execute_from_outside"), // CallArray selector + Felt::ZERO, // CallArray data_offset + (execute_from_outside_calldata.len()).into(), // CallArraydata data_len + (execute_from_outside_calldata.len()).into(), // calldata length + ]; + execute_entrypoint_calldata.append(&mut execute_from_outside_calldata); let request = { { @@ -137,14 +136,14 @@ pub fn to_broadcasted_starknet_transaction( let relayer_address = *RELAYER_ADDRESS.0.key(); let relayer_nonce = relayer_nonce.expect("Relayer nonce not provided"); let invoke_v1_tx = vec![ - Felt::from_bytes_be_slice(b"invoke"), // "invoke" - Felt::ONE, // version - relayer_address, // sender_address - Felt::ZERO, // 0 + Felt::from_bytes_be_slice(b"invoke"), // "invoke" + Felt::ONE, // version + relayer_address, // sender_address + Felt::ZERO, // 0 compute_hash_on_elements(&execute_entrypoint_calldata), // h(calldata) - Felt::ZERO, // max_fee - transaction.chain_id().unwrap().into(), // chain_id - relayer_nonce, // nonce + Felt::ZERO, // max_fee + transaction.chain_id().unwrap().into(), // chain_id + relayer_nonce, // nonce ]; let transaction_hash = compute_hash_on_elements(&invoke_v1_tx); let signature_relayer = RELAYER_SIGNING_KEY From 931e21148363936349f70e104e9626b7f7768a7a Mon Sep 17 00:00:00 2001 From: enitrat Date: Wed, 11 Sep 2024 16:01:38 +0200 Subject: [PATCH 3/5] apply review suggestions --- .../src/evm_sequencer/sequencer/mod.rs | 28 ++++++++----------- crates/ef-testing/src/evm_sequencer/utils.rs | 28 ++++++++----------- 2 files changed, 23 insertions(+), 33 deletions(-) diff --git a/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs b/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs index 66fe67cf..5b7293e2 100644 --- a/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs +++ b/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs @@ -208,26 +208,20 @@ lazy_static! { pub static ref INITIAL_SEQUENCER_STATE: SequencerState = { let mut state = SequencerState::default(); - // On KakarotZero we rely on the Cairo1 helpers class for unavailable syscalls and precompiles. - #[cfg(feature = "v0")] - let storage = vec![ - (OWNABLE_OWNER, *KAKAROT_OWNER_ADDRESS.0.key()), - (KAKAROT_NATIVE_TOKEN_ADDRESS, *ETH_FEE_TOKEN_ADDRESS.0.key()), - (KAKAROT_ACCOUNT_CONTRACT_CLASS_HASH, ACCOUNT_CONTRACT_CLASS_HASH.0), - (KAKAROT_CAIRO1_HELPERS_CLASS_HASH, CAIRO1_HELPERS_CLASS_HASH.0), - (KAKAROT_BLOCK_GAS_LIMIT, Felt::from(BLOCK_GAS_LIMIT)), - (KAKAROT_UNINITIALIZED_ACCOUNT_CLASS_HASH, UNINITIALIZED_ACCOUNT_CLASS_HASH.0), - ]; - #[cfg(not(feature = "v0"))] - let storage = vec![ - (OWNABLE_OWNER, *KAKAROT_OWNER_ADDRESS.0.key()), - (KAKAROT_NATIVE_TOKEN_ADDRESS, *ETH_FEE_TOKEN_ADDRESS.0.key()), - (KAKAROT_ACCOUNT_CONTRACT_CLASS_HASH, ACCOUNT_CONTRACT_CLASS_HASH.0), - (KAKAROT_BLOCK_GAS_LIMIT, Felt::from(BLOCK_GAS_LIMIT)), - (KAKAROT_UNINITIALIZED_ACCOUNT_CLASS_HASH, UNINITIALIZED_ACCOUNT_CLASS_HASH.0), + #[allow(unused_mut)] + let mut storage = vec![ + (OWNABLE_OWNER, *KAKAROT_OWNER_ADDRESS.0.key()), + (KAKAROT_NATIVE_TOKEN_ADDRESS, *ETH_FEE_TOKEN_ADDRESS.0.key()), + (KAKAROT_ACCOUNT_CONTRACT_CLASS_HASH, ACCOUNT_CONTRACT_CLASS_HASH.0), + (KAKAROT_BLOCK_GAS_LIMIT, Felt::from(BLOCK_GAS_LIMIT)), + (KAKAROT_UNINITIALIZED_ACCOUNT_CLASS_HASH, UNINITIALIZED_ACCOUNT_CLASS_HASH.0), ]; + // On KakarotZero we rely on the Cairo1 helpers class for unavailable syscalls and precompiles. + #[cfg(feature = "v0")] + storage.push((KAKAROT_CAIRO1_HELPERS_CLASS_HASH, CAIRO1_HELPERS_CLASS_HASH.0)); + // Write all the storage vars to the sequencer state. for (k, v) in storage { (&mut state).set_storage_at(*KAKAROT_ADDRESS, get_storage_var_address(k, &[]), v).expect("failed to set storage"); diff --git a/crates/ef-testing/src/evm_sequencer/utils.rs b/crates/ef-testing/src/evm_sequencer/utils.rs index 3e38b031..82a414dd 100644 --- a/crates/ef-testing/src/evm_sequencer/utils.rs +++ b/crates/ef-testing/src/evm_sequencer/utils.rs @@ -83,7 +83,7 @@ pub fn to_broadcasted_starknet_transaction( ]; let mut execute_from_outside_calldata = if cfg!(feature = "v0") { - let mut execute_from_outside_calldata = vec![ + vec![ *RELAYER_ADDRESS.0.key(), // OutsideExecution caller Felt::ZERO, // OutsideExecution nonce Felt::ZERO, // OutsideExecution execute_after @@ -94,13 +94,9 @@ pub fn to_broadcasted_starknet_transaction( Felt::ZERO, // CallArray data_offset calldata.len().into(), // CallArray data_len calldata.len().into(), // calldata_len - ]; - execute_from_outside_calldata.append(&mut calldata); - execute_from_outside_calldata.push(signature.len().into()); - execute_from_outside_calldata.append(&mut signature); - execute_from_outside_calldata + ] } else if cfg!(feature = "v1") { - let mut execute_from_outside_calldata = vec![ + vec![ *RELAYER_ADDRESS.0.key(), // OutsideExecution caller Felt::ZERO, // OutsideExecution nonce Felt::ZERO, // OutsideExecution execute_after @@ -109,15 +105,15 @@ pub fn to_broadcasted_starknet_transaction( *KAKAROT_ADDRESS.0.key(), // CallArray to selector!("eth_send_transaction"), // CallArray selector calldata.len().into(), // CallArray data_len - ]; - execute_from_outside_calldata.append(&mut calldata); - execute_from_outside_calldata.push(signature.len().into()); - execute_from_outside_calldata.append(&mut signature); - execute_from_outside_calldata + ] } else { panic!("Either 'v0' or 'v1' feature must be enabled") }; + execute_from_outside_calldata.append(&mut calldata); + execute_from_outside_calldata.push(signature.len().into()); + execute_from_outside_calldata.append(&mut signature); + let mut execute_entrypoint_calldata = vec![ Felt::ONE, // call_array_len starknet_address, // CallArray to @@ -140,10 +136,10 @@ pub fn to_broadcasted_starknet_transaction( Felt::ONE, // version relayer_address, // sender_address Felt::ZERO, // 0 - compute_hash_on_elements(&execute_entrypoint_calldata), // h(calldata) - Felt::ZERO, // max_fee - transaction.chain_id().unwrap().into(), // chain_id - relayer_nonce, // nonce + compute_hash_on_elements(&execute_entrypoint_calldata), // h(execute_entrypoint_calldata) + Felt::ZERO, // max_fee + transaction.chain_id().unwrap().into(), // chain_id + relayer_nonce, // nonce ]; let transaction_hash = compute_hash_on_elements(&invoke_v1_tx); let signature_relayer = RELAYER_SIGNING_KEY From 30027c72e36bf814c2e331f38ffb275ff88869e3 Mon Sep 17 00:00:00 2001 From: enitrat Date: Wed, 11 Sep 2024 16:30:31 +0200 Subject: [PATCH 4/5] apply pr suggestions --- crates/ef-testing/src/evm_sequencer/account/mod.rs | 9 +++------ crates/ef-testing/src/evm_sequencer/evm_state/mod.rs | 2 +- crates/ef-testing/src/evm_sequencer/sequencer/mod.rs | 1 - 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/crates/ef-testing/src/evm_sequencer/account/mod.rs b/crates/ef-testing/src/evm_sequencer/account/mod.rs index 93a48d58..866da256 100644 --- a/crates/ef-testing/src/evm_sequencer/account/mod.rs +++ b/crates/ef-testing/src/evm_sequencer/account/mod.rs @@ -5,7 +5,6 @@ use reth_primitives::{Address, U256}; use starknet::core::utils::cairo_short_string_to_felt; use starknet_api::{core::Nonce, state::StorageKey}; use starknet_crypto::{poseidon_permute_comp, Felt}; - use crate::evm_sequencer::constants::storage_variables::{ ACCOUNT_BYTECODE_LEN, ACCOUNT_CODE_HASH, ACCOUNT_EVM_ADDRESS, ACCOUNT_IS_INITIALIZED, ACCOUNT_NONCE, ACCOUNT_STORAGE, ACCOUNT_VALID_JUMPDESTS, @@ -90,11 +89,9 @@ impl KakarotAccount { starknet_storage!(ACCOUNT_EVM_ADDRESS, evm_address), starknet_storage!(ACCOUNT_IS_INITIALIZED, 1u8), starknet_storage!(ACCOUNT_BYTECODE_LEN, code.len() as u32), + starknet_storage!(ACCOUNT_NONCE, nonce), ]; - // Write the nonce of the account is written to storage after each tx. - storage.append(&mut vec![starknet_storage!(ACCOUNT_NONCE, nonce)]); - // Initialize the bytecode storage var. let mut bytecode_storage = pack_byte_array_to_starkfelt_array(code) .enumerate() @@ -104,9 +101,9 @@ impl KakarotAccount { // Initialize the code hash var let account_is_empty = - code.is_empty() && nonce == Felt::from(0) && balance == U256::from(0); + code.is_empty() && nonce == Felt::ZERO && balance == U256::ZERO; let code_hash = if account_is_empty { - U256::from(0) + U256::ZERO } else if code.is_empty() { U256::from_be_slice(KECCAK_EMPTY.as_slice()) } else { diff --git a/crates/ef-testing/src/evm_sequencer/evm_state/mod.rs b/crates/ef-testing/src/evm_sequencer/evm_state/mod.rs index 096522a4..661dbaab 100644 --- a/crates/ef-testing/src/evm_sequencer/evm_state/mod.rs +++ b/crates/ef-testing/src/evm_sequencer/evm_state/mod.rs @@ -393,7 +393,7 @@ mod tests { let signature = sign_message(*PRIVATE_KEY, transaction.transaction.signature_hash()).unwrap(); transaction.signature = signature; - let eoa_nonce = U256::from(0); + let eoa_nonce = U256::ZERO; let contract_bytecode = Bytes::from(vec![96, 1, 96, 0, 85]); // PUSH 01 PUSH 00 SSTORE let contract_nonce = U256::from(1); diff --git a/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs b/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs index 5b7293e2..ed1dd7e3 100644 --- a/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs +++ b/crates/ef-testing/src/evm_sequencer/sequencer/mod.rs @@ -43,7 +43,6 @@ use crate::evm_sequencer::constants::{ storage_variables::KAKAROT_CAIRO1_HELPERS_CLASS_HASH, CAIRO1_HELPERS_CLASS, CAIRO1_HELPERS_CLASS_HASH, }; - use blockifier::abi::abi_utils::get_storage_var_address; #[allow(unused_imports)] use blockifier::state::state_api::{ From da88d4de82dedb177d4bbec556a2b25336512f13 Mon Sep 17 00:00:00 2001 From: enitrat Date: Wed, 11 Sep 2024 19:47:40 +0200 Subject: [PATCH 5/5] fmt --- .../ef-testing/src/evm_sequencer/account/mod.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/crates/ef-testing/src/evm_sequencer/account/mod.rs b/crates/ef-testing/src/evm_sequencer/account/mod.rs index 866da256..f9d80535 100644 --- a/crates/ef-testing/src/evm_sequencer/account/mod.rs +++ b/crates/ef-testing/src/evm_sequencer/account/mod.rs @@ -1,19 +1,19 @@ -use blockifier::abi::{abi_utils::get_storage_var_address, sierra_types::next_storage_key}; -use reth_primitives::alloy_primitives::keccak256; -use reth_primitives::KECCAK_EMPTY; -use reth_primitives::{Address, U256}; -use starknet::core::utils::cairo_short_string_to_felt; -use starknet_api::{core::Nonce, state::StorageKey}; -use starknet_crypto::{poseidon_permute_comp, Felt}; use crate::evm_sequencer::constants::storage_variables::{ ACCOUNT_BYTECODE_LEN, ACCOUNT_CODE_HASH, ACCOUNT_EVM_ADDRESS, ACCOUNT_IS_INITIALIZED, ACCOUNT_NONCE, ACCOUNT_STORAGE, ACCOUNT_VALID_JUMPDESTS, }; use crate::evm_sequencer::{types::felt::FeltSequencer, utils::split_u256}; use crate::starknet_storage; +use blockifier::abi::{abi_utils::get_storage_var_address, sierra_types::next_storage_key}; +use reth_primitives::alloy_primitives::keccak256; +use reth_primitives::KECCAK_EMPTY; +use reth_primitives::{Address, U256}; use revm_interpreter::analysis::to_analysed; use revm_primitives::{Bytecode, Bytes}; +use starknet::core::utils::cairo_short_string_to_felt; use starknet_api::StarknetApiError; +use starknet_api::{core::Nonce, state::StorageKey}; +use starknet_crypto::{poseidon_permute_comp, Felt}; #[macro_export] macro_rules! starknet_storage { @@ -100,8 +100,7 @@ impl KakarotAccount { storage.append(&mut bytecode_storage); // Initialize the code hash var - let account_is_empty = - code.is_empty() && nonce == Felt::ZERO && balance == U256::ZERO; + let account_is_empty = code.is_empty() && nonce == Felt::ZERO && balance == U256::ZERO; let code_hash = if account_is_empty { U256::ZERO } else if code.is_empty() {