diff --git a/crates/ef-testing/src/evm_sequencer/account/mod.rs b/crates/ef-testing/src/evm_sequencer/account/mod.rs index 4bb3a72b..a21e2330 100644 --- a/crates/ef-testing/src/evm_sequencer/account/mod.rs +++ b/crates/ef-testing/src/evm_sequencer/account/mod.rs @@ -75,6 +75,7 @@ pub mod kkrt_account { _code: &Bytes, _nonce: U256, _evm_storage: &[(U256, U256)], + _is_eoa: bool, ) -> Result { Ok(Self { evm_address: StarkFelt::default(), diff --git a/crates/ef-testing/src/evm_sequencer/account/v0.rs b/crates/ef-testing/src/evm_sequencer/account/v0.rs index af2e3236..13f7cfde 100644 --- a/crates/ef-testing/src/evm_sequencer/account/v0.rs +++ b/crates/ef-testing/src/evm_sequencer/account/v0.rs @@ -12,6 +12,7 @@ impl KakarotAccount { code: &Bytes, nonce: U256, evm_storage: &[(U256, U256)], + is_eoa: bool, ) -> Result { let nonce = StarkFelt::from(TryInto::::try_into(nonce).map_err(|err| { StarknetApiError::OutOfRange { @@ -30,9 +31,8 @@ impl KakarotAccount { ]; // Initialize the implementation and nonce based on account type. - // The account is an EOA if it has no bytecode and no storage (or all storage is zero). - let has_code_or_storage = !code.is_empty() || evm_storage.iter().any(|x| x.1 != U256::ZERO); - let account_type = if !has_code_or_storage { + // In tests, only the sender is an EOA. + let account_type = if is_eoa { AccountType::EOA } else { storage.append(&mut vec![starknet_storage!("nonce", nonce)]); diff --git a/crates/ef-testing/src/evm_sequencer/account/v1.rs b/crates/ef-testing/src/evm_sequencer/account/v1.rs index dc0516d8..f3bcedb4 100644 --- a/crates/ef-testing/src/evm_sequencer/account/v1.rs +++ b/crates/ef-testing/src/evm_sequencer/account/v1.rs @@ -22,6 +22,7 @@ impl KakarotAccount { code: &Bytes, nonce: U256, evm_storage: &[(U256, U256)], + is_eoa: bool, ) -> Result { let nonce = StarkFelt::from(TryInto::::try_into(nonce).map_err(|err| { StarknetApiError::OutOfRange { @@ -36,9 +37,8 @@ impl KakarotAccount { let mut storage = vec![starknet_storage!("evm_address", evm_address)]; // Initialize the implementation and nonce based on account type. - // The account is an EOA if it has no bytecode and no storage (or all storage is zero). - let has_code_or_storage = !code.is_empty() || evm_storage.iter().any(|x| x.1 != U256::ZERO); - let account_type = if !has_code_or_storage { + // In tests, only the sender is an EOA. + let account_type = if is_eoa { AccountType::EOA } else { storage.push(starknet_storage!("contract_account_nonce", nonce)); diff --git a/crates/ef-testing/src/evm_sequencer/evm_state/v0.rs b/crates/ef-testing/src/evm_sequencer/evm_state/v0.rs index e81f8b50..761f9e77 100644 --- a/crates/ef-testing/src/evm_sequencer/evm_state/v0.rs +++ b/crates/ef-testing/src/evm_sequencer/evm_state/v0.rs @@ -335,8 +335,9 @@ mod tests { let nonce = U256::from(0); // When - let contract = KakarotAccount::new(&TEST_CONTRACT_ADDRESS, &bytecode, nonce, &[]).unwrap(); - let eoa = KakarotAccount::new(&PUBLIC_KEY, &Bytes::default(), nonce, &[]).unwrap(); + let contract = + KakarotAccount::new(&TEST_CONTRACT_ADDRESS, &bytecode, nonce, &[], false).unwrap(); + let eoa = KakarotAccount::new(&PUBLIC_KEY, &Bytes::default(), nonce, &[], true).unwrap(); sequencer.setup_account(contract).unwrap(); sequencer.setup_account(eoa).unwrap(); sequencer.execute_transaction(transaction).unwrap(); diff --git a/crates/ef-testing/src/evm_sequencer/evm_state/v1.rs b/crates/ef-testing/src/evm_sequencer/evm_state/v1.rs index fe5ae48b..8f5e8cad 100644 --- a/crates/ef-testing/src/evm_sequencer/evm_state/v1.rs +++ b/crates/ef-testing/src/evm_sequencer/evm_state/v1.rs @@ -40,7 +40,8 @@ impl Evm for KakarotSequencer { /// Sets up the evm state (coinbase, block number, etc.) fn setup_state(&mut self, _base_fee: U256) -> StateResult<()> { let coinbase_address = *self.address(); - let coinbase = KakarotAccount::new(&coinbase_address, &Bytes::default(), U256::ZERO, &[])?; + let coinbase = + KakarotAccount::new(&coinbase_address, &Bytes::default(), U256::ZERO, &[], true)?; self.setup_account(coinbase)?; self.fund(&coinbase_address, U256::ZERO)?; @@ -383,7 +384,7 @@ mod tests { // When let account = - KakarotAccount::new(&TEST_CONTRACT_ADDRESS, &bytecode, U256::ZERO, &[]).unwrap(); + KakarotAccount::new(&TEST_CONTRACT_ADDRESS, &bytecode, U256::ZERO, &[], false).unwrap(); sequencer.setup_account(account).unwrap(); // Then @@ -437,8 +438,8 @@ mod tests { ]); // PUSH 01 PUSH 00 SSTORE let nonce = U256::from(0); let contract_account = - KakarotAccount::new(&TEST_CONTRACT_ADDRESS, &bytecode, nonce, &[]).unwrap(); - let eoa = KakarotAccount::new(&PUBLIC_KEY, &Bytes::default(), nonce, &[]).unwrap(); + KakarotAccount::new(&TEST_CONTRACT_ADDRESS, &bytecode, nonce, &[], false).unwrap(); + let eoa = KakarotAccount::new(&PUBLIC_KEY, &Bytes::default(), nonce, &[], true).unwrap(); sequencer.setup_account(contract_account).unwrap(); sequencer.setup_account(eoa).unwrap(); sequencer.execute_transaction(transaction).unwrap(); diff --git a/crates/ef-testing/src/models/case.rs b/crates/ef-testing/src/models/case.rs index 50753bfb..02c21fa3 100644 --- a/crates/ef-testing/src/models/case.rs +++ b/crates/ef-testing/src/models/case.rs @@ -56,12 +56,18 @@ impl BlockchainTestCase { } fn handle_pre_state(&self, sequencer: &mut KakarotSequencer) -> Result<(), RunnerError> { + let wallet = LocalWallet::from_bytes(&self.secret_key.0) + .map_err(|err| RunnerError::Other(vec![err.to_string()].into()))?; + let sender_address = wallet.address().to_fixed_bytes(); + for (address, account) in self.pre.iter() { + let is_eoa = address.0 == sender_address; let kakarot_account = KakarotAccount::new( address, &account.code, account.nonce, &account.storage.clone().into_iter().collect::>()[..], + is_eoa, )?; sequencer.setup_account(kakarot_account)?; sequencer.fund(address, account.balance)?; diff --git a/crates/ef-testing/src/models/result.rs b/crates/ef-testing/src/models/result.rs index 64fe67b7..0e7cbf18 100644 --- a/crates/ef-testing/src/models/result.rs +++ b/crates/ef-testing/src/models/result.rs @@ -70,6 +70,11 @@ pub(crate) fn log_execution_result( TransactionExecutionResult::Err(TransactionExecutionError::ValidateTransactionError( EntryPointExecutionError::VirtualMachineExecutionErrorWithTrace { trace, .. }, )) => { + // There are specific test cases where validation failed because the sender account has code. + // They're caught by EOA validation, and rejected with this specific error message. + if trace.contains("EOAs cannot have code") { + return; + } let re = regex::Regex::new( r#"Error in the called contract \((0x[0-9a-zA-Z]+)\)[\s\S]*?EntryPointSelector\(StarkFelt\("(0x[0-9a-zA-Z]+)"\)\)"#, ).unwrap();