diff --git a/.tool-versions b/.tool-versions index a9ae4ab32..e87352f08 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -scarb nightly-2023-11-25 \ No newline at end of file +scarb 2.4.0-rc6 \ No newline at end of file diff --git a/Scarb.toml b/Scarb.toml index aec96db9d..b0e3f3d2d 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -4,14 +4,14 @@ members = ["crates/*"] [workspace.package] description = "Kakarot is an (zk)-Ethereum Virtual Machine implementation written in Cairo." documentation = "https://www.kakarot.org/" -cairo-version = "2.3.1" +cairo-version = "2.4.0" version = "0.1.0" readme = "README.md" repository = "https://github.com/kkrt-labs/kakarot-ssj/" license-file = "LICENSE" [workspace.dependencies] -starknet = "2.3.1" +starknet = "2.4.0-rc6" [workspace.tool.fmt] sort-module-level-items = true diff --git a/crates/contracts/src/eoa.cairo b/crates/contracts/src/eoa.cairo index d683970fa..bd1774380 100644 --- a/crates/contracts/src/eoa.cairo +++ b/crates/contracts/src/eoa.cairo @@ -147,12 +147,12 @@ mod ExternallyOwnedAccount { contract_address: self.kakarot_core_address() }; - let result = kakarot_core_dispatcher + let (_, return_data) = kakarot_core_dispatcher .eth_send_transaction( Option::Some(destination), gas_limit, gas_price, amount, calldata ); - array![result.to_felt252_array().span()] + array![return_data.to_felt252_array().span()] } } diff --git a/crates/contracts/src/kakarot_core/interface.cairo b/crates/contracts/src/kakarot_core/interface.cairo index 219055219..0d3d4151a 100644 --- a/crates/contracts/src/kakarot_core/interface.cairo +++ b/crates/contracts/src/kakarot_core/interface.cairo @@ -70,7 +70,7 @@ trait IKakarotCore { gas_price: u128, value: u256, calldata: Span - ) -> Span; + ) -> (bool, Span); /// Transaction entrypoint into the EVM /// Executes an EVM transaction and possibly modifies the state @@ -81,7 +81,7 @@ trait IKakarotCore { gas_price: u128, value: u256, calldata: Span - ) -> Span; + ) -> (bool, Span); /// Upgrade the KakarotCore smart contract /// Using replace_class_syscall @@ -171,7 +171,7 @@ trait IExtendedKakarotCore { gas_price: u128, value: u256, calldata: Span - ) -> Span; + ) -> (bool, Span); /// Transaction entrypoint into the EVM /// Executes an EVM transaction and possibly modifies the state @@ -182,7 +182,7 @@ trait IExtendedKakarotCore { gas_price: u128, value: u256, calldata: Span - ) -> Span; + ) -> (bool, Span); /// Upgrade the KakarotCore smart contract /// Using replace_class_syscall diff --git a/crates/contracts/src/kakarot_core/kakarot.cairo b/crates/contracts/src/kakarot_core/kakarot.cairo index 790bb29cb..8ded7a443 100644 --- a/crates/contracts/src/kakarot_core/kakarot.cairo +++ b/crates/contracts/src/kakarot_core/kakarot.cairo @@ -25,14 +25,13 @@ mod KakarotCore { use core::traits::TryInto; use core::zeroable::Zeroable; - use evm::context::Status; use evm::errors::{EVMError, EVMErrorTrait, CALLING_FROM_CA, CALLING_FROM_UNDEPLOYED_ACCOUNT}; - use evm::execution::execute; - use evm::machine::{Machine, MachineTrait}; + use evm::interpreter::{EVMTrait}; use evm::model::account::{Account, AccountType, AccountTrait}; use evm::model::contract_account::{ContractAccountTrait}; use evm::model::eoa::{EOATrait}; - use evm::model::{ExecutionResult, Address, AddressTrait}; + use evm::model::{ExecutionSummary, Address, AddressTrait}; + use evm::model::{Message, Environment}; use evm::state::{State, StateTrait}; use starknet::{ EthAddress, ContractAddress, ClassHash, get_tx_info, get_contract_address, deploy_syscall, @@ -41,6 +40,7 @@ mod KakarotCore { use super::{INVOKE_ETH_CALL_FORBIDDEN}; use super::{StoredAccountType}; use utils::address::compute_contract_address; + use utils::constants; use utils::helpers::{compute_starknet_address, EthAddressExTrait}; use utils::rlp::RLPTrait; @@ -253,20 +253,16 @@ mod KakarotCore { gas_price: u128, value: u256, calldata: Span - ) -> Span { + ) -> (bool, Span) { if !self.is_view() { panic_with_felt252('fn must be called, not invoked'); }; let origin = Address { evm: origin, starknet: self.compute_starknet_address(origin) }; - let result = self.handle_call(:origin, :to, :gas_limit, :gas_price, :value, :calldata); - match result { - Result::Ok(result) => result.return_data, - // TODO: Return the error message as Bytes in the response - // Eliminate all paths of possible panic in logic with relations to the EVM itself. - Result::Err(err) => panic_with_felt252(err.to_string()), - } + let ExecutionSummary{state: _, return_data, address: _, success } = self + .process_transaction(:origin, :to, :gas_limit, :gas_price, :value, :calldata); + (success, return_data) } fn eth_send_transaction( @@ -276,7 +272,7 @@ mod KakarotCore { gas_price: u128, value: u256, calldata: Span - ) -> Span { + ) -> (bool, Span) { let starknet_caller_address = get_caller_address(); let account = IExternallyOwnedAccountDispatcher { contract_address: starknet_caller_address @@ -294,21 +290,10 @@ mod KakarotCore { .expect('Fetching EOA failed'); assert(caller_account_type == AccountType::EOA, 'Caller is not an EOA'); - let mut maybe_exec_result = self - .handle_call(:origin, :to, :gas_limit, :gas_price, :value, :calldata); - match maybe_exec_result { - Result::Ok(mut result) => { - result.state.commit_state().expect('Committing state failed'); - if to.is_none() { - // Overwrite return_data with deployed address - return result.address.evm.to_bytes().span(); - } - result.return_data - }, - // TODO: Return the error message as Bytes in the response - // Eliminate all paths of possible panic in logic with relations to the EVM itself. - Result::Err(err) => panic_with_felt252(err.to_string()), - } + let ExecutionSummary{mut state, return_data, address: _, success } = self + .process_transaction(:origin, :to, :gas_limit, :gas_price, :value, :calldata); + state.commit_state().expect('Committing state failed'); + (success, return_data) } fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { @@ -373,7 +358,7 @@ mod KakarotCore { } - fn handle_call( + fn process_transaction( self: @ContractState, origin: Address, to: Option, @@ -381,12 +366,30 @@ mod KakarotCore { gas_price: u128, value: u256, calldata: Span - ) -> Result { - let (to, is_deploy_tx) = match to { + ) -> ExecutionSummary { + let block_info = starknet::get_block_info().unbox(); + let coinbase = IExternallyOwnedAccountDispatcher { + contract_address: block_info.sequencer_address + } + .evm_address(); + let mut env = Environment { + origin: origin.evm, + gas_price, + chain_id: self.chain_id.read(), + prevrandao: 0, + block_number: block_info.block_number, + block_timestamp: block_info.block_timestamp, + block_gas_limit: constants::BLOCK_GAS_LIMIT, + coinbase, + state: Default::default(), + }; + + let (to, is_deploy_tx, code, calldata) = match to { Option::Some(to) => { let target_starknet_address = self.compute_starknet_address(to); let to = Address { evm: to, starknet: target_starknet_address }; - (to, false) + let code = env.state.get_account(to.evm).code; + (to, false, code, calldata) }, Option::None => { // Deploy tx case. @@ -394,21 +397,27 @@ mod KakarotCore { let to_evm_address = compute_contract_address(origin.evm, origin_nonce); let to_starknet_address = self.compute_starknet_address(to_evm_address); let to = Address { evm: to_evm_address, starknet: to_starknet_address }; - (to, true) + let code = calldata; + let calldata = Default::default().span(); + (to, true, code, calldata) }, }; - let execution_result = execute( - :origin, + let code = env.state.get_account(to.evm).code; + + let message = Message { + caller: origin, target: to, - :calldata, - :value, - :gas_price, - :gas_limit, + gas_limit, + data: calldata, + code, + value, + depth: 0, read_only: false, - :is_deploy_tx, - ); - Result::Ok(execution_result) + should_transfer_value: true, + }; + + EVMTrait::process_message_call(message, env, is_deploy_tx) } } } diff --git a/crates/contracts/src/tests/test_eoa.cairo b/crates/contracts/src/tests/test_eoa.cairo index 5e923eab5..4dd24774c 100644 --- a/crates/contracts/src/tests/test_eoa.cairo +++ b/crates/contracts/src/tests/test_eoa.cairo @@ -27,7 +27,7 @@ mod test_external_owned_account { use evm::model::{Address, AddressTrait, ContractAccountTrait}; use evm::tests::test_utils::{ kakarot_address, evm_address, other_evm_address, other_starknet_address, eoa_address, - chain_id, gas_limit, gas_price + chain_id, tx_gas_limit, gas_price }; use openzeppelin::token::erc20::interface::IERC20CamelDispatcherTrait; use starknet::class_hash::Felt252TryIntoClassHash; @@ -42,7 +42,6 @@ mod test_external_owned_account { #[test] - #[available_gas(2000000000)] fn test_kakarot_address() { let (_, kakarot) = setup_contracts_for_testing(); let kakarot_address = kakarot.contract_address; @@ -53,7 +52,6 @@ mod test_external_owned_account { } #[test] - #[available_gas(2000000000)] fn test_evm_address() { let expected_address: EthAddress = eoa_address(); setup_contracts_for_testing(); @@ -64,7 +62,6 @@ mod test_external_owned_account { } #[test] - #[available_gas(2000000000)] fn test_eoa_upgrade() { setup_contracts_for_testing(); let eoa_contract = deploy_eoa(eoa_address()); @@ -85,7 +82,6 @@ mod test_external_owned_account { } #[test] - #[available_gas(2000000000)] #[should_panic(expected: ('Caller not self', 'ENTRYPOINT_FAILED'))] fn test_eoa_upgrade_from_noncontractaddress() { setup_contracts_for_testing(); @@ -98,7 +94,7 @@ mod test_external_owned_account { } #[test] - #[available_gas(2000000000)] + #[ignore] fn test___execute__() { let (_, kakarot_core) = setup_contracts_for_testing(); @@ -117,11 +113,11 @@ mod test_external_owned_account { let data_get_tx = array![0x6d, 0x4c, 0xe6, 0x3c].span(); // check counter value is 0 before doing inc - let return_data = kakarot_core + let (_, return_data) = kakarot_core .eth_call( origin: evm_address, to: Option::Some(other_evm_address()), - gas_limit: gas_limit(), + gas_limit: tx_gas_limit(), gas_price: gas_price(), value: 0, calldata: data_get_tx @@ -141,11 +137,11 @@ mod test_external_owned_account { eoa_contract.__execute__(array![call]); // check counter value has increased - let return_data = kakarot_core + let (_, return_data) = kakarot_core .eth_call( origin: evm_address, to: Option::Some(other_evm_address()), - gas_limit: gas_limit(), + gas_limit: tx_gas_limit(), gas_price: gas_price(), value: 0, calldata: data_get_tx @@ -155,7 +151,6 @@ mod test_external_owned_account { } #[test] - #[available_gas(2000000000)] #[should_panic(expected: ('calls length is not 1', 'ENTRYPOINT_FAILED'))] fn test___execute___should_fail_with_zero_calls() { setup_contracts_for_testing(); @@ -169,7 +164,6 @@ mod test_external_owned_account { } #[test] - #[available_gas(2000000000)] #[should_panic(expected: ('Caller not 0', 'ENTRYPOINT_FAILED'))] fn test___validate__fail__caller_not_0() { let (_, kakarot_core) = setup_contracts_for_testing(); @@ -184,7 +178,6 @@ mod test_external_owned_account { } #[test] - #[available_gas(2000000000)] #[should_panic(expected: ('call len is not 1', 'ENTRYPOINT_FAILED'))] fn test___validate__fail__call_data_len_not_1() { let (_, kakarot_core) = setup_contracts_for_testing(); @@ -199,7 +192,7 @@ mod test_external_owned_account { } #[test] - #[available_gas(2000000000)] + #[ignore] #[should_panic(expected: ('to is not kakarot core', 'ENTRYPOINT_FAILED'))] fn test___validate__fail__to_address_not_kakarot_core() { let (_, kakarot_core) = setup_contracts_for_testing(); @@ -219,7 +212,6 @@ mod test_external_owned_account { } #[test] - #[available_gas(2000000000)] #[should_panic( expected: ("Validate: selector must be eth_send_transaction", 'ENTRYPOINT_FAILED') )] @@ -239,7 +231,6 @@ mod test_external_owned_account { } #[test] - #[available_gas(2000000000)] fn test___validate__legacy_transaction() { let (_, kakarot_core) = setup_contracts_for_testing(); let evm_address: EthAddress = 0x6Bd85F39321B00c6d603474C5B2fddEB9c92A466_u256.into(); @@ -269,7 +260,6 @@ mod test_external_owned_account { } #[test] - #[available_gas(2000000000)] fn test___validate__eip_2930_transaction() { let (_, kakarot_core) = setup_contracts_for_testing(); let evm_address: EthAddress = 0x6Bd85F39321B00c6d603474C5B2fddEB9c92A466_u256.into(); @@ -300,7 +290,6 @@ mod test_external_owned_account { } #[test] - #[available_gas(2000000000)] fn test___validate__eip_1559_transaction() { let (_, kakarot_core) = setup_contracts_for_testing(); let evm_address: EthAddress = 0x6Bd85F39321B00c6d603474C5B2fddEB9c92A466_u256.into(); diff --git a/crates/contracts/src/tests/test_kakarot_core.cairo b/crates/contracts/src/tests/test_kakarot_core.cairo index 7426c6ff1..99031a3c6 100644 --- a/crates/contracts/src/tests/test_kakarot_core.cairo +++ b/crates/contracts/src/tests/test_kakarot_core.cairo @@ -24,12 +24,13 @@ use core::option::OptionTrait; use core::traits::TryInto; -use evm::machine::Status; use evm::model::contract_account::ContractAccountTrait; use evm::model::{AccountType, Address}; use evm::tests::test_utils; use starknet::{testing, contract_address_const, ContractAddress, EthAddress, ClassHash}; use utils::helpers::{EthAddressExTrait, u256_to_bytes_array}; +//Required for assert_eq! macro +use utils::traits::{EthAddressDebug, ContractAddressDebug}; #[test] fn test_kakarot_core_owner() { @@ -138,13 +139,14 @@ fn test_kakarot_core_eoa_mapping() { } #[test] +#[ignore] fn test_kakarot_core_compute_starknet_address() { let evm_address = test_utils::evm_address(); let (_, kakarot_core) = contract_utils::setup_contracts_for_testing(); let expected_starknet_address = kakarot_core.deploy_eoa(evm_address); let actual_starknet_address = kakarot_core.compute_starknet_address(evm_address); - assert(actual_starknet_address == expected_starknet_address, 'wrong starknet address'); + assert_eq!(actual_starknet_address, expected_starknet_address); } #[test] @@ -232,6 +234,7 @@ fn test_kakarot_contract_account_false_positive_jumpdest() { } #[test] +#[ignore] fn test_eth_send_transaction() { // Given let (_, kakarot_core) = contract_utils::setup_contracts_for_testing(); @@ -244,7 +247,7 @@ fn test_eth_send_transaction() { ); let to = Option::Some(test_utils::other_evm_address()); - let gas_limit = test_utils::gas_limit(); + let gas_limit = test_utils::tx_gas_limit(); let gas_price = test_utils::gas_price(); let value = 0; @@ -253,7 +256,7 @@ fn test_eth_send_transaction() { let data_get_tx = array![0x6d, 0x4c, 0xe6, 0x3c].span(); // check counter value is 0 before doing inc - let return_data = kakarot_core + let (_, return_data) = kakarot_core .eth_call( origin: evm_address, to: Option::Some(account.evm), @@ -278,7 +281,7 @@ fn test_eth_send_transaction() { let calldata = array![0x6d, 0x4c, 0xe6, 0x3c].span(); // When - let return_data = kakarot_core + let (_, return_data) = kakarot_core .eth_call(origin: evm_address, :to, :gas_limit, :gas_price, :value, :calldata); // Then @@ -286,6 +289,7 @@ fn test_eth_send_transaction() { } #[test] +#[ignore] fn test_eth_call() { // Given let (_, kakarot_core) = contract_utils::setup_contracts_for_testing(); @@ -300,14 +304,14 @@ fn test_eth_call() { counter.set_storage_at(0, 1); let to = Option::Some(test_utils::other_evm_address()); - let gas_limit = test_utils::gas_limit(); + let gas_limit = test_utils::tx_gas_limit(); let gas_price = test_utils::gas_price(); let value = 0; // selector: function get() let calldata = array![0x6d, 0x4c, 0xe6, 0x3c].span(); // When - let return_data = kakarot_core + let (_, return_data) = kakarot_core .eth_call(origin: evm_address, :to, :gas_limit, :gas_price, :value, :calldata); // Then @@ -315,7 +319,8 @@ fn test_eth_call() { } #[test] -fn test_handle_call() { +#[ignore] +fn test_process_transaction() { // Given let (_, kakarot_core) = contract_utils::setup_contracts_for_testing(); @@ -327,7 +332,7 @@ fn test_handle_call() { ); let to = Option::Some(test_utils::other_evm_address()); - let gas_limit = test_utils::gas_limit(); + let gas_limit = test_utils::tx_gas_limit(); let gas_price = test_utils::gas_price(); let value = 0; // selector: function get() @@ -336,24 +341,24 @@ fn test_handle_call() { // When let mut kakarot_core = KakarotCore::unsafe_new_contract_state(); let result = kakarot_core - .handle_call( + .process_transaction( origin: Address { evm: evm_address, starknet: eoa }, :to, :gas_limit, :gas_price, :value, :calldata - ) - .expect('handle_call failed'); + ); let return_data = result.return_data; - assert(result.status == Status::Stopped, 'wrong status'); + assert!(result.success); // Then assert(return_data == u256_to_bytes_array(0).span(), 'wrong result'); } #[test] +#[ignore] fn test_eth_send_transaction_deploy_tx() { // Given let (_, kakarot_core) = contract_utils::setup_contracts_for_testing(); @@ -362,14 +367,14 @@ fn test_eth_send_transaction_deploy_tx() { let eoa = kakarot_core.deploy_eoa(evm_address); let to = Option::None; - let gas_limit = test_utils::gas_limit(); + let gas_limit = test_utils::tx_gas_limit(); let gas_price = test_utils::gas_price(); let value = 0; // When // Set the contract address to the EOA address, so that the caller of the `eth_send_transaction` is an eoa testing::set_contract_address(eoa); - let deploy_result = kakarot_core + let (_, deploy_result) = kakarot_core .eth_send_transaction( :to, :gas_limit, :gas_price, :value, calldata: deploy_counter_calldata() ); @@ -394,7 +399,7 @@ fn test_eth_send_transaction_deploy_tx() { let to = Option::Some(expected_address); // No need to set address back to eoa, as eth_call doesn't use the caller address. - let result = kakarot_core + let (_, result) = kakarot_core .eth_call(origin: evm_address, :to, :gas_limit, :gas_price, :value, :calldata); // Then assert(result == u256_to_bytes_array(0).span(), 'wrong result'); diff --git a/crates/evm/src/call_helpers.cairo b/crates/evm/src/call_helpers.cairo index be1935dde..6bb652d05 100644 --- a/crates/evm/src/call_helpers.cairo +++ b/crates/evm/src/call_helpers.cairo @@ -3,15 +3,12 @@ use cmp::min; use contracts::kakarot_core::KakarotCore; use contracts::kakarot_core::interface::IKakarotCore; -use evm::context::{ - ExecutionContext, Status, CallContext, CallContextTrait, ExecutionContextType, - ExecutionContextTrait -}; use evm::errors::{EVMError, CALL_GAS_GT_GAS_LIMIT, ACTIVE_MACHINE_STATE_IN_CALL_FINALIZATION}; -use evm::machine::{Machine, MachineTrait}; +use evm::interpreter::EVMTrait; use evm::memory::MemoryTrait; use evm::model::account::{AccountTrait}; -use evm::model::{Transfer, Address}; +use evm::model::vm::{VM, VMTrait}; +use evm::model::{Transfer, Address, Message}; use evm::stack::StackTrait; use evm::state::StateTrait; use starknet::{EthAddress, get_contract_address}; @@ -30,6 +27,7 @@ struct CallArgs { calldata: Span, ret_offset: usize, ret_size: usize, + read_only: bool, should_transfer: bool, } @@ -42,17 +40,17 @@ enum CallType { } #[generate_trait] -impl MachineCallHelpersImpl of MachineCallHelpers { +impl CallHelpersImpl of CallHelpers { /// Prepare the initialization of a new child or so-called sub-context /// As part of the CALL family of opcodes. - fn prepare_call(ref self: Machine, call_type: @CallType) -> Result { + fn prepare_call(ref self: VM, call_type: @CallType) -> Result { let gas = self.stack.pop_u128()?; let code_address = self.stack.pop_eth_address()?; let to = match call_type { CallType::Call => code_address, - CallType::DelegateCall => self.address().evm, - CallType::CallCode => self.address().evm, + CallType::DelegateCall => self.message().target.evm, + CallType::CallCode => self.message().target.evm, CallType::StaticCall => code_address }; @@ -64,18 +62,17 @@ impl MachineCallHelpersImpl of MachineCallHelpers { let to = Address { evm: to, starknet: kakarot_core.compute_starknet_address(to) }; - let (value, should_transfer) = match call_type { - CallType::Call => (self.stack.pop()?, true), - CallType::DelegateCall => (self.value(), false), - CallType::CallCode => (self.stack.pop()?, false), - CallType::StaticCall => (0, false), - }; - - let caller = match call_type { - CallType::Call => self.address(), - CallType::DelegateCall => self.call_ctx().caller, - CallType::CallCode => self.address(), - CallType::StaticCall => self.address(), + let (value, caller, should_transfer, read_only) = match call_type { + CallType::Call => ( + self.stack.pop()?, self.message().target, true, self.message().read_only + ), + CallType::DelegateCall => ( + self.message().value, self.message().caller, false, self.message().read_only + ), + CallType::CallCode => ( + self.stack.pop()?, self.message().target, false, self.message().read_only + ), + CallType::StaticCall => (0, self.message().target, false, true), }; let args_offset = self.stack.pop_usize()?; @@ -97,7 +94,8 @@ impl MachineCallHelpersImpl of MachineCallHelpers { calldata: calldata.span(), ret_offset, ret_size, - should_transfer + should_transfer, + read_only, } ) } @@ -106,97 +104,51 @@ impl MachineCallHelpersImpl of MachineCallHelpers { /// The Machine will change its `current_ctx` to point to the /// newly created sub-context. /// Then, the EVM execution loop will start on this new execution context. - fn init_call_sub_ctx( - ref self: Machine, call_args: CallArgs, read_only: bool - ) -> Result<(), EVMError> { - if call_args.should_transfer && call_args.value > 0 { - let transfer = Transfer { - sender: self.address(), recipient: call_args.to, amount: call_args.value, - }; - let result = self.state.add_transfer(transfer); - if result.is_err() { - self.stack.push(0)?; - return Result::Ok(()); - } - } - - // Case 1: `to` address is a precompile - // Handle precompile logic - if is_precompile(call_args.to.evm) { - panic_with_felt252('precompiles not implemented'); - } + fn generic_call(ref self: VM, call_args: CallArgs) -> Result<(), EVMError> { + // check if depth is too high // Case 2: `to` address is not a precompile // We enter the standard flow - let bytecode = self.state.get_account(call_args.code_address.evm).code; - - let call_ctx = CallContextTrait::new( - call_args.caller, - bytecode, - call_args.calldata, - call_args.value, - read_only, - call_args.gas, - self.gas_price(), - call_args.ret_offset, - call_args.ret_size, - ); - - let parent_ctx = NullableTrait::new(self.current_ctx.unbox()); - let child_ctx = ExecutionContextTrait::new( - ExecutionContextType::Call(self.ctx_count), - call_args.to, - call_ctx, - parent_ctx, - Default::default().span() - ); - - // Machine logic - self.ctx_count += 1; - self.current_ctx = BoxTrait::new(child_ctx); - - Result::Ok(()) - } - - /// Finalize the calling context by: - /// - Pushing the execution status to the Stack - /// - Set the return data of the parent context - /// - Store the return data in Memory - /// - Return to parent context. - fn finalize_calling_context(ref self: Machine) -> Result<(), EVMError> { - // Put the status of the call on the stack. - let status = self.status(); - let success = match status { - Status::Active => { - return Result::Err( - EVMError::InvalidMachineState(ACTIVE_MACHINE_STATE_IN_CALL_FINALIZATION) - ); - }, - Status::Stopped => 1, - Status::Reverted => 0, + let code = self.env.state.get_account(call_args.code_address.evm).code; + self.return_data = Default::default().span(); + let message = Message { + caller: call_args.caller, + target: call_args.to, + gas_limit: call_args.gas, + value: call_args.value, + read_only: call_args.read_only, + should_transfer_value: call_args.should_transfer, + data: call_args.calldata, + code, + depth: self.message().depth + 1 }; - self.stack.push(success)?; - // Get the return_data of the parent context. - let return_data = self.return_data(); + let result = EVMTrait::process_message(message, ref self.env); + + self.return_data = result.return_data; + self.gas_used += result.gas_used; + if result.success { + self.stack.push(1)?; + } else { + self.stack.push(0)?; + } // Get the min between len(return_data) and call_ctx.ret_size. - let call_ctx = self.call_ctx(); - let return_data_len = min(return_data.len(), call_ctx.ret_size); + let actual_returndata_len = min(result.return_data.len(), call_args.ret_size); - let return_data = return_data.slice(0, return_data_len); - self.memory.store_n(return_data, call_ctx.ret_offset); + let actual_return_data = result.return_data.slice(0, actual_returndata_len); + // TODO: Check if need to pad the memory with zeroes if result.return_data.len() < call_ctx.ret_size and memory is not empty at + // offset call_args.ret_offset + result.return_data.len() + self.memory.store_n(actual_return_data, call_args.ret_offset); - // Return from the current sub ctx by setting the execution context - // to the parent context. - self.return_to_parent_ctx() + Result::Ok(()) } } -/// Check whether a `to` address for a call-family opcode is a precompile. -fn is_precompile(to: EthAddress) -> bool { - let to: felt252 = to.into(); - if to.into() < 0x10_u256 { +/// Check whether an address for a call-family opcode is a precompile. +fn is_precompile(self: EthAddress) -> bool { + let self: felt252 = self.into(); + if self.into() < 0x10_u256 { return true; } false diff --git a/crates/evm/src/context.cairo b/crates/evm/src/context.cairo deleted file mode 100644 index 36754f284..000000000 --- a/crates/evm/src/context.cairo +++ /dev/null @@ -1,378 +0,0 @@ -use evm::errors::EVMError; -use evm::memory::{Memory, MemoryTrait}; -use evm::model::Address; -use evm::model::Event; -use evm::stack::{Stack, StackTrait}; -use starknet::get_caller_address; -use starknet::{EthAddress, ContractAddress}; -use utils::helpers::{ArrayExtension, ArrayExtTrait}; -use utils::traits::{SpanDefault, EthAddressDefault, ContractAddressDefault}; - -#[derive(Drop, Default, Copy, PartialEq)] -enum Status { - #[default] - Active, - Stopped, - Reverted -} - -// ************************************************************************* -// CallContext -// ************************************************************************* -// We should not directly access the fields of the call context; -// instead we should use the methods defined in the trait. -// This is not enforced until there are `pub` and `priv` visibility on struct fields. - -/// The call context. -#[derive(Drop, Copy, Default)] -struct CallContext { - caller: Address, - /// The bytecode to execute. - bytecode: Span, - /// The call data. - calldata: Span, - /// Amount of native token to transfer. - value: u256, - // If the call is read only (cannot modify the state of the chain) - read_only: bool, - // Evm gas limit for the call - gas_limit: u128, - // Evm gas price for the call - gas_price: u128, - // The offset in memory to store the context return - ret_offset: usize, - // The size in memory to store the context return - ret_size: usize, -} - -#[generate_trait] -impl CallContextImpl of CallContextTrait { - #[inline(always)] - fn new( - caller: Address, - bytecode: Span, - calldata: Span, - value: u256, - read_only: bool, - gas_limit: u128, - gas_price: u128, - ret_offset: usize, - ret_size: usize, - ) -> CallContext { - CallContext { - caller, - bytecode, - calldata, - value, - read_only, - gas_limit, - gas_price, - ret_offset, - ret_size, - } - } - - - #[inline(always)] - fn caller(self: @CallContext) -> Address { - *self.caller - } - - - #[inline(always)] - fn bytecode(self: @CallContext) -> Span { - *self.bytecode - } - - #[inline(always)] - fn calldata(self: @CallContext) -> Span { - *self.calldata - } - - #[inline(always)] - fn value(self: @CallContext) -> u256 { - *self.value - } - - #[inline(always)] - fn read_only(self: @CallContext) -> bool { - *self.read_only - } - - #[inline(always)] - fn gas_limit(self: @CallContext) -> u128 { - *self.gas_limit - } - - #[inline(always)] - fn gas_price(self: @CallContext) -> u128 { - *self.gas_price - } -} - -impl DefaultBoxCallContext of Default> { - fn default() -> Box { - let call_ctx: CallContext = Default::default(); - BoxTrait::new(call_ctx) - } -} - -impl DefaultOptionSpanU8 of Default>> { - fn default() -> Option> { - Option::None - } -} - - -// ************************************************************************* -// ExecutionContext -// ************************************************************************* - -/// The execution context. -/// Stores all data relevant to the current execution context. -#[derive(Drop, Default)] -struct ExecutionContext { - ctx_type: ExecutionContextType, - address: Address, - program_counter: u32, - status: Status, - call_ctx: Box, - // Return data of a child context. - return_data: Span, - parent_ctx: Nullable, - gas_used: u128, -} - - -type IsCreate = bool; -/// In the case of call and create, the execution context requires an id number -/// to access their respective Stack and Memory; while the Root context always has -/// id equal to 0. -/// A context is either: the root, a call sub-context or a create sub-context. -#[derive(Drop, Default, Copy, PartialEq)] -enum ExecutionContextType { - #[default] - Root: IsCreate, - Call: usize, - Create: usize -} - -impl DefaultBoxExecutionContext of Default> { - fn default() -> Box { - let context: ExecutionContext = Default::default(); - BoxTrait::new(context) - } -} - - -/// `ExecutionContext` implementation. - -#[generate_trait] -impl ExecutionContextImpl of ExecutionContextTrait { - /// Create a new execution context instance. - #[inline(always)] - fn new( - ctx_type: ExecutionContextType, - address: Address, - call_ctx: CallContext, - parent_ctx: Nullable, - return_data: Span, - ) -> ExecutionContext { - ExecutionContext { - ctx_type, - address, - program_counter: Default::default(), - status: Default::default(), - call_ctx: BoxTrait::new(call_ctx), - return_data, - parent_ctx, - gas_used: Default::default(), - } - } - - // ************************************************************************* - // DynamicContext getters - // ************************************************************************* - - #[inline(always)] - fn reverted(self: @ExecutionContext) -> bool { - if (*self.status == Status::Reverted) { - return true; - } - false - } - - #[inline(always)] - fn stopped(self: @ExecutionContext) -> bool { - // A context is considered stopped if it has status Stopped or Reverted - if (*self.status == Status::Active) { - return false; - } - true - } - - #[inline(always)] - fn status(self: @ExecutionContext) -> Status { - *self.status - } - - #[inline(always)] - fn call_ctx(self: @ExecutionContext) -> CallContext { - (*self.call_ctx).unbox() - } - - #[inline(always)] - fn return_data(self: @ExecutionContext) -> Span { - *self.return_data - } - - /// Stops the current execution context. - #[inline(always)] - fn set_stopped(ref self: ExecutionContext) { - self.status = Status::Stopped; - } - - #[inline(always)] - fn gas_used(self: @ExecutionContext) -> u128 { - *self.gas_used - } - - #[inline(always)] - fn increment_gas_used_unchecked(ref self: ExecutionContext, value: u128) { - self.gas_used += value; - } - - /// Increments the gas_used field of the current execution context by the value amount. - /// # Error : returns `EVMError::OutOfGas` if gas_used + new_gas >= limit - #[inline(always)] - fn increment_gas_used_checked(ref self: ExecutionContext, value: u128) -> Result<(), EVMError> { - let new_gas_used = self.gas_used() + value; - if (new_gas_used >= self.call_ctx().gas_limit()) { - return Result::Err(EVMError::OutOfGas); - } - self.gas_used = new_gas_used; - Result::Ok(()) - } - - /// Revert the current execution context. - /// - /// When the execution context is reverted, no more instructions can be executed - /// (it is stopped) and contract creation and contract storage writes are - /// reverted on its finalization. - #[inline(always)] - fn set_reverted(ref self: ExecutionContext) { - self.status = Status::Reverted; - } - - // ************************************************************************* - // StaticExecutionContext getters - // ************************************************************************* - - /// Getter for the currently executing account address - #[inline(always)] - fn address(self: @ExecutionContext) -> Address { - *self.address - } - - // ************************************************************************* - // ExecutionContext methods - // ************************************************************************* - - /// Reads and return data from bytecode. - /// The program counter is incremented accordingly. - /// - /// # Arguments - /// - /// * `self` - The `ExecutionContext` instance to read the data from. - /// * `len` - The length of the data to read from the bytecode. - #[inline(always)] - fn read_code(self: @ExecutionContext, len: usize) -> Span { - // Copy code slice from [pc, pc+len] - let code = (*self.call_ctx).unbox().bytecode().slice(self.pc(), len); - - code - } - - /// Returns the read only field for the current call context - /// - /// # Arguments - /// - /// * `self` - The `ExecutionContext` instance to read the data from. - #[inline(always)] - fn read_only(self: @ExecutionContext) -> bool { - self.call_ctx().read_only() - } - - #[inline(always)] - fn is_call(self: @ExecutionContext) -> bool { - match *self.ctx_type { - ExecutionContextType::Root(_) => false, - ExecutionContextType::Call(_) => true, - ExecutionContextType::Create(_) => false, - } - } - - #[inline(always)] - fn is_root(self: @ExecutionContext) -> bool { - match *self.ctx_type { - ExecutionContextType::Root(_) => true, - ExecutionContextType::Call(_) => false, - ExecutionContextType::Create(_) => false, - } - } - - #[inline(always)] - fn is_create(self: @ExecutionContext) -> bool { - match *self.ctx_type { - ExecutionContextType::Root(is_create) => is_create, - ExecutionContextType::Call(_) => false, - ExecutionContextType::Create(_) => true, - } - } - - #[inline(always)] - fn ctx_type(self: @ExecutionContext) -> ExecutionContextType { - *self.ctx_type - } - - #[inline(always)] - fn id(self: @ExecutionContext) -> usize { - match *self.ctx_type { - ExecutionContextType::Root(_) => 0, - ExecutionContextType::Call(id) => id, - ExecutionContextType::Create(id) => id, - } - } - - // TODO: Implement print_debug - /// Debug print the execution context. - #[inline(always)] - fn print_debug(ref self: ExecutionContext) { // debug::print_felt252('gas used'); - // self.gas_used.print(); - } - - #[inline(always)] - fn set_pc(ref self: ExecutionContext, value: u32) { - self.program_counter = value; - } - - #[inline(always)] - fn pc(self: @ExecutionContext) -> u32 { - *self.program_counter - } - - fn origin(self: @ExecutionContext) -> Address { - if (self.is_root()) { - return self.call_ctx().caller(); - } - // If the current execution context is not root, then it MUST have a parent_context - // We're able to deref the nullable pointer without risk of panic - let mut parent_context = self.parent_ctx.as_snapshot().deref(); - - // Entering a recursion - let origin = parent_context.origin(); - - // Return self.call_context().caller() where self is the root context - origin - } -} diff --git a/crates/evm/src/create_helpers.cairo b/crates/evm/src/create_helpers.cairo index c38da8f76..267f16acd 100644 --- a/crates/evm/src/create_helpers.cairo +++ b/crates/evm/src/create_helpers.cairo @@ -1,20 +1,21 @@ //! CREATE, CREATE2 opcode helpers use cmp::min; -use evm::context::{ - ExecutionContext, Status, CallContext, CallContextTrait, ExecutionContextType, - ExecutionContextTrait -}; +use contracts::kakarot_core::KakarotCore; +use contracts::kakarot_core::interface::IKakarotCore; use evm::errors::{EVMError, CALL_GAS_GT_GAS_LIMIT, ACTIVE_MACHINE_STATE_IN_CALL_FINALIZATION}; -use evm::machine::{Machine, MachineTrait}; +use evm::interpreter::EVMTrait; use evm::memory::MemoryTrait; +use evm::model::ExecutionSummary; use evm::model::account::{AccountTrait}; use evm::model::contract_account::{ContractAccountTrait}; -use evm::model::{Address, AccountType, Transfer}; +use evm::model::vm::{VM, VMTrait}; +use evm::model::{Message, Address, AccountType, Transfer}; use evm::stack::StackTrait; use evm::state::StateTrait; use keccak::cairo_keccak; use starknet::{EthAddress, get_tx_info}; use utils::address::{compute_contract_address, compute_create2_contract_address}; +use utils::constants; use utils::helpers::ArrayExtTrait; use utils::helpers::{ResultExTrait, EthAddressExTrait, U256Trait, U8SpanExTrait}; use utils::traits::{ @@ -31,15 +32,15 @@ struct CreateArgs { #[derive(Drop)] enum CreateType { - CreateOrDeployTx, + Create, Create2, } #[generate_trait] -impl MachineCreateHelpersImpl of MachineCreateHelpers { +impl CreateHelpersImpl of CreateHelpers { /// Prepare the initialization of a new child or so-called sub-context /// As part of the CREATE family of opcodes. - fn prepare_create(ref self: Machine, create_type: CreateType) -> Result { + fn prepare_create(ref self: VM, create_type: CreateType) -> Result { let value = self.stack.pop()?; let offset = self.stack.pop_usize()?; let size = self.stack.pop_usize()?; @@ -48,12 +49,12 @@ impl MachineCreateHelpersImpl of MachineCreateHelpers { self.memory.load_n(size, ref bytecode, offset); let to = match create_type { - CreateType::CreateOrDeployTx => { - let nonce = self.state.get_account(self.address().evm).nonce(); - compute_contract_address(self.address().evm, sender_nonce: nonce) + CreateType::Create => { + let nonce = self.env.state.get_account(self.message().target.evm).nonce(); + compute_contract_address(self.message().target.evm, sender_nonce: nonce) }, CreateType::Create2 => compute_create2_contract_address( - self.address().evm, salt: self.stack.pop()?, bytecode: bytecode.span() + self.message().target.evm, salt: self.stack.pop()?, bytecode: bytecode.span() )?, }; @@ -65,38 +66,23 @@ impl MachineCreateHelpersImpl of MachineCreateHelpers { /// The Machine will change its `current_ctx` to point to the /// newly created sub-context. /// Then, the EVM execution loop will start on this new execution context. - fn init_create_sub_ctx(ref self: Machine, create_args: CreateArgs) -> Result<(), EVMError> { - let mut target_account = self.state.get_account(create_args.to); + fn generic_create(ref self: VM, create_args: CreateArgs) -> Result<(), EVMError> { + let mut target_account = self.env.state.get_account(create_args.to); let target_address = target_account.address(); + //TODO(gas) charge max message call gas + // The caller in the subcontext is the calling context's current address - let caller = self.address(); - let mut caller_account = self.state.get_account(caller.evm); + let caller = self.message().target; + let mut caller_account = self.env.state.get_account(caller.evm); let caller_current_nonce = caller_account.nonce(); let caller_balance = caller_account.balance(); if caller_balance < create_args.value - || target_account.nonce() == integer::BoundedInt::::max() { + || target_account.nonce() == integer::BoundedInt::::max() + || self.message.depth + + 1 == constants::STACK_MAX_DEPTH { return self.stack.push(0); } - let maybe_transfer = if create_args.value > 0 { - Option::Some( - Transfer { - sender: self.address(), recipient: target_address, amount: create_args.value, - } - ) - } else { - Option::None - }; - - caller_account.set_nonce(caller_current_nonce + 1); - self.state.set_account(caller_account); - - //TODO when compiler bug is fixed handle this properly. - // It needs to be after self.set_current_ctx(child_ctx); - match maybe_transfer { - Option::Some(transfer) => { self.state.add_transfer(transfer).expect('transfer'); }, - Option::None => {} - }; // Collision happens if the target account loaded in state has code or nonce set, meaning // - it's deployed on SN and is an active EVM contract @@ -105,78 +91,31 @@ impl MachineCreateHelpersImpl of MachineCreateHelpers { return self.stack.push(0); }; - target_account.set_nonce(1); - target_account.set_type(AccountType::ContractAccount); - target_account.address = target_address; - self.state.set_account(target_account); + //TODO(gas) ensure calldata_len <= 2*MAX_CODE_SIZE + + caller_account.set_nonce(caller_current_nonce + 1); + self.env.state.set_account(caller_account); - let call_ctx = CallContextTrait::new( + let child_message = Message { caller, - create_args.bytecode, - calldata: Default::default().span(), + target: target_address, value: create_args.value, + should_transfer_value: true, + code: create_args.bytecode, + data: Default::default().span(), + gas_limit: self.message().gas_limit, + depth: self.message().depth + 1, read_only: false, - gas_limit: self.gas_limit(), - gas_price: self.gas_price(), - ret_offset: 0, - ret_size: 0, - ); - - let parent_ctx = NullableTrait::new(self.current_ctx.unbox()); - let child_ctx = ExecutionContextTrait::new( - ExecutionContextType::Create(self.ctx_count), - target_address, - call_ctx, - parent_ctx, - Default::default().span() - ); - - // Machine logic - self.ctx_count += 1; - - // Satisfy the compiler by setting the current_ctx to a default value - // before setting it to its real value - otherwise, "variable moved" - //TODO find workaround - self.current_ctx = BoxTrait::new(Default::default()); - self.set_current_ctx(child_ctx); + }; - Result::Ok(()) - } + let result = EVMTrait::process_create_message(child_message, ref self.env); - /// Finalize the create context by: - /// - Pushing the deployed contract's address (success) to the Stack or 0 (failure) - /// - Set the return data of the parent context - /// - Store the bytecode (subcontext's return data) of the newly deployed contract account - /// - Return to parent context. - fn finalize_create_context(ref self: Machine) -> Result<(), EVMError> { - // Put the status of the call on the stack. - let status = self.status(); - let account_address = self.address().evm; - match status { - Status::Active => { - return Result::Err( - EVMError::InvalidMachineState(ACTIVE_MACHINE_STATE_IN_CALL_FINALIZATION) - ); - }, - // Success - Status::Stopped => { - let mut return_data = self.return_data(); - - let mut account = self.state.get_account(account_address); - account.set_code(return_data); - assert( - account.account_type == AccountType::ContractAccount, - 'type should be CA in finalize' - ); - self.state.set_account(account); - self.return_to_parent_ctx()?; - self.stack.push(account_address.into()) - }, - // Failure - Status::Reverted => { - self.return_to_parent_ctx()?; - self.stack.push(0) - }, + if result.success { + self.return_data = Default::default().span(); + self.stack.push(target_address.evm.into())?; + } else { + self.stack.push(0)?; } + Result::Ok(()) } } diff --git a/crates/evm/src/errors.cairo b/crates/evm/src/errors.cairo index 88133ff07..d03143f82 100644 --- a/crates/evm/src/errors.cairo +++ b/crates/evm/src/errors.cairo @@ -63,6 +63,7 @@ enum EVMError { DeployError: felt252, OriginError: felt252, OutOfGas, + Assertion } #[generate_trait] @@ -84,6 +85,7 @@ impl EVMErrorImpl of EVMErrorTrait { EVMError::DeployError(error_message) => error_message, EVMError::OriginError(error_message) => error_message, EVMError::OutOfGas => 'OutOfGas'.into(), + EVMError::Assertion => 'Assertion failed'.into(), } } } diff --git a/crates/evm/src/execution.cairo b/crates/evm/src/execution.cairo deleted file mode 100644 index 58224ed34..000000000 --- a/crates/evm/src/execution.cairo +++ /dev/null @@ -1,108 +0,0 @@ -use evm::context::{ - CallContext, CallContextTrait, ExecutionContext, ExecutionContextType, ExecutionContextTrait, - Status -}; -use evm::errors::{EVMError, EVMErrorTrait, CONTRACT_ACCOUNT_EXISTS}; -use evm::interpreter::EVMInterpreterTrait; -use evm::machine::{Machine, MachineTrait, MachineBuilderTrait}; -use evm::model::account::{AccountTrait}; -use evm::model::{Address, Transfer, ExecutionResult, AccountType}; -use evm::state::{State, StateTrait}; -use starknet::{EthAddress, ContractAddress}; -use utils::helpers::{U256Trait, compute_starknet_address}; - -/// Creates an instance of the EVM to execute a transaction. -/// -/// # Arguments -/// * `origin` - The EVM address of the origin of the transaction. -/// * `target` - The EVM address of the called contract. -/// * `calldata` - The calldata of the execution. -/// * `value` - The value of the execution. -/// * `gas_limit` - The gas limit of the execution. -/// * `gas_price` - The gas price for the execution. -/// * `read_only` - Whether the execution is read only. -/// * `is_deploy_tx` - Whether the execution is a deploy transaction. -/// -/// # Returns -/// * ExecutionResult struct, containing: -/// * The execution status -/// * The return data of the execution. -/// * The destroyed contracts -/// * The created contracts -/// * The events emitted -fn execute( - origin: Address, - target: Address, - mut calldata: Span, - value: u256, - gas_price: u128, - gas_limit: u128, - read_only: bool, - is_deploy_tx: bool, -) -> ExecutionResult { - // Create a new root execution context. - let mut state: State = Default::default(); - - let mut target_account = state.get_account(target.evm); - let (bytecode, calldata) = if is_deploy_tx { - (calldata, array![].span()) - } else { - (target_account.code, calldata) - }; - - let call_ctx = CallContextTrait::new( - caller: origin, - :bytecode, - :calldata, - :value, - :read_only, - :gas_limit, - :gas_price, - ret_offset: 0, - ret_size: 0, - ); - let ctx = ExecutionContextTrait::new( - ctx_type: ExecutionContextType::Root(is_deploy_tx), - address: target, - :call_ctx, - parent_ctx: Default::default(), - return_data: Default::default().span() - ); - - let mut machine = MachineBuilderTrait::new().set_state(state).set_ctx(ctx).build(); - - let transfer = Transfer { sender: origin, recipient: target, amount: value }; - match machine.state.add_transfer(transfer) { - Result::Ok(_) => {}, - Result::Err(err) => { return reverted_with_err(machine, err); } - } - - if is_deploy_tx { - // Check collision - if target_account.has_code_or_nonce() { - return reverted_with_err(machine, EVMError::DeployError(CONTRACT_ACCOUNT_EXISTS)); - } - // Nonce is set to 1 in the case of a deploy tx - target_account.nonce = 1; - target_account.account_type = AccountType::ContractAccount; - machine.state.set_account(target_account); - } - - let mut interpreter = EVMInterpreterTrait::new(); - // Execute the bytecode - interpreter.run(ref machine); - let address = machine.address(); - let status = machine.status(); - let return_data = machine.return_data(); - ExecutionResult { address, status, return_data, state: machine.state } -} - -fn reverted_with_err(mut machine: Machine, error: EVMError) -> ExecutionResult { - let return_data = Into::::into(error.to_string()).to_bytes(); - ExecutionResult { - address: machine.address(), - status: Status::Reverted, - return_data: return_data, - state: machine.state, - } -} diff --git a/crates/evm/src/gas.cairo b/crates/evm/src/gas.cairo index b31a61d62..55eee45b8 100644 --- a/crates/evm/src/gas.cairo +++ b/crates/evm/src/gas.cairo @@ -2,44 +2,48 @@ //! Code is based on alloy project //! Source: -pub const ZERO: u128 = 0; -pub const BASE: u128 = 2; -pub const VERYLOW: u128 = 3; -pub const LOW: u128 = 5; -pub const MID: u128 = 8; -pub const HIGH: u128 = 10; -pub const JUMPDEST: u128 = 1; -pub const SELFDESTRUCT: u128 = 5000; -pub const CREATE: u128 = 32000; -pub const CALLVALUE: u128 = 9000; -pub const NEWACCOUNT: u128 = 25000; -pub const EXP: u128 = 10; -pub const MEMORY: u128 = 3; -pub const LOG: u128 = 375; -pub const LOGDATA: u128 = 8; -pub const LOGTOPIC: u128 = 375; -pub const KECCAK256: u128 = 30; -pub const KECCAK256WORD: u128 = 6; -pub const COPY: u128 = 3; -pub const BLOCKHASH: u128 = 20; -pub const CODEDEPOSIT: u128 = 200; +const ZERO: u128 = 0; +const BASE: u128 = 2; +const VERYLOW: u128 = 3; +const LOW: u128 = 5; +const MID: u128 = 8; +const HIGH: u128 = 10; +const JUMPDEST: u128 = 1; +const SELFDESTRUCT: u128 = 5000; +const CREATE: u128 = 32000; +const CALLVALUE: u128 = 9000; +const NEWACCOUNT: u128 = 25000; +const EXP: u128 = 10; +const MEMORY: u128 = 3; +const LOG: u128 = 375; +const LOGDATA: u128 = 8; +const LOGTOPIC: u128 = 375; +const KECCAK256: u128 = 30; +const KECCAK256WORD: u128 = 6; +const COPY: u128 = 3; +const BLOCKHASH: u128 = 20; +const CODEDEPOSIT: u128 = 200; -pub const SSTORE_SET: u128 = 20000; -pub const SSTORE_RESET: u128 = 5000; -pub const REFUND_SSTORE_CLEARS: u128 = 15000; +const SSTORE_SET: u128 = 20000; +const SSTORE_RESET: u128 = 5000; +const REFUND_SSTORE_CLEARS: u128 = 15000; -pub const TRANSACTION_ZERO_DATA: u128 = 4; -pub const TRANSACTION_NON_ZERO_DATA_INIT: u128 = 16; -pub const TRANSACTION_NON_ZERO_DATA_FRONTIER: u128 = 68; +const TRANSACTION_ZERO_DATA: u128 = 4; +const TRANSACTION_NON_ZERO_DATA_INIT: u128 = 16; +const TRANSACTION_NON_ZERO_DATA_FRONTIER: u128 = 68; // Berlin EIP-2929 constants -pub const ACCESS_LIST_ADDRESS: u128 = 2400; -pub const ACCESS_LIST_STORAGE_KEY: u128 = 1900; -pub const COLD_SLOAD_COST: u128 = 2100; -pub const COLD_ACCOUNT_ACCESS_COST: u128 = 2600; -pub const WARM_STORAGE_READ_COST: u128 = 100; +const ACCESS_LIST_ADDRESS: u128 = 2400; +const ACCESS_LIST_STORAGE_KEY: u128 = 1900; +const COLD_SLOAD_COST: u128 = 2100; +const COLD_ACCOUNT_ACCESS_COST: u128 = 2600; +const WARM_STORAGE_READ_COST: u128 = 100; /// EIP-3860 : Limit and meter initcode -pub const INITCODE_WORD_COST: u128 = 2; +const INITCODE_WORD_COST: u128 = 2; -pub const CALL_STIPEND: u128 = 2300; +const CALL_STIPEND: u128 = 2300; + +fn max_message_call_gas(gas: u128) -> u128 { + gas - (gas / 64) +} diff --git a/crates/evm/src/instructions/block_information.cairo b/crates/evm/src/instructions/block_information.cairo index f53dd3b39..5e2b70ba4 100644 --- a/crates/evm/src/instructions/block_information.cairo +++ b/crates/evm/src/instructions/block_information.cairo @@ -8,9 +8,9 @@ use evm::errors::{ }; use evm::gas; -use evm::machine::{Machine, MachineTrait}; -use evm::model::Account; use evm::model::account::{AccountTrait}; +use evm::model::vm::{VM, VMTrait}; +use evm::model::{Account}; use evm::stack::StackTrait; use evm::state::StateTrait; @@ -26,8 +26,8 @@ impl BlockInformation of BlockInformationTrait { /// 0x40 - BLOCKHASH /// Get the hash of one of the 256 most recent complete blocks. /// # Specification: https://www.evm.codes/#40?fork=shanghai - fn exec_blockhash(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BLOCKHASH)?; + fn exec_blockhash(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BLOCKHASH)?; let block_number = self.stack.pop_u64()?; let current_block = get_block_number(); @@ -55,8 +55,8 @@ impl BlockInformation of BlockInformationTrait { /// 0x41 - COINBASE /// Get the block's beneficiary address. /// # Specification: https://www.evm.codes/#41?fork=shanghai - fn exec_coinbase(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; + fn exec_coinbase(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; let execution_info = get_execution_info_syscall() .map_err(EVMError::SyscallFailed(EXECUTION_INFO_SYSCALL_FAILED))? @@ -72,8 +72,8 @@ impl BlockInformation of BlockInformationTrait { /// 0x42 - TIMESTAMP /// Get the block’s timestamp /// # Specification: https://www.evm.codes/#42?fork=shanghai - fn exec_timestamp(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; + fn exec_timestamp(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; self.stack.push(get_block_timestamp().into()) } @@ -81,16 +81,16 @@ impl BlockInformation of BlockInformationTrait { /// 0x43 - NUMBER /// Get the block number. /// # Specification: https://www.evm.codes/#43?fork=shanghai - fn exec_number(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; + fn exec_number(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; self.stack.push(get_block_number().into()) } /// 0x44 - PREVRANDAO /// # Specification: https://www.evm.codes/#44?fork=shanghai - fn exec_prevrandao(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; + fn exec_prevrandao(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; // PREVRANDAO does not exist in Starknet // PREVRANDAO used to be DIFFICULTY, which returns 0 for non-POW chains @@ -98,19 +98,19 @@ impl BlockInformation of BlockInformationTrait { } /// 0x45 - GASLIMIT - /// Get gas limit + /// Get the block’s gas limit /// # Specification: https://www.evm.codes/#45?fork=shanghai - fn exec_gaslimit(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; + fn exec_gaslimit(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; - self.stack.push(self.gas_limit().into()) + self.stack.push(self.env.block_gas_limit.into()) } /// 0x46 - CHAINID /// Get the chain ID. /// # Specification: https://www.evm.codes/#46?fork=shanghai - fn exec_chainid(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; + fn exec_chainid(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; let kakarot_state = KakarotCore::unsafe_new_contract_state(); let chain_id = kakarot_state.chain_id(); @@ -120,12 +120,12 @@ impl BlockInformation of BlockInformationTrait { /// 0x47 - SELFBALANCE /// Get balance of currently executing contract /// # Specification: https://www.evm.codes/#47?fork=shanghai - fn exec_selfbalance(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::LOW)?; + fn exec_selfbalance(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::LOW)?; - let evm_address = self.address().evm; + let evm_address = self.message().target.evm; - let balance = self.state.get_account(evm_address).balance; + let balance = self.env.state.get_account(evm_address).balance; self.stack.push(balance) } @@ -133,11 +133,11 @@ impl BlockInformation of BlockInformationTrait { /// 0x48 - BASEFEE /// Get base fee. /// # Specification: https://www.evm.codes/#48?fork=shanghai - fn exec_basefee(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; + fn exec_basefee(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; // Get the current base fee. (Kakarot doesn't use EIP 1559 so basefee // doesn't really exists there so we just use the gas price) - self.stack.push(self.gas_price().into()) + self.stack.push(self.env.gas_price.into()) } } diff --git a/crates/evm/src/instructions/comparison_operations.cairo b/crates/evm/src/instructions/comparison_operations.cairo index e362917e7..a663d6cba 100644 --- a/crates/evm/src/instructions/comparison_operations.cairo +++ b/crates/evm/src/instructions/comparison_operations.cairo @@ -1,8 +1,8 @@ use evm::errors::EVMError; use evm::errors::STACK_UNDERFLOW; use evm::gas; +use evm::model::vm::{VM, VMTrait}; // Internal imports -use evm::machine::{Machine, MachineTrait}; use evm::stack::StackTrait; use integer::BoundedInt; use utils::constants::{POW_2_127}; @@ -14,8 +14,8 @@ use utils::traits::BoolIntoNumeric; impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait { /// 0x10 - LT /// # Specification: https://www.evm.codes/#10?fork=shanghai - fn exec_lt(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::VERYLOW)?; + fn exec_lt(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; let popped = self.stack.pop_n(2)?; let a = *popped[0]; let b = *popped[1]; @@ -25,8 +25,8 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait { /// 0x11 - GT /// # Specification: https://www.evm.codes/#11?fork=shanghai - fn exec_gt(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::VERYLOW)?; + fn exec_gt(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; let popped = self.stack.pop_n(2)?; let a = *popped[0]; let b = *popped[1]; @@ -37,8 +37,8 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait { /// 0x12 - SLT /// # Specification: https://www.evm.codes/#12?fork=shanghai - fn exec_slt(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::VERYLOW)?; + fn exec_slt(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; let a: i256 = self.stack.pop_i256()?; let b: i256 = self.stack.pop_i256()?; let result: u256 = (a < b).into(); @@ -47,8 +47,8 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait { /// 0x13 - SGT /// # Specification: https://www.evm.codes/#13?fork=shanghai - fn exec_sgt(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::VERYLOW)?; + fn exec_sgt(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; let a: i256 = self.stack.pop_i256()?; let b: i256 = self.stack.pop_i256()?; let result: u256 = (a > b).into(); @@ -58,8 +58,8 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait { /// 0x14 - EQ /// # Specification: https://www.evm.codes/#14?fork=shanghai - fn exec_eq(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::VERYLOW)?; + fn exec_eq(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; let popped = self.stack.pop_n(2)?; let a = *popped[0]; let b = *popped[1]; @@ -69,8 +69,8 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait { /// 0x15 - ISZERO /// # Specification: https://www.evm.codes/#15?fork=shanghai - fn exec_iszero(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::VERYLOW)?; + fn exec_iszero(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; let popped = self.stack.pop()?; let result: u256 = (popped == 0).into(); self.stack.push(result) @@ -78,8 +78,8 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait { /// 0x16 - AND /// # Specification: https://www.evm.codes/#16?fork=shanghai - fn exec_and(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::VERYLOW)?; + fn exec_and(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; let popped = self.stack.pop_n(2)?; let a = *popped[0]; let b = *popped[1]; @@ -89,8 +89,8 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait { /// 0x17 - OR /// # Specification: https://www.evm.codes/#17?fork=shanghai - fn exec_or(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::VERYLOW)?; + fn exec_or(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; let popped = self.stack.pop_n(2)?; let a = *popped[0]; let b = *popped[1]; @@ -100,8 +100,8 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait { /// 0x18 - XOR operation /// # Specification: https://www.evm.codes/#18?fork=shanghai - fn exec_xor(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::VERYLOW)?; + fn exec_xor(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; let popped = self.stack.pop_n(2)?; let a = *popped[0]; let b = *popped[1]; @@ -112,8 +112,8 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait { /// 0x19 - NOT /// Bitwise NOT operation /// # Specification: https://www.evm.codes/#19?fork=shanghai - fn exec_not(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::VERYLOW)?; + fn exec_not(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; let a = self.stack.pop()?; let result = ~a; self.stack.push(result) @@ -122,8 +122,8 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait { /// 0x1A - BYTE /// # Specification: https://www.evm.codes/#1a?fork=shanghai /// Retrieve single byte located at the byte offset of value, starting from the most significant byte. - fn exec_byte(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::VERYLOW)?; + fn exec_byte(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; let popped = self.stack.pop_n(2)?; let i = *popped[0]; let x = *popped[1]; @@ -140,8 +140,8 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait { /// 0x1B - SHL /// # Specification: https://www.evm.codes/#1b?fork=shanghai - fn exec_shl(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::VERYLOW)?; + fn exec_shl(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; let popped = self.stack.pop_n(2)?; let shift = *popped[0]; let val = *popped[1]; @@ -157,8 +157,8 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait { /// 0x1C - SHR /// # Specification: https://www.evm.codes/#1c?fork=shanghai - fn exec_shr(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::VERYLOW)?; + fn exec_shr(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; let popped = self.stack.pop_n(2)?; let shift = *popped[0]; let value = *popped[1]; @@ -169,8 +169,8 @@ impl ComparisonAndBitwiseOperations of ComparisonAndBitwiseOperationsTrait { /// 0x1D - SAR /// # Specification: https://www.evm.codes/#1d?fork=shanghai - fn exec_sar(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::VERYLOW)?; + fn exec_sar(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; let shift: u256 = self.stack.pop()?; let value: i256 = self.stack.pop_i256()?; diff --git a/crates/evm/src/instructions/duplication_operations.cairo b/crates/evm/src/instructions/duplication_operations.cairo index 6e23674de..1a33c372f 100644 --- a/crates/evm/src/instructions/duplication_operations.cairo +++ b/crates/evm/src/instructions/duplication_operations.cairo @@ -2,21 +2,20 @@ // Internal imports use evm::errors::EVMError; -use evm::machine::Machine; +use evm::model::vm::{VM, VMTrait}; mod internal { - use evm::context::{ExecutionContext, ExecutionContextTrait,}; use evm::errors::EVMError; use evm::gas; - use evm::machine::{Machine, MachineTrait}; + use evm::model::vm::{VM, VMTrait}; use evm::stack::StackTrait; /// Generic DUP operation #[inline(always)] - fn exec_dup_i(ref machine: Machine, i: u8) -> Result<(), EVMError> { - machine.increment_gas_used_checked(gas::VERYLOW)?; - let item = machine.stack.peek_at((i - 1).into())?; - machine.stack.push(item) + fn exec_dup_i(ref self: VM, i: u8) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; + let item = self.stack.peek_at((i - 1).into())?; + self.stack.push(item) } } @@ -24,97 +23,97 @@ mod internal { impl DuplicationOperations of DuplicationOperationsTrait { /// 0x80 - DUP1 operation #[inline(always)] - fn exec_dup1(ref self: Machine) -> Result<(), EVMError> { + fn exec_dup1(ref self: VM) -> Result<(), EVMError> { internal::exec_dup_i(ref self, 1) } /// 0x81 - DUP2 operation #[inline(always)] - fn exec_dup2(ref self: Machine) -> Result<(), EVMError> { + fn exec_dup2(ref self: VM) -> Result<(), EVMError> { internal::exec_dup_i(ref self, 2) } /// 0x82 - DUP3 operation #[inline(always)] - fn exec_dup3(ref self: Machine) -> Result<(), EVMError> { + fn exec_dup3(ref self: VM) -> Result<(), EVMError> { internal::exec_dup_i(ref self, 3) } /// 0x83 - DUP2 operation #[inline(always)] - fn exec_dup4(ref self: Machine) -> Result<(), EVMError> { + fn exec_dup4(ref self: VM) -> Result<(), EVMError> { internal::exec_dup_i(ref self, 4) } /// 0x84 - DUP5 operation #[inline(always)] - fn exec_dup5(ref self: Machine) -> Result<(), EVMError> { + fn exec_dup5(ref self: VM) -> Result<(), EVMError> { internal::exec_dup_i(ref self, 5) } /// 0x85 - DUP6 operation #[inline(always)] - fn exec_dup6(ref self: Machine) -> Result<(), EVMError> { + fn exec_dup6(ref self: VM) -> Result<(), EVMError> { internal::exec_dup_i(ref self, 6) } /// 0x86 - DUP7 operation #[inline(always)] - fn exec_dup7(ref self: Machine) -> Result<(), EVMError> { + fn exec_dup7(ref self: VM) -> Result<(), EVMError> { internal::exec_dup_i(ref self, 7) } /// 0x87 - DUP8 operation #[inline(always)] - fn exec_dup8(ref self: Machine) -> Result<(), EVMError> { + fn exec_dup8(ref self: VM) -> Result<(), EVMError> { internal::exec_dup_i(ref self, 8) } /// 0x88 - DUP9 operation #[inline(always)] - fn exec_dup9(ref self: Machine) -> Result<(), EVMError> { + fn exec_dup9(ref self: VM) -> Result<(), EVMError> { internal::exec_dup_i(ref self, 9) } /// 0x89 - DUP10 operation #[inline(always)] - fn exec_dup10(ref self: Machine) -> Result<(), EVMError> { + fn exec_dup10(ref self: VM) -> Result<(), EVMError> { internal::exec_dup_i(ref self, 10) } /// 0x8A - DUP11 operation #[inline(always)] - fn exec_dup11(ref self: Machine) -> Result<(), EVMError> { + fn exec_dup11(ref self: VM) -> Result<(), EVMError> { internal::exec_dup_i(ref self, 11) } /// 0x8B - DUP12 operation #[inline(always)] - fn exec_dup12(ref self: Machine) -> Result<(), EVMError> { + fn exec_dup12(ref self: VM) -> Result<(), EVMError> { internal::exec_dup_i(ref self, 12) } /// 0x8C - DUP13 operation #[inline(always)] - fn exec_dup13(ref self: Machine) -> Result<(), EVMError> { + fn exec_dup13(ref self: VM) -> Result<(), EVMError> { internal::exec_dup_i(ref self, 13) } /// 0x8D - DUP14 operation #[inline(always)] - fn exec_dup14(ref self: Machine) -> Result<(), EVMError> { + fn exec_dup14(ref self: VM) -> Result<(), EVMError> { internal::exec_dup_i(ref self, 14) } /// 0x8E - DUP15 operation #[inline(always)] - fn exec_dup15(ref self: Machine) -> Result<(), EVMError> { + fn exec_dup15(ref self: VM) -> Result<(), EVMError> { internal::exec_dup_i(ref self, 15) } /// 0x8F - DUP16 operation #[inline(always)] - fn exec_dup16(ref self: Machine) -> Result<(), EVMError> { + fn exec_dup16(ref self: VM) -> Result<(), EVMError> { internal::exec_dup_i(ref self, 16) } } diff --git a/crates/evm/src/instructions/environmental_information.cairo b/crates/evm/src/instructions/environmental_information.cairo index 4aa8824fc..012970ddd 100644 --- a/crates/evm/src/instructions/environmental_information.cairo +++ b/crates/evm/src/instructions/environmental_information.cairo @@ -1,12 +1,11 @@ use contracts::kakarot_core::interface::{IKakarotCore}; use contracts::kakarot_core::{KakarotCore}; use core::hash::{HashStateExTrait, HashStateTrait}; -use evm::context::ExecutionContextTrait; use evm::errors::{EVMError, RETURNDATA_OUT_OF_BOUNDS_ERROR, READ_SYSCALL_FAILED}; use evm::gas; -use evm::machine::{Machine, MachineTrait}; use evm::memory::MemoryTrait; use evm::model::account::{AccountTrait}; +use evm::model::vm::{VM, VMTrait}; use evm::model::{AccountType, ContractAccountTrait}; use evm::stack::StackTrait; use evm::state::StateTrait; @@ -27,57 +26,57 @@ impl EnvironmentInformationImpl of EnvironmentInformationTrait { /// 0x30 - ADDRESS /// Get address of currently executing account. /// # Specification: https://www.evm.codes/#30?fork=shanghai - fn exec_address(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; - self.stack.push(self.address().evm.into()) + fn exec_address(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; + self.stack.push(self.message().target.evm.into()) } /// 0x31 - BALANCE opcode. /// Get ETH balance of the specified address. /// # Specification: https://www.evm.codes/#31?fork=shanghai - fn exec_balance(ref self: Machine) -> Result<(), EVMError> { + fn exec_balance(ref self: VM) -> Result<(), EVMError> { // TODO: Add warm / cold storage costs - self.increment_gas_used_checked(gas::WARM_STORAGE_READ_COST)?; + self.charge_gas(gas::WARM_STORAGE_READ_COST)?; let evm_address = self.stack.pop_eth_address()?; - let balance = self.state.get_account(evm_address).balance(); + let balance = self.env.state.get_account(evm_address).balance(); self.stack.push(balance) } /// 0x32 - ORIGIN /// Get execution origination address. /// # Specification: https://www.evm.codes/#32?fork=shanghai - fn exec_origin(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; - self.stack.push(self.origin().evm.into()) + fn exec_origin(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; + self.stack.push(self.env.origin.into()) } /// 0x33 - CALLER /// Get caller address. /// # Specification: https://www.evm.codes/#33?fork=shanghai - fn exec_caller(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; - self.stack.push(self.caller().evm.into()) + fn exec_caller(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; + self.stack.push(self.message().caller.evm.into()) } /// 0x34 - CALLVALUE /// Get deposited value by the instruction/transaction responsible for this execution. /// # Specification: https://www.evm.codes/#34?fork=shanghai - fn exec_callvalue(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; - self.stack.push(self.value()) + fn exec_callvalue(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; + self.stack.push(self.message().value) } /// 0x35 - CALLDATALOAD /// Push a word from the calldata onto the stack. /// # Specification: https://www.evm.codes/#35?fork=shanghai - fn exec_calldataload(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::VERYLOW)?; + fn exec_calldataload(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; let offset: usize = self.stack.pop_usize()?; - let calldata = self.calldata(); + let calldata = self.message().data; let calldata_len = calldata.len(); // All bytes after the end of the calldata are set to 0. @@ -109,24 +108,24 @@ impl EnvironmentInformationImpl of EnvironmentInformationTrait { /// 0x36 - CALLDATASIZE /// Get the size of return data. /// # Specification: https://www.evm.codes/#36?fork=shanghai - fn exec_calldatasize(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; - let size: u256 = self.calldata().len().into(); + fn exec_calldatasize(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; + let size: u256 = self.message().data.len().into(); self.stack.push(size) } /// 0x37 - CALLDATACOPY operation /// Save word to memory. /// # Specification: https://www.evm.codes/#37?fork=shanghai - fn exec_calldatacopy(ref self: Machine) -> Result<(), EVMError> { + fn exec_calldatacopy(ref self: VM) -> Result<(), EVMError> { // TODO: Add dynamic gas - self.increment_gas_used_checked(gas::VERYLOW)?; + self.charge_gas(gas::VERYLOW)?; let dest_offset = self.stack.pop_usize()?; let offset = self.stack.pop_usize()?; let size = self.stack.pop_usize()?; - let calldata: Span = self.calldata(); + let calldata: Span = self.message().data; let copied: Span = if (offset + size > calldata.len()) { calldata.slice(offset, calldata.len() - offset) @@ -142,24 +141,24 @@ impl EnvironmentInformationImpl of EnvironmentInformationTrait { /// 0x38 - CODESIZE /// Get size of bytecode running in current environment. /// # Specification: https://www.evm.codes/#38?fork=shanghai - fn exec_codesize(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; - let size: u256 = self.bytecode().len().into(); + fn exec_codesize(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; + let size: u256 = self.message().code.len().into(); self.stack.push(size) } /// 0x39 - CODECOPY /// Copies slice of bytecode to memory. /// # Specification: https://www.evm.codes/#39?fork=shanghai - fn exec_codecopy(ref self: Machine) -> Result<(), EVMError> { + fn exec_codecopy(ref self: VM) -> Result<(), EVMError> { // TODO: Add dynamic gas - self.increment_gas_used_checked(gas::VERYLOW)?; + self.charge_gas(gas::VERYLOW)?; let dest_offset = self.stack.pop_usize()?; let offset = self.stack.pop_usize()?; let size = self.stack.pop_usize()?; - let bytecode: Span = self.bytecode(); + let bytecode: Span = self.message().code; let copied: Span = if offset > bytecode.len() { Default::default().span() @@ -177,37 +176,37 @@ impl EnvironmentInformationImpl of EnvironmentInformationTrait { /// 0x3A - GASPRICE /// Get price of gas in current environment. /// # Specification: https://www.evm.codes/#3a?fork=shanghai - fn exec_gasprice(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; - self.stack.push(self.gas_price().into()) + fn exec_gasprice(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; + self.stack.push(self.env.gas_price.into()) } /// 0x3B - EXTCODESIZE /// Get size of an account's code. /// # Specification: https://www.evm.codes/#3b?fork=shanghai - fn exec_extcodesize(ref self: Machine) -> Result<(), EVMError> { + fn exec_extcodesize(ref self: VM) -> Result<(), EVMError> { // TODO: Add Warm / Cold storage costs - self.increment_gas_used_checked(gas::WARM_STORAGE_READ_COST)?; + self.charge_gas(gas::WARM_STORAGE_READ_COST)?; let evm_address = self.stack.pop_eth_address()?; - let account = self.state.get_account(evm_address); + let account = self.env.state.get_account(evm_address); self.stack.push(account.code.len().into()) } /// 0x3C - EXTCODECOPY /// Copy an account's code to memory /// # Specification: https://www.evm.codes/#3c?fork=shanghai - fn exec_extcodecopy(ref self: Machine) -> Result<(), EVMError> { + fn exec_extcodecopy(ref self: VM) -> Result<(), EVMError> { // TODO: Add Warm / Cold storage costs - self.increment_gas_used_checked(gas::WARM_STORAGE_READ_COST)?; + self.charge_gas(gas::WARM_STORAGE_READ_COST)?; let evm_address = self.stack.pop_eth_address()?; let dest_offset = self.stack.pop_usize()?; let offset = self.stack.pop_usize()?; let size = self.stack.pop_usize()?; - let bytecode = self.state.get_account(evm_address).code; + let bytecode = self.env.state.get_account(evm_address).code; let bytecode_len = bytecode.len(); let bytecode_slice = if offset < bytecode_len { bytecode.slice(offset, bytecode_len - offset) @@ -221,8 +220,8 @@ impl EnvironmentInformationImpl of EnvironmentInformationTrait { /// 0x3D - RETURNDATASIZE /// Get the size of return data. /// # Specification: https://www.evm.codes/#3d?fork=shanghai - fn exec_returndatasize(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; + fn exec_returndatasize(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; let size = self.return_data().len(); self.stack.push(size.into()) } @@ -230,9 +229,9 @@ impl EnvironmentInformationImpl of EnvironmentInformationTrait { /// 0x3E - RETURNDATACOPY /// Save word to memory. /// # Specification: https://www.evm.codes/#3e?fork=shanghai - fn exec_returndatacopy(ref self: Machine) -> Result<(), EVMError> { + fn exec_returndatacopy(ref self: VM) -> Result<(), EVMError> { // TODO: Add dynamic gas - self.increment_gas_used_checked(gas::VERYLOW)?; + self.charge_gas(gas::VERYLOW)?; let dest_offset = self.stack.pop_usize()?; let offset = self.stack.pop_usize()?; @@ -264,13 +263,13 @@ impl EnvironmentInformationImpl of EnvironmentInformationTrait { // If the account does not exist, is a precompile or was destroyed (SELFDESTRUCT), return 0 // Else return, the hash of the account's code /// # Specification: https://www.evm.codes/#3f?fork=shanghai - fn exec_extcodehash(ref self: Machine) -> Result<(), EVMError> { + fn exec_extcodehash(ref self: VM) -> Result<(), EVMError> { // TODO: Add Warm / Cold storage costs - self.increment_gas_used_checked(gas::WARM_STORAGE_READ_COST)?; + self.charge_gas(gas::WARM_STORAGE_READ_COST)?; let evm_address = self.stack.pop_eth_address()?; - let account = self.state.get_account(evm_address); + let account = self.env.state.get_account(evm_address); // UnknownAccount can either be // -> Undeployed CAs that might be deployed later, but currently don't // exist and have only been touched for value transfers diff --git a/crates/evm/src/instructions/exchange_operations.cairo b/crates/evm/src/instructions/exchange_operations.cairo index 0a598f424..ce9a4a2ec 100644 --- a/crates/evm/src/instructions/exchange_operations.cairo +++ b/crates/evm/src/instructions/exchange_operations.cairo @@ -1,22 +1,22 @@ //! Exchange Operations. use evm::errors::EVMError; -use evm::machine::Machine; +use evm::model::vm::{VM, VMTrait}; use evm::stack::StackTrait; use utils::helpers::load_word; mod internal { use evm::errors::EVMError; use evm::gas; - use evm::machine::{Machine, MachineTrait}; + use evm::model::vm::{VM, VMTrait}; use evm::stack::StackTrait; use utils::helpers::load_word; /// Place i bytes items on stack. #[inline(always)] - fn exec_swap_i(ref machine: Machine, i: u8) -> Result<(), EVMError> { - machine.increment_gas_used_checked(gas::VERYLOW)?; - machine.stack.swap_i(i.into()) + fn exec_swap_i(ref self: VM, i: u8) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; + self.stack.swap_i(i.into()) } } @@ -26,112 +26,112 @@ impl ExchangeOperations of ExchangeOperationsTrait { /// Exchange 1st and 2nd stack items. /// # Specification: https://www.evm.codes/#90?fork=shanghai - fn exec_swap1(ref self: Machine) -> Result<(), EVMError> { + fn exec_swap1(ref self: VM) -> Result<(), EVMError> { internal::exec_swap_i(ref self, 1) } /// 0x91 - SWAP2 operation /// Exchange 1st and 3rd stack items. /// # Specification: https://www.evm.codes/#91?fork=shanghai - fn exec_swap2(ref self: Machine) -> Result<(), EVMError> { + fn exec_swap2(ref self: VM) -> Result<(), EVMError> { internal::exec_swap_i(ref self, 2) } /// 0x92 - SWAP3 operation /// Exchange 1st and 4th stack items. /// # Specification: https://www.evm.codes/#92?fork=shanghai - fn exec_swap3(ref self: Machine) -> Result<(), EVMError> { + fn exec_swap3(ref self: VM) -> Result<(), EVMError> { internal::exec_swap_i(ref self, 3) } /// 0x93 - SWAP4 operation /// Exchange 1st and 5th stack items. /// # Specification: https://www.evm.codes/#93?fork=shanghai - fn exec_swap4(ref self: Machine) -> Result<(), EVMError> { + fn exec_swap4(ref self: VM) -> Result<(), EVMError> { internal::exec_swap_i(ref self, 4) } /// 0x94 - SWAP5 operation /// Exchange 1st and 6th stack items. /// # Specification: https://www.evm.codes/#94?fork=shanghai - fn exec_swap5(ref self: Machine) -> Result<(), EVMError> { + fn exec_swap5(ref self: VM) -> Result<(), EVMError> { internal::exec_swap_i(ref self, 5) } /// 0x95 - SWAP6 operation /// Exchange 1st and 7th stack items. /// # Specification: https://www.evm.codes/#95?fork=shanghai - fn exec_swap6(ref self: Machine) -> Result<(), EVMError> { + fn exec_swap6(ref self: VM) -> Result<(), EVMError> { internal::exec_swap_i(ref self, 6) } /// 0x96 - SWAP7 operation /// Exchange 1st and 8th stack items. /// # Specification: https://www.evm.codes/#96?fork=shanghai - fn exec_swap7(ref self: Machine) -> Result<(), EVMError> { + fn exec_swap7(ref self: VM) -> Result<(), EVMError> { internal::exec_swap_i(ref self, 7) } /// 0x97 - SWAP8 operation /// Exchange 1st and 9th stack items. /// # Specification: https://www.evm.codes/#97?fork=shanghai - fn exec_swap8(ref self: Machine) -> Result<(), EVMError> { + fn exec_swap8(ref self: VM) -> Result<(), EVMError> { internal::exec_swap_i(ref self, 8) } /// 0x98 - SWAP9 operation /// Exchange 1st and 10th stack items. /// # Specification: https://www.evm.codes/#98?fork=shanghai - fn exec_swap9(ref self: Machine) -> Result<(), EVMError> { + fn exec_swap9(ref self: VM) -> Result<(), EVMError> { internal::exec_swap_i(ref self, 9) } /// 0x99 - SWAP10 operation /// Exchange 1st and 11th stack items. /// # Specification: https://www.evm.codes/#99?fork=shanghai - fn exec_swap10(ref self: Machine) -> Result<(), EVMError> { + fn exec_swap10(ref self: VM) -> Result<(), EVMError> { internal::exec_swap_i(ref self, 10) } /// 0x9A - SWAP11 operation /// Exchange 1st and 12th stack items. /// # Specification: https://www.evm.codes/#9a?fork=shanghai - fn exec_swap11(ref self: Machine) -> Result<(), EVMError> { + fn exec_swap11(ref self: VM) -> Result<(), EVMError> { internal::exec_swap_i(ref self, 11) } /// 0x9B - SWAP12 operation /// Exchange 1st and 13th stack items. /// # Specification: https://www.evm.codes/#9b?fork=shanghai - fn exec_swap12(ref self: Machine) -> Result<(), EVMError> { + fn exec_swap12(ref self: VM) -> Result<(), EVMError> { internal::exec_swap_i(ref self, 12) } /// 0x9C - SWAP13 operation /// Exchange 1st and 14th stack items. /// # Specification: https://www.evm.codes/#9c?fork=shanghai - fn exec_swap13(ref self: Machine) -> Result<(), EVMError> { + fn exec_swap13(ref self: VM) -> Result<(), EVMError> { internal::exec_swap_i(ref self, 13) } /// 0x9D - SWAP14 operation /// Exchange 1st and 15th stack items. /// # Specification: https://www.evm.codes/#9d?fork=shanghai - fn exec_swap14(ref self: Machine) -> Result<(), EVMError> { + fn exec_swap14(ref self: VM) -> Result<(), EVMError> { internal::exec_swap_i(ref self, 14) } /// 0x9E - SWAP15 operation /// Exchange 1st and 16th stack items. /// # Specification: https://www.evm.codes/#9e?fork=shanghai - fn exec_swap15(ref self: Machine) -> Result<(), EVMError> { + fn exec_swap15(ref self: VM) -> Result<(), EVMError> { internal::exec_swap_i(ref self, 15) } /// 0x9F - SWAP16 operation /// Exchange 1st and 16th stack items. /// # Specification: https://www.evm.codes/#9f?fork=shanghai - fn exec_swap16(ref self: Machine) -> Result<(), EVMError> { + fn exec_swap16(ref self: VM) -> Result<(), EVMError> { internal::exec_swap_i(ref self, 16) } } diff --git a/crates/evm/src/instructions/logging_operations.cairo b/crates/evm/src/instructions/logging_operations.cairo index f24dd79d1..b2068f35a 100644 --- a/crates/evm/src/instructions/logging_operations.cairo +++ b/crates/evm/src/instructions/logging_operations.cairo @@ -2,42 +2,42 @@ use evm::errors::EVMError; //! Logging Operations. // Internal imports -use evm::machine::Machine; +use evm::model::vm::{VM, VMTrait}; #[generate_trait] impl LoggingOperations of LoggingOperationsTrait { /// 0xA0 - LOG0 operation /// Append log record with no topic. /// # Specification: https://www.evm.codes/#a0?fork=shanghai - fn exec_log0(ref self: Machine) -> Result<(), EVMError> { + fn exec_log0(ref self: VM) -> Result<(), EVMError> { internal::exec_log_i(ref self, 0) } /// 0xA1 - LOG1 /// Append log record with one topic. /// # Specification: https://www.evm.codes/#a1?fork=shanghai - fn exec_log1(ref self: Machine) -> Result<(), EVMError> { + fn exec_log1(ref self: VM) -> Result<(), EVMError> { internal::exec_log_i(ref self, 1) } /// 0xA2 - LOG2 /// Append log record with two topics. /// # Specification: https://www.evm.codes/#a2?fork=shanghai - fn exec_log2(ref self: Machine) -> Result<(), EVMError> { + fn exec_log2(ref self: VM) -> Result<(), EVMError> { internal::exec_log_i(ref self, 2) } /// 0xA3 - LOG3 /// Append log record with three topics. /// # Specification: https://www.evm.codes/#a3?fork=shanghai - fn exec_log3(ref self: Machine) -> Result<(), EVMError> { + fn exec_log3(ref self: VM) -> Result<(), EVMError> { internal::exec_log_i(ref self, 3) } /// 0xA4 - LOG4 /// Append log record with four topics. /// # Specification: https://www.evm.codes/#a4?fork=shanghai - fn exec_log4(ref self: Machine) -> Result<(), EVMError> { + fn exec_log4(ref self: VM) -> Result<(), EVMError> { internal::exec_log_i(ref self, 4) } } @@ -45,12 +45,13 @@ impl LoggingOperations of LoggingOperationsTrait { mod internal { use evm::errors::{EVMError, WRITE_IN_STATIC_CONTEXT}; use evm::gas; - use evm::machine::{Machine, MachineTrait}; use evm::memory::MemoryTrait; use evm::model::Event; + use evm::model::vm::{VM, VMTrait}; use evm::stack::StackTrait; use evm::state::StateTrait; + /// Store a new event in the dynamic context using topics /// popped from the stack and data from the memory. /// @@ -58,14 +59,14 @@ mod internal { /// /// * `self` - The context to which the event will be added /// * `topics_len` - The amount of topics to pop from the stack - fn exec_log_i(ref self: Machine, topics_len: u8) -> Result<(), EVMError> { + fn exec_log_i(ref self: VM, topics_len: u8) -> Result<(), EVMError> { // Revert if the transaction is in a read only context - if self.read_only() { + if self.message().read_only { return Result::Err(EVMError::WriteInStaticContext(WRITE_IN_STATIC_CONTEXT)); } // TODO: Add dynamic memory gas - self.increment_gas_used_checked(gas::LOG + gas::LOGTOPIC * topics_len.into())?; + self.charge_gas(gas::LOG + gas::LOGTOPIC * topics_len.into())?; let offset = self.stack.pop_usize()?; let size = self.stack.pop_usize()?; @@ -75,7 +76,7 @@ mod internal { self.memory.load_n(size, ref data, offset); let event: Event = Event { keys: topics, data }; - self.state.add_event(event); + self.env.state.add_event(event); Result::Ok(()) } diff --git a/crates/evm/src/instructions/memory_operations.cairo b/crates/evm/src/instructions/memory_operations.cairo index bb368fbdb..dcd78da88 100644 --- a/crates/evm/src/instructions/memory_operations.cairo +++ b/crates/evm/src/instructions/memory_operations.cairo @@ -1,8 +1,8 @@ //! Stack Memory Storage and Flow Operations. use evm::errors::{EVMError, INVALID_DESTINATION, READ_SYSCALL_FAILED, WRITE_IN_STATIC_CONTEXT}; use evm::gas; -use evm::machine::{Machine, MachineTrait}; use evm::memory::MemoryTrait; +use evm::model::vm::{VM, VMTrait}; use evm::stack::StackTrait; use evm::state::{StateTrait, compute_state_key}; use hash::{HashStateTrait, HashStateExTrait}; @@ -14,8 +14,8 @@ impl MemoryOperation of MemoryOperationTrait { /// 0x50 - POP operation. /// Pops the first item on the stack (top of the stack). /// # Specification: https://www.evm.codes/#50?fork=shanghai - fn exec_pop(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; + fn exec_pop(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; // self.stack.pop() returns a Result so we cannot simply return its result self.stack.pop()?; @@ -24,9 +24,9 @@ impl MemoryOperation of MemoryOperationTrait { /// MLOAD operation. /// Load word from memory and push to stack. - fn exec_mload(ref self: Machine) -> Result<(), EVMError> { + fn exec_mload(ref self: VM) -> Result<(), EVMError> { // TODO: add dynamic gas - self.increment_gas_used_checked(gas::VERYLOW)?; + self.charge_gas(gas::VERYLOW)?; let offset: usize = self.stack.pop_usize()?; let result = self.memory.load(offset); @@ -36,9 +36,9 @@ impl MemoryOperation of MemoryOperationTrait { /// 0x52 - MSTORE operation. /// Save word to memory. /// # Specification: https://www.evm.codes/#52?fork=shanghai - fn exec_mstore(ref self: Machine) -> Result<(), EVMError> { + fn exec_mstore(ref self: VM) -> Result<(), EVMError> { // TODO: add dynamic gas - self.increment_gas_used_checked(gas::VERYLOW)?; + self.charge_gas(gas::VERYLOW)?; let offset: usize = self.stack.pop_usize()?; let value: u256 = self.stack.pop()?; @@ -50,9 +50,9 @@ impl MemoryOperation of MemoryOperationTrait { /// 0x53 - MSTORE8 operation. /// Save single byte to memory /// # Specification: https://www.evm.codes/#53?fork=shanghai - fn exec_mstore8(ref self: Machine) -> Result<(), EVMError> { + fn exec_mstore8(ref self: VM) -> Result<(), EVMError> { // TODO: add dynamic gas - self.increment_gas_used_checked(gas::VERYLOW)?; + self.charge_gas(gas::VERYLOW)?; let offset = self.stack.pop_usize()?; let value = self.stack.pop()?; @@ -66,14 +66,14 @@ impl MemoryOperation of MemoryOperationTrait { /// 0x54 - SLOAD operation /// Load from storage. /// # Specification: https://www.evm.codes/#54?fork=shanghai - fn exec_sload(ref self: Machine) -> Result<(), EVMError> { + fn exec_sload(ref self: VM) -> Result<(), EVMError> { // TODO: Add Warm / Cold storage costs - self.increment_gas_used_checked(gas::WARM_STORAGE_READ_COST)?; + self.charge_gas(gas::WARM_STORAGE_READ_COST)?; let key = self.stack.pop()?; - let evm_address = self.address().evm; + let evm_address = self.message().target.evm; - let value = self.state.read_state(evm_address, key)?; + let value = self.env.state.read_state(evm_address, key)?; self.stack.push(value) } @@ -81,18 +81,18 @@ impl MemoryOperation of MemoryOperationTrait { /// 0x55 - SSTORE operation /// Save 32-byte word to storage. /// # Specification: https://www.evm.codes/#55?fork=shanghai - fn exec_sstore(ref self: Machine) -> Result<(), EVMError> { - if self.read_only() { + fn exec_sstore(ref self: VM) -> Result<(), EVMError> { + if self.message().read_only { return Result::Err(EVMError::WriteInStaticContext(WRITE_IN_STATIC_CONTEXT)); } // TODO: Add Warm / Cold storage costs - self.increment_gas_used_checked(gas::WARM_STORAGE_READ_COST)?; + self.charge_gas(gas::WARM_STORAGE_READ_COST)?; let key = self.stack.pop()?; let value = self.stack.pop()?; - let evm_address = self.address().evm; - self.state.write_state(:evm_address, :key, :value); + let evm_address = self.message().target.evm; + self.env.state.write_state(:evm_address, :key, :value); Result::Ok(()) } @@ -109,8 +109,8 @@ impl MemoryOperation of MemoryOperationTrait { /// `PUSH-N` opcodes. /// /// Note: Jump destinations are 0-indexed. - fn exec_jump(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::MID)?; + fn exec_jump(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::MID)?; let index = self.stack.pop_usize()?; @@ -122,7 +122,7 @@ impl MemoryOperation of MemoryOperationTrait { // present in that list // // Check if idx in bytecode points to `JUMPDEST` opcode - match self.bytecode().get(index) { + match self.message().code.get(index) { Option::Some(opcode) => { if *opcode.unbox() != 0x5B { return Result::Err(EVMError::JumpError(INVALID_DESTINATION)); @@ -138,8 +138,8 @@ impl MemoryOperation of MemoryOperationTrait { /// Change the pc counter under a provided certain condition. /// The new pc target has to be a JUMPDEST opcode. /// # Specification: https://www.evm.codes/#57?fork=shanghai - fn exec_jumpi(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::HIGH)?; + fn exec_jumpi(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::HIGH)?; // Peek the value so we don't need to push it back again incase we want to call `exec_jump` let b = self.stack.peek_at(1)?; @@ -161,8 +161,8 @@ impl MemoryOperation of MemoryOperationTrait { /// 0x58 - PC operation /// Get the value of the program counter prior to the increment. /// # Specification: https://www.evm.codes/#58?fork=shanghai - fn exec_pc(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; + fn exec_pc(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; let pc = self.pc().into(); self.stack.push(pc) @@ -171,8 +171,8 @@ impl MemoryOperation of MemoryOperationTrait { /// 0x59 - MSIZE operation. /// Get the value of memory size. /// # Specification: https://www.evm.codes/#59?fork=shanghai - fn exec_msize(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; + fn exec_msize(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; let msize: u256 = self.memory.size().into(); self.stack.push(msize) @@ -182,8 +182,8 @@ impl MemoryOperation of MemoryOperationTrait { /// 0x5A - GAS operation /// Get the amount of available gas, including the corresponding reduction for the cost of this instruction. /// # Specification: https://www.evm.codes/#5a?fork=shanghai - fn exec_gas(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; + fn exec_gas(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; self.stack.push(self.gas_used().into()) } @@ -194,8 +194,8 @@ impl MemoryOperation of MemoryOperationTrait { /// /// This doesn't have any affect on execution state, so we don't have /// to do anything here. It's a NO-OP. - fn exec_jumpdest(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::JUMPDEST)?; + fn exec_jumpdest(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::JUMPDEST)?; Result::Ok(()) } } diff --git a/crates/evm/src/instructions/push_operations.cairo b/crates/evm/src/instructions/push_operations.cairo index 3aee1f0cb..fcb040459 100644 --- a/crates/evm/src/instructions/push_operations.cairo +++ b/crates/evm/src/instructions/push_operations.cairo @@ -2,26 +2,26 @@ use evm::errors::EVMError; use evm::gas; -use evm::machine::{Machine, MachineTrait}; +use evm::model::vm::{VM, VMTrait}; use evm::stack::StackTrait; mod internal { use evm::errors::EVMError; use evm::gas; - use evm::machine::{Machine, MachineTrait}; + use evm::model::vm::{VM, VMTrait}; use evm::stack::StackTrait; use utils::helpers::load_word; /// Place i bytes items on stack. #[inline(always)] - fn exec_push_i(ref machine: Machine, i: u8) -> Result<(), EVMError> { - machine.increment_gas_used_checked(gas::VERYLOW)?; + fn exec_push_i(ref self: VM, i: u8) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; let i = i.into(); - let data = machine.read_code(i); + let data = self.read_code(i); - machine.set_pc(machine.pc() + i); + self.set_pc(self.pc() + i); - machine.stack.push(load_word(i, data)) + self.stack.push(load_word(i, data)) } } @@ -30,8 +30,8 @@ impl PushOperations of PushOperationsTrait { /// 5F - PUSH0 operation /// # Specification: https://www.evm.codes/#5f?fork=shanghai #[inline(always)] - fn exec_push0(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::BASE)?; + fn exec_push0(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::BASE)?; self.stack.push(0) } @@ -39,7 +39,7 @@ impl PushOperations of PushOperationsTrait { /// 0x60 - PUSH1 operation /// # Specification: https://www.evm.codes/#60?fork=shanghai #[inline(always)] - fn exec_push1(ref self: Machine) -> Result<(), EVMError> { + fn exec_push1(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 1) } @@ -47,7 +47,7 @@ impl PushOperations of PushOperationsTrait { /// 0x61 - PUSH2 operation /// # Specification: https://www.evm.codes/#61?fork=shanghai #[inline(always)] - fn exec_push2(ref self: Machine) -> Result<(), EVMError> { + fn exec_push2(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 2) } @@ -55,42 +55,42 @@ impl PushOperations of PushOperationsTrait { /// 0x62 - PUSH3 operation /// # Specification: https://www.evm.codes/#62?fork=shanghai #[inline(always)] - fn exec_push3(ref self: Machine) -> Result<(), EVMError> { + fn exec_push3(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 3) } /// 0x63 - PUSH4 operation /// # Specification: https://www.evm.codes/#63?fork=shanghai #[inline(always)] - fn exec_push4(ref self: Machine) -> Result<(), EVMError> { + fn exec_push4(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 4) } /// 0x64 - PUSH5 operation /// # Specification: https://www.evm.codes/#64?fork=shanghai #[inline(always)] - fn exec_push5(ref self: Machine) -> Result<(), EVMError> { + fn exec_push5(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 5) } /// 0x65 - PUSH6 operation /// # Specification: https://www.evm.codes/#65?fork=shanghai #[inline(always)] - fn exec_push6(ref self: Machine) -> Result<(), EVMError> { + fn exec_push6(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 6) } /// 0x66 - PUSH7 operation /// # Specification: https://www.evm.codes/#66?fork=shanghai #[inline(always)] - fn exec_push7(ref self: Machine) -> Result<(), EVMError> { + fn exec_push7(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 7) } /// 0x67 - PUSH8 operation /// # Specification: https://www.evm.codes/#67?fork=shanghai #[inline(always)] - fn exec_push8(ref self: Machine) -> Result<(), EVMError> { + fn exec_push8(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 8) } @@ -98,28 +98,28 @@ impl PushOperations of PushOperationsTrait { /// 0x68 - PUSH9 operation /// # Specification: https://www.evm.codes/#68?fork=shanghai #[inline(always)] - fn exec_push9(ref self: Machine) -> Result<(), EVMError> { + fn exec_push9(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 9) } /// 0x69 - PUSH10 operation /// # Specification: https://www.evm.codes/#69?fork=shanghai #[inline(always)] - fn exec_push10(ref self: Machine) -> Result<(), EVMError> { + fn exec_push10(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 10) } /// 0x6A - PUSH11 operation /// # Specification: https://www.evm.codes/#6a?fork=shanghai #[inline(always)] - fn exec_push11(ref self: Machine) -> Result<(), EVMError> { + fn exec_push11(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 11) } /// 0x6B - PUSH12 operation /// # Specification: https://www.evm.codes/#6b?fork=shanghai #[inline(always)] - fn exec_push12(ref self: Machine) -> Result<(), EVMError> { + fn exec_push12(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 12) } @@ -127,14 +127,14 @@ impl PushOperations of PushOperationsTrait { /// 0x6C - PUSH13 operation /// # Specification: https://www.evm.codes/#6c?fork=shanghai #[inline(always)] - fn exec_push13(ref self: Machine) -> Result<(), EVMError> { + fn exec_push13(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 13) } /// 0x6D - PUSH14 operation /// # Specification: https://www.evm.codes/#6d?fork=shanghai #[inline(always)] - fn exec_push14(ref self: Machine) -> Result<(), EVMError> { + fn exec_push14(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 14) } @@ -142,28 +142,28 @@ impl PushOperations of PushOperationsTrait { /// 0x6E - PUSH15 operation /// # Specification: https://www.evm.codes/#6e?fork=shanghai #[inline(always)] - fn exec_push15(ref self: Machine) -> Result<(), EVMError> { + fn exec_push15(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 15) } /// 0x6F - PUSH16 operation /// # Specification: https://www.evm.codes/#6f?fork=shanghai #[inline(always)] - fn exec_push16(ref self: Machine) -> Result<(), EVMError> { + fn exec_push16(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 16) } /// 0x70 - PUSH17 operation /// # Specification: https://www.evm.codes/#70?fork=shanghai #[inline(always)] - fn exec_push17(ref self: Machine) -> Result<(), EVMError> { + fn exec_push17(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 17) } /// 0x71 - PUSH18 operation /// # Specification: https://www.evm.codes/#71?fork=shanghai #[inline(always)] - fn exec_push18(ref self: Machine) -> Result<(), EVMError> { + fn exec_push18(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 18) } @@ -171,14 +171,14 @@ impl PushOperations of PushOperationsTrait { /// 0x72 - PUSH19 operation /// # Specification: https://www.evm.codes/#72?fork=shanghai #[inline(always)] - fn exec_push19(ref self: Machine) -> Result<(), EVMError> { + fn exec_push19(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 19) } /// 0x73 - PUSH20 operation /// # Specification: https://www.evm.codes/#73?fork=shanghai #[inline(always)] - fn exec_push20(ref self: Machine) -> Result<(), EVMError> { + fn exec_push20(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 20) } @@ -186,7 +186,7 @@ impl PushOperations of PushOperationsTrait { /// 0x74 - PUSH21 operation /// # Specification: https://www.evm.codes/#74?fork=shanghai #[inline(always)] - fn exec_push21(ref self: Machine) -> Result<(), EVMError> { + fn exec_push21(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 21) } @@ -194,7 +194,7 @@ impl PushOperations of PushOperationsTrait { /// 0x75 - PUSH22 operation /// # Specification: https://www.evm.codes/#75?fork=shanghai #[inline(always)] - fn exec_push22(ref self: Machine) -> Result<(), EVMError> { + fn exec_push22(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 22) } @@ -202,7 +202,7 @@ impl PushOperations of PushOperationsTrait { /// 0x76 - PUSH23 operation /// # Specification: https://www.evm.codes/#76?fork=shanghai #[inline(always)] - fn exec_push23(ref self: Machine) -> Result<(), EVMError> { + fn exec_push23(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 23) } @@ -210,7 +210,7 @@ impl PushOperations of PushOperationsTrait { /// 0x77 - PUSH24 operation /// # Specification: https://www.evm.codes/#77?fork=shanghai #[inline(always)] - fn exec_push24(ref self: Machine) -> Result<(), EVMError> { + fn exec_push24(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 24) } @@ -218,7 +218,7 @@ impl PushOperations of PushOperationsTrait { /// 0x78 - PUSH21 operation /// # Specification: https://www.evm.codes/#78?fork=shanghai #[inline(always)] - fn exec_push25(ref self: Machine) -> Result<(), EVMError> { + fn exec_push25(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 25) } @@ -226,7 +226,7 @@ impl PushOperations of PushOperationsTrait { /// 0x79 - PUSH26 operation /// # Specification: https://www.evm.codes/#79?fork=shanghai #[inline(always)] - fn exec_push26(ref self: Machine) -> Result<(), EVMError> { + fn exec_push26(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 26) } @@ -234,14 +234,14 @@ impl PushOperations of PushOperationsTrait { /// 0x7A - PUSH27 operation /// # Specification: https://www.evm.codes/#7a?fork=shanghai #[inline(always)] - fn exec_push27(ref self: Machine) -> Result<(), EVMError> { + fn exec_push27(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 27) } /// 0x7B - PUSH28 operation /// # Specification: https://www.evm.codes/#7b?fork=shanghai #[inline(always)] - fn exec_push28(ref self: Machine) -> Result<(), EVMError> { + fn exec_push28(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 28) } @@ -249,7 +249,7 @@ impl PushOperations of PushOperationsTrait { /// 0x7C - PUSH29 operation /// # Specification: https://www.evm.codes/#7c?fork=shanghai #[inline(always)] - fn exec_push29(ref self: Machine) -> Result<(), EVMError> { + fn exec_push29(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 29) } @@ -257,7 +257,7 @@ impl PushOperations of PushOperationsTrait { /// 0x7D - PUSH30 operation /// # Specification: https://www.evm.codes/#7d?fork=shanghai #[inline(always)] - fn exec_push30(ref self: Machine) -> Result<(), EVMError> { + fn exec_push30(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 30) } @@ -265,7 +265,7 @@ impl PushOperations of PushOperationsTrait { /// 0x7E - PUSH31 operation /// # Specification: https://www.evm.codes/#7e?fork=shanghai #[inline(always)] - fn exec_push31(ref self: Machine) -> Result<(), EVMError> { + fn exec_push31(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 31) } @@ -273,7 +273,7 @@ impl PushOperations of PushOperationsTrait { /// 0x7F - PUSH32 operation /// # Specification: https://www.evm.codes/#7f?fork=shanghai #[inline(always)] - fn exec_push32(ref self: Machine) -> Result<(), EVMError> { + fn exec_push32(ref self: VM) -> Result<(), EVMError> { internal::exec_push_i(ref self, 32) } } diff --git a/crates/evm/src/instructions/sha3.cairo b/crates/evm/src/instructions/sha3.cairo index b33881b56..66d253de9 100644 --- a/crates/evm/src/instructions/sha3.cairo +++ b/crates/evm/src/instructions/sha3.cairo @@ -3,8 +3,8 @@ use evm::errors::EVMError; use evm::gas; // Internal imports -use evm::machine::{Machine, MachineTrait}; use evm::memory::MemoryTrait; +use evm::model::vm::{VM, VMTrait}; use evm::stack::StackTrait; use keccak::{cairo_keccak, u128_split}; use utils::helpers::{ArrayExtTrait, U256Trait}; @@ -19,9 +19,9 @@ impl Sha3Impl of Sha3Trait { /// * `size` - The amount of bytes to read /// /// # Specification: https://www.evm.codes/#20?fork=shanghai - fn exec_sha3(ref self: Machine) -> Result<(), EVMError> { + fn exec_sha3(ref self: VM) -> Result<(), EVMError> { // TODO: Add dynamic gas - self.increment_gas_used_checked(gas::KECCAK256)?; + self.charge_gas(gas::KECCAK256)?; let offset: usize = self.stack.pop_usize()?; let mut size: usize = self.stack.pop_usize()?; @@ -56,8 +56,8 @@ impl Sha3Impl of Sha3Trait { mod internal { - use evm::machine::Machine; use evm::memory::MemoryTrait; + use evm::model::vm::{VM, VMTrait}; use evm::stack::StackTrait; use utils::helpers::U256Trait; @@ -102,7 +102,7 @@ mod internal { /// * `amount` - The amount of words to read from memory /// Return the new offset fn fill_array_with_memory_words( - ref self: Machine, ref to_hash: Array, mut offset: u32, mut amount: u32 + ref self: VM, ref to_hash: Array, mut offset: u32, mut amount: u32 ) -> u32 { loop { if amount == 0 { diff --git a/crates/evm/src/instructions/stop_and_arithmetic_operations.cairo b/crates/evm/src/instructions/stop_and_arithmetic_operations.cairo index 1d916c4ec..1ba0f17af 100644 --- a/crates/evm/src/instructions/stop_and_arithmetic_operations.cairo +++ b/crates/evm/src/instructions/stop_and_arithmetic_operations.cairo @@ -2,7 +2,7 @@ use evm::errors::EVMError; use evm::gas; -use evm::machine::{Machine, MachineTrait}; +use evm::model::vm::{VM, VMTrait}; use evm::stack::StackTrait; use integer::{ @@ -17,8 +17,8 @@ impl StopAndArithmeticOperations of StopAndArithmeticOperationsTrait { /// 0x00 - STOP /// Halts the execution of the current program. /// # Specification: https://www.evm.codes/#00?fork=shanghai - fn exec_stop(ref self: Machine) -> Result<(), EVMError> { - self.set_stopped(); + fn exec_stop(ref self: VM) -> Result<(), EVMError> { + self.stop(); Result::Ok(()) } @@ -26,8 +26,8 @@ impl StopAndArithmeticOperations of StopAndArithmeticOperationsTrait { /// Addition operation /// a + b: integer result of the addition modulo 2^256. /// # Specification: https://www.evm.codes/#01?fork=shanghai - fn exec_add(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::VERYLOW)?; + fn exec_add(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; let popped = self.stack.pop_n(2)?; // Compute the addition @@ -40,8 +40,8 @@ impl StopAndArithmeticOperations of StopAndArithmeticOperationsTrait { /// Multiplication /// a * b: integer result of the multiplication modulo 2^256. /// # Specification: https://www.evm.codes/#02?fork=shanghai - fn exec_mul(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::LOW)?; + fn exec_mul(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::LOW)?; let popped = self.stack.pop_n(2)?; // Compute the multiplication @@ -54,8 +54,8 @@ impl StopAndArithmeticOperations of StopAndArithmeticOperationsTrait { /// Subtraction operation /// a - b: integer result of the subtraction modulo 2^256. /// # Specification: https://www.evm.codes/#03?fork=shanghai - fn exec_sub(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::VERYLOW)?; + fn exec_sub(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::VERYLOW)?; let popped = self.stack.pop_n(2)?; // Compute the subtraction @@ -68,8 +68,8 @@ impl StopAndArithmeticOperations of StopAndArithmeticOperationsTrait { /// If the denominator is 0, the result will be 0. /// a / b: integer result of the integer division. /// # Specification: https://www.evm.codes/#04?fork=shanghai - fn exec_div(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::LOW)?; + fn exec_div(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::LOW)?; let popped = self.stack.pop_n(2)?; let a: u256 = *popped[0]; @@ -91,8 +91,8 @@ impl StopAndArithmeticOperations of StopAndArithmeticOperationsTrait { /// a / b: integer result of the signed integer division. /// If the denominator is 0, the result will be 0. /// # Specification: https://www.evm.codes/#05?fork=shanghai - fn exec_sdiv(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::LOW)?; + fn exec_sdiv(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::LOW)?; let a: i256 = self.stack.pop_i256()?; let b: i256 = self.stack.pop_i256()?; @@ -108,8 +108,8 @@ impl StopAndArithmeticOperations of StopAndArithmeticOperationsTrait { /// Modulo operation /// a % b: integer result of the integer modulo. If the denominator is 0, the result will be 0. /// # Specification: https://www.evm.codes/#06?fork=shanghai - fn exec_mod(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::LOW)?; + fn exec_mod(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::LOW)?; let popped = self.stack.pop_n(2)?; let a: u256 = *popped[0]; @@ -131,8 +131,8 @@ impl StopAndArithmeticOperations of StopAndArithmeticOperationsTrait { /// a % b: integer result of the signed integer modulo. If the denominator is 0, the result will be 0. /// All values are treated as two’s complement signed 256-bit integers. Note the overflow semantic when −2^255 is negated. /// # Specification: https://www.evm.codes/#07?fork=shanghai - fn exec_smod(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::LOW)?; + fn exec_smod(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::LOW)?; let a: i256 = self.stack.pop_i256()?; let b: i256 = self.stack.pop_i256()?; @@ -149,8 +149,8 @@ impl StopAndArithmeticOperations of StopAndArithmeticOperationsTrait { /// (a + b) % N: integer result of the addition followed by a modulo. If the denominator is 0, the result will be 0. /// All intermediate calculations of this operation are not subject to the 2256 modulo. /// # Specification: https://www.evm.codes/#08?fork=shanghai - fn exec_addmod(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::MID)?; + fn exec_addmod(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::MID)?; let popped = self.stack.pop_n(3)?; let a: u256 = *popped[0]; @@ -175,8 +175,8 @@ impl StopAndArithmeticOperations of StopAndArithmeticOperationsTrait { /// All intermediate calculations of this operation are not subject to the 2^256 modulo. /// If the denominator is 0, the result will be 0. /// # Specification: https://www.evm.codes/#09?fork=shanghai - fn exec_mulmod(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::MID)?; + fn exec_mulmod(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::MID)?; let a: u256 = self.stack.pop()?; let b: u256 = self.stack.pop()?; let n = self.stack.pop()?; @@ -198,9 +198,9 @@ impl StopAndArithmeticOperations of StopAndArithmeticOperationsTrait { /// Exponential operation /// a ** b: integer result of raising a to the bth power modulo 2^256. /// # Specification: https://www.evm.codes/#0a?fork=shanghai - fn exec_exp(ref self: Machine) -> Result<(), EVMError> { + fn exec_exp(ref self: VM) -> Result<(), EVMError> { // TODO: Add dynamic gas - self.increment_gas_used_checked(gas::HIGH)?; + self.charge_gas(gas::HIGH)?; let a = self.stack.pop()?; let b = self.stack.pop()?; @@ -226,8 +226,8 @@ impl StopAndArithmeticOperations of StopAndArithmeticOperationsTrait { /// which corresponds to (x & mask). /// # Specification: https://www.evm.codes/#0b?fork=shanghai /// Complex opcode, check: https://ethereum.github.io/yellowpaper/paper.pdf - fn exec_signextend(ref self: Machine) -> Result<(), EVMError> { - self.increment_gas_used_checked(gas::LOW)?; + fn exec_signextend(ref self: VM) -> Result<(), EVMError> { + self.charge_gas(gas::LOW)?; let b = self.stack.pop()?; let x = self.stack.pop()?; diff --git a/crates/evm/src/instructions/system_operations.cairo b/crates/evm/src/instructions/system_operations.cairo index b781f6ffd..f68b1144d 100644 --- a/crates/evm/src/instructions/system_operations.cairo +++ b/crates/evm/src/instructions/system_operations.cairo @@ -2,44 +2,43 @@ use box::BoxTrait; use contracts::kakarot_core::{KakarotCore, IKakarotCore}; -use evm::call_helpers::{MachineCallHelpers, CallType}; -use evm::create_helpers::{MachineCreateHelpers, CreateType}; +use evm::call_helpers::{CallHelpers, CallType}; +use evm::create_helpers::{CreateHelpers, CreateType}; use evm::errors::{EVMError, VALUE_TRANSFER_IN_STATIC_CALL, WRITE_IN_STATIC_CONTEXT}; use evm::gas; -use evm::machine::{Machine, MachineTrait}; use evm::memory::MemoryTrait; use evm::model::account::{AccountTrait}; +use evm::model::vm::{VM, VMTrait}; use evm::model::{Address, Transfer}; use evm::stack::StackTrait; use evm::state::StateTrait; use utils::math::Exponentiation; - #[generate_trait] impl SystemOperations of SystemOperationsTrait { /// CREATE /// # Specification: https://www.evm.codes/#f0?fork=shanghai - fn exec_create(ref self: Machine) -> Result<(), EVMError> { - if self.read_only() { + fn exec_create(ref self: VM) -> Result<(), EVMError> { + if self.message().read_only { return Result::Err(EVMError::WriteInStaticContext(WRITE_IN_STATIC_CONTEXT)); } // TODO: add dynamic gas cost - self.increment_gas_used_checked(gas::CREATE)?; - - let create_args = self.prepare_create(CreateType::CreateOrDeployTx)?; + self.charge_gas(gas::CREATE)?; - self.init_create_sub_ctx(create_args) + let create_args = self.prepare_create(CreateType::Create)?; + self.generic_create(create_args) } + /// CALL /// # Specification: https://www.evm.codes/#f1?fork=shanghai - fn exec_call(ref self: Machine) -> Result<(), EVMError> { + fn exec_call(ref self: VM) -> Result<(), EVMError> { // TODO: add dynamic gas cost and handle warm/cold storage - self.increment_gas_used_checked(gas::WARM_STORAGE_READ_COST)?; + self.charge_gas(gas::WARM_STORAGE_READ_COST)?; let call_args = self.prepare_call(@CallType::Call)?; - let read_only = self.read_only(); + let read_only = self.message().read_only; let value = call_args.value; // Check if current context is read only that value == 0. @@ -49,32 +48,38 @@ impl SystemOperations of SystemOperationsTrait { // If sender_balance < value, return early, pushing // 0 on the stack to indicate call failure. - let caller_address = self.address(); - let sender_balance = self.state.get_account(caller_address.evm).balance(); + let caller_address = self.message().target; + let sender_balance = self.env.state.get_account(caller_address.evm).balance(); if sender_balance < value { return self.stack.push(0); } // Initialize the sub context. - self.init_call_sub_ctx(call_args, read_only) + // TODO(elias) + // create a new sub context here + // with the correct arguments + // let result = sub_ctx.process_message(); + // store the return data in the memory of the parent context with the correct offsets and size + // store the return data whole in the return data field of the parent context + self.generic_call(call_args) } + /// CALLCODE /// # Specification: https://www.evm.codes/#f2?fork=shanghai - fn exec_callcode(ref self: Machine) -> Result<(), EVMError> { + fn exec_callcode(ref self: VM) -> Result<(), EVMError> { // TODO: add dynamic gas cost and handle warm/cold storage - self.increment_gas_used_checked(gas::WARM_STORAGE_READ_COST)?; + self.charge_gas(gas::WARM_STORAGE_READ_COST)?; let call_args = self.prepare_call(@CallType::CallCode)?; - let read_only = self.read_only(); - // Initialize the sub context. - self.init_call_sub_ctx(call_args, read_only) + self.generic_call(call_args) } /// RETURN /// # Specification: https://www.evm.codes/#f3?fork=shanghai - fn exec_return(ref self: Machine) -> Result<(), EVMError> { + fn exec_return(ref self: VM) -> Result<(), EVMError> { // TODO: add dynamic gas + self.charge_gas(gas::ZERO)?; let offset = self.stack.pop_usize()?; let size = self.stack.pop_usize()?; @@ -85,57 +90,51 @@ impl SystemOperations of SystemOperationsTrait { // Set the memory data to the parent context return data // and halt the context. self.set_return_data(return_data.span()); - self.set_stopped(); + self.stop(); Result::Ok(()) } /// DELEGATECALL /// # Specification: https://www.evm.codes/#f4?fork=shanghai - fn exec_delegatecall(ref self: Machine) -> Result<(), EVMError> { + fn exec_delegatecall(ref self: VM) -> Result<(), EVMError> { // TODO: add dynamic gas cost and handle warm/cold storage - self.increment_gas_used_checked(gas::WARM_STORAGE_READ_COST)?; + self.charge_gas(gas::WARM_STORAGE_READ_COST)?; let call_args = self.prepare_call(@CallType::DelegateCall)?; - let read_only = self.read_only(); - - // Initialize the sub context. - self.init_call_sub_ctx(call_args, read_only) + self.generic_call(call_args) } /// CREATE2 /// # Specification: https://www.evm.codes/#f5?fork=shanghai - fn exec_create2(ref self: Machine) -> Result<(), EVMError> { - if self.read_only() { + fn exec_create2(ref self: VM) -> Result<(), EVMError> { + if self.message().read_only { return Result::Err(EVMError::WriteInStaticContext(WRITE_IN_STATIC_CONTEXT)); } // TODO: add dynamic gas costs - self.increment_gas_used_checked(gas::CREATE)?; + self.charge_gas(gas::CREATE)?; let create_args = self.prepare_create(CreateType::Create2)?; - - self.init_create_sub_ctx(create_args) + self.generic_create(create_args) } /// STATICCALL /// # Specification: https://www.evm.codes/#fa?fork=shanghai - fn exec_staticcall(ref self: Machine) -> Result<(), EVMError> { + fn exec_staticcall(ref self: VM) -> Result<(), EVMError> { // TODO: add dynamic gas cost and handle warm/cold storage - self.increment_gas_used_checked(gas::WARM_STORAGE_READ_COST)?; + self.charge_gas(gas::WARM_STORAGE_READ_COST)?; let call_args = self.prepare_call(@CallType::StaticCall)?; - let read_only = self.read_only(); - // Initialize the sub context. - self.init_call_sub_ctx(call_args, read_only) + self.generic_call(call_args) } /// REVERT /// # Specification: https://www.evm.codes/#fd?fork=shanghai - fn exec_revert(ref self: Machine) -> Result<(), EVMError> { + fn exec_revert(ref self: VM) -> Result<(), EVMError> { // TODO: add dynamic gas - self.increment_gas_used_checked(gas::ZERO)?; + self.charge_gas(gas::ZERO)?; let offset = self.stack.pop_usize()?; let size = self.stack.pop_usize()?; @@ -146,39 +145,40 @@ impl SystemOperations of SystemOperationsTrait { // Set the memory data to the parent context return data // and halt the context. self.set_return_data(return_data.span()); - self.set_reverted(); + self.stop(); + self.set_error(); Result::Ok(()) } /// INVALID /// # Specification: https://www.evm.codes/#fe?fork=shanghai - fn exec_invalid(ref self: Machine) -> Result<(), EVMError> { + fn exec_invalid(ref self: VM) -> Result<(), EVMError> { Result::Err(EVMError::InvalidOpcode(0xfe)) } /// SELFDESTRUCT /// # Specification: https://www.evm.codes/#ff?fork=shanghai - fn exec_selfdestruct(ref self: Machine) -> Result<(), EVMError> { - if self.read_only() { + fn exec_selfdestruct(ref self: VM) -> Result<(), EVMError> { + if self.message().read_only { return Result::Err(EVMError::WriteInStaticContext(WRITE_IN_STATIC_CONTEXT)); } // TODO: add dynamic gas costs - self.increment_gas_used_checked(gas::SELFDESTRUCT)?; + self.charge_gas(gas::SELFDESTRUCT)?; let kakarot_state = KakarotCore::unsafe_new_contract_state(); let address = self.stack.pop_eth_address()?; //TODO Remove this when https://eips.ethereum.org/EIPS/eip-6780 is validated - let recipient_evm_address = if (address == self.address().evm) { + let recipient_evm_address = if (address == self.message().target.evm) { 0.try_into().unwrap() } else { address }; let recipient_starknet_address = kakarot_state .compute_starknet_address(recipient_evm_address); - let mut account = self.state.get_account(self.address().evm); + let mut account = self.env.state.get_account(self.message().target.evm); let recipient = Address { evm: recipient_evm_address, starknet: recipient_starknet_address @@ -186,19 +186,20 @@ impl SystemOperations of SystemOperationsTrait { // Transfer balance self + .env .state .add_transfer( Transfer { sender: account.address(), recipient, - amount: self.state.get_account(account.address().evm).balance + amount: self.env.state.get_account(account.address().evm).balance } )?; // Register for selfdestruct account.selfdestruct(); - self.state.set_account(account); - self.set_stopped(); + self.env.state.set_account(account); + self.stop(); Result::Ok(()) } } diff --git a/crates/evm/src/interpreter.cairo b/crates/evm/src/interpreter.cairo index e5731a7bf..76cf12d4e 100644 --- a/crates/evm/src/interpreter.cairo +++ b/crates/evm/src/interpreter.cairo @@ -1,12 +1,6 @@ -/// System imports. +use evm::call_helpers::is_precompile; +use evm::errors::{EVMError, PC_OUT_OF_BOUNDS, EVMErrorTrait, CONTRACT_ACCOUNT_EXISTS}; -/// Internal imports. -use evm::call_helpers::MachineCallHelpers; -use evm::context::{CallContextTrait, Status}; -use evm::context::{ExecutionContextTrait, ExecutionContext, ExecutionContextType}; -use evm::create_helpers::MachineCreateHelpers; -use evm::errors::EVMErrorTrait; -use evm::errors::{EVMError, PC_OUT_OF_BOUNDS}; use evm::instructions::{ duplication_operations, environmental_information, ExchangeOperationsTrait, logging_operations, LoggingOperationsTrait, memory_operations, sha3, StopAndArithmeticOperationsTrait, @@ -14,687 +8,749 @@ use evm::instructions::{ DuplicationOperationsTrait, EnvironmentInformationTrait, PushOperationsTrait, MemoryOperationTrait }; -use evm::machine::{Machine, MachineTrait}; -use evm::model::account::AccountTrait; -use evm::state::StateTrait; -use utils::helpers::{U256Trait}; -#[derive(Drop, Copy)] -struct EVMInterpreter {} +use evm::model::account::{AccountTrait}; +use evm::model::vm::{VM, VMTrait}; +use evm::model::{ + Message, Environment, Address, Transfer, ExecutionSummary, ExecutionResult, AccountType +}; +use evm::stack::{Stack, StackTrait}; +use evm::state::{State, StateTrait}; +use starknet::{EthAddress, ContractAddress}; +use utils::helpers::{U256Trait, compute_starknet_address, EthAddressExTrait}; -trait EVMInterpreterTrait { - /// Create a new instance of the EVM Interpreter. - fn new() -> EVMInterpreter; - /// Execute the EVM bytecode. - fn run(ref self: EVMInterpreter, ref machine: Machine); - /// Decodes the opcode at `pc` and executes the associated function. - fn decode_and_execute(ref self: EVMInterpreter, ref machine: Machine) -> Result<(), EVMError>; - fn handle_revert(ref self: Machine, maybe_message: Option); - fn finalize_context(ref self: EVMInterpreter, ref machine: Machine) -> Result<(), EVMError>; -} +#[generate_trait] +impl EVMImpl of EVMTrait { + fn process_message_call( + message: Message, mut env: Environment, is_deploy_tx: bool, + ) -> ExecutionSummary { + let mut target_account = env.state.get_account(message.target.evm); + if is_deploy_tx { + // Check collision + if target_account.has_code_or_nonce() { + return ExecutionSummary { + state: env.state, + address: message.target.evm, + success: false, + return_data: Into::< + felt252, u256 + >::into(EVMError::DeployError(CONTRACT_ACCOUNT_EXISTS).to_string()) + .to_bytes(), + }; + } + + let mut result = EVMTrait::process_create_message(message, ref env); + if result.success { + result.return_data = message.target.evm.to_bytes().span(); + } + return ExecutionSummary { + state: env.state, + address: message.target.evm, + success: result.success, + return_data: result.return_data, + }; + } -impl EVMInterpreterImpl of EVMInterpreterTrait { - #[inline(always)] - fn new() -> EVMInterpreter { - EVMInterpreter {} + // No need to take snapshot of state, as the state is still empty at this point. + let result = EVMTrait::process_message(message, ref env); + ExecutionSummary { + success: result.success, + address: message.target.evm, + state: env.state, + return_data: result.return_data, + } } - fn run(ref self: EVMInterpreter, ref machine: Machine) { - // Decode and execute the current opcode. - let result = self.decode_and_execute(ref machine); + fn process_create_message(message: Message, ref env: Environment) -> ExecutionResult { + //TODO(optimization) - Since the effects of executed code are + //reverted in the `process_message` function already, + // we only need to revert the changes made to the target account. Take a + // snapshot of the environment state so that we can revert if the + let state_snapshot = env.state.clone(); + let target_evm_address = message.target.evm; + let mut target_account = env.state.get_account(target_evm_address); - match result { - Result::Ok(_) => { - match machine.status() { - Status::Active => { - // execute the next opcode - return self.run(ref machine); - }, - Status::Stopped => {}, - Status::Reverted => { machine.handle_revert(Option::None); } + // Increment nonce of target + target_account.set_nonce(1); + target_account.set_type(AccountType::ContractAccount); + target_account.address = *(@message.target); + env.state.set_account(target_account); + + let result = EVMTrait::process_message(message, ref env); + + if result.success { + // Write the return_data of the initcode + // as the deployed contract's bytecode + //TODO(gas) charge gas on contract code length + // Don't forget to revert the state if the gas charging fails. + let code = result.return_data; + target_account.set_code(code); + env.state.set_account(target_account); + } else { + // Revert state to the snapshot taken before the create processing. + env.state = state_snapshot; + } + result + } + + fn process_message(message: Message, ref env: Environment) -> ExecutionResult { + let state_snapshot = env.state.clone(); + if message.should_transfer_value && message.value != 0 { + let transfer = Transfer { + sender: message.caller, recipient: message.target, amount: message.value + }; + match env.state.add_transfer(transfer) { + Result::Ok(_) => {}, + Result::Err(err) => { + return ExecutionResult { + success: false, + //TODO(optimization) avoid converstion to u256 to get bytes + return_data: Into::::into(err.to_string()).to_bytes(), + gas_used: 0, + }; } - }, - Result::Err(error) => { - // If an error occurred, revert execution machine. - // Currently, revert reason is a Span. - machine.set_reverted(); - machine.handle_revert(Option::Some(error)); } } - //TODO handle this error gracefully - self.finalize_context(ref machine).expect('Failed to finalize context'); + + // Handle precompile logic + if is_precompile(message.target.evm) { + panic!("Not Implemented: Precompiles are not implemented yet"); + } + + // Instantiate a new VM using the to process message and the current environment. + let mut vm: VM = VMTrait::new(message, env); + + // Decode and execute the current opcode. + // until we have processed all opcodes or until we have stopped. + // Use a recursive function to allow passing VM by ref - which wouldn't work in a loop; + let result = EVMTrait::execute_code(ref vm); + + // Retrieve ownership of the `env` variable + // The state in the environment has been modified by the VM. + // Handling state reverts is done at a higher level, using previously taken state snapshots. + env = vm.env; + + if !result.success { + // The `process_message` function has mutated the environment state. + // Revert state changes using the old snapshot as execution failed. + env.state = state_snapshot; + } + + result } - fn decode_and_execute(ref self: EVMInterpreter, ref machine: Machine) -> Result<(), EVMError> { + fn execute_code(ref vm: VM) -> ExecutionResult { // Retrieve the current program counter. - let pc = machine.pc(); - - let bytecode = machine.call_ctx().bytecode(); - let bytecode_len = bytecode.len(); + let pc = vm.pc(); + let bytecode = vm.message().code; // Check if PC is not out of bounds. - if pc >= bytecode_len { - machine.set_stopped(); - return Result::Ok(()); + if pc >= bytecode.len() || vm.is_running() == false { + return ExecutionResult { + success: true, return_data: vm.return_data(), gas_used: vm.gas_used() + }; } let opcode: u8 = *bytecode.at(pc); // Increment pc - machine.set_pc(pc + 1); + vm.set_pc(pc + 1); + + match EVMTrait::execute_opcode(ref vm, opcode) { + Result::Ok(_) => { + if vm.is_running() { + return EVMTrait::execute_code(ref vm); + } + return ExecutionResult { + success: true, return_data: vm.return_data(), gas_used: vm.gas_used() + }; + }, + Result::Err(error) => { + // If an error occurred, revert execution self. + // Currently, revert reason is a Span. + return ExecutionResult { + success: false, + return_data: Into::::into(error.to_string()).to_bytes(), + gas_used: vm.gas_used(), + }; + } + } + } + fn execute_opcode(ref self: VM, opcode: u8) -> Result<(), EVMError> { // Call the appropriate function based on the opcode. if opcode == 0 { // STOP - return machine.exec_stop(); + return self.exec_stop(); } if opcode == 1 { // ADD - return machine.exec_add(); + return self.exec_add(); } if opcode == 2 { // MUL - return machine.exec_mul(); + return self.exec_mul(); } if opcode == 3 { // SUB - return machine.exec_sub(); + return self.exec_sub(); } if opcode == 4 { // DIV - return machine.exec_div(); + return self.exec_div(); } if opcode == 5 { // SDIV - return machine.exec_sdiv(); + return self.exec_sdiv(); } if opcode == 6 { // MOD - return machine.exec_mod(); + return self.exec_mod(); } if opcode == 7 { // SMOD - return machine.exec_smod(); + return self.exec_smod(); } if opcode == 8 { // ADDMOD - return machine.exec_addmod(); + return self.exec_addmod(); } if opcode == 9 { // MULMOD - return machine.exec_mulmod(); + return self.exec_mulmod(); } if opcode == 10 { // EXP - return machine.exec_exp(); + return self.exec_exp(); } if opcode == 11 { // SIGNEXTEND - return machine.exec_signextend(); + return self.exec_signextend(); } if opcode == 16 { // LT - return machine.exec_lt(); + return self.exec_lt(); } if opcode == 17 { // GT - return machine.exec_gt(); + return self.exec_gt(); } if opcode == 18 { // SLT - return machine.exec_slt(); + return self.exec_slt(); } if opcode == 19 { // SGT - return machine.exec_sgt(); + return self.exec_sgt(); } if opcode == 20 { // EQ - return machine.exec_eq(); + return self.exec_eq(); } if opcode == 21 { // ISZERO - return machine.exec_iszero(); + return self.exec_iszero(); } if opcode == 22 { // AND - return machine.exec_and(); + return self.exec_and(); } if opcode == 23 { // OR - return machine.exec_or(); + return self.exec_or(); } if opcode == 24 { // XOR - return machine.exec_xor(); + return self.exec_xor(); } if opcode == 25 { // NOT - return machine.exec_not(); + return self.exec_not(); } if opcode == 26 { // BYTE - return machine.exec_byte(); + return self.exec_byte(); } if opcode == 27 { // SHL - return machine.exec_shl(); + return self.exec_shl(); } if opcode == 28 { // SHR - return machine.exec_shr(); + return self.exec_shr(); } if opcode == 29 { // SAR - return machine.exec_sar(); + return self.exec_sar(); } if opcode == 48 { // ADDRESS - return machine.exec_address(); + return self.exec_address(); } if opcode == 49 { // BALANCE - return machine.exec_balance(); + return self.exec_balance(); } if opcode == 50 { // ORIGIN - return machine.exec_origin(); + return self.exec_origin(); } if opcode == 51 { // CALLER - return machine.exec_caller(); + return self.exec_caller(); } if opcode == 52 { // CALLVALUE - return machine.exec_callvalue(); + return self.exec_callvalue(); } if opcode == 53 { // CALLDATALOAD - return machine.exec_calldataload(); + return self.exec_calldataload(); } if opcode == 54 { // CALLDATASIZE - return machine.exec_calldatasize(); + return self.exec_calldatasize(); } if opcode == 55 { // CALLDATACOPY - return machine.exec_calldatacopy(); + return self.exec_calldatacopy(); } if opcode == 56 { // CODESIZE - return machine.exec_codesize(); + return self.exec_codesize(); } if opcode == 57 { // CODECOPY - return machine.exec_codecopy(); + return self.exec_codecopy(); } if opcode == 58 { // GASPRICE - return machine.exec_gasprice(); + return self.exec_gasprice(); } if opcode == 59 { // EXTCODESIZE - return machine.exec_extcodesize(); + return self.exec_extcodesize(); } if opcode == 60 { // EXTCODECOPY - return machine.exec_extcodecopy(); + return self.exec_extcodecopy(); } if opcode == 61 { // RETURNDATASIZE - return machine.exec_returndatasize(); + return self.exec_returndatasize(); } if opcode == 62 { // RETURNDATACOPY - return machine.exec_returndatacopy(); + return self.exec_returndatacopy(); } if opcode == 63 { // EXTCODEHASH - return machine.exec_extcodehash(); + return self.exec_extcodehash(); } if opcode == 64 { // BLOCKHASH - return machine.exec_blockhash(); + return self.exec_blockhash(); } if opcode == 65 { // COINBASE - return machine.exec_coinbase(); + return self.exec_coinbase(); } if opcode == 66 { // TIMESTAMP - return machine.exec_timestamp(); + return self.exec_timestamp(); } if opcode == 67 { // NUMBER - return machine.exec_number(); + return self.exec_number(); } if opcode == 68 { // PREVRANDAO - return machine.exec_prevrandao(); + return self.exec_prevrandao(); } if opcode == 69 { // GASLIMIT - return machine.exec_gaslimit(); + return self.exec_gaslimit(); } if opcode == 70 { // CHAINID - return machine.exec_chainid(); + return self.exec_chainid(); } if opcode == 71 { // SELFBALANCE - return machine.exec_selfbalance(); + return self.exec_selfbalance(); } if opcode == 72 { // BASEFEE - return machine.exec_basefee(); + return self.exec_basefee(); } if opcode == 80 { // POP - return machine.exec_pop(); + return self.exec_pop(); } if opcode == 81 { // MLOAD - return machine.exec_mload(); + return self.exec_mload(); } if opcode == 82 { // MSTORE - return machine.exec_mstore(); + return self.exec_mstore(); } if opcode == 83 { // MSTORE8 - return machine.exec_mstore8(); + return self.exec_mstore8(); } if opcode == 84 { // SLOAD - return machine.exec_sload(); + return self.exec_sload(); } if opcode == 85 { // SSTORE - return machine.exec_sstore(); + return self.exec_sstore(); } if opcode == 86 { // JUMP - return machine.exec_jump(); + return self.exec_jump(); } if opcode == 87 { // JUMPI - return machine.exec_jumpi(); + return self.exec_jumpi(); } if opcode == 88 { // PC - return machine.exec_pc(); + return self.exec_pc(); } if opcode == 89 { // MSIZE - return machine.exec_msize(); + return self.exec_msize(); } if opcode == 90 { // GAS - return machine.exec_gas(); + return self.exec_gas(); } if opcode == 91 { // JUMPDEST - return machine.exec_jumpdest(); + return self.exec_jumpdest(); } if opcode == 95 { // PUSH0 - return machine.exec_push0(); + return self.exec_push0(); } if opcode == 96 { // PUSH1 - return machine.exec_push1(); + return self.exec_push1(); } if opcode == 97 { // PUSH2 - return machine.exec_push2(); + return self.exec_push2(); } if opcode == 98 { // PUSH3 - return machine.exec_push3(); + return self.exec_push3(); } if opcode == 99 { // PUSH4 - return machine.exec_push4(); + return self.exec_push4(); } if opcode == 100 { // PUSH5 - return machine.exec_push5(); + return self.exec_push5(); } if opcode == 101 { // PUSH6 - return machine.exec_push6(); + return self.exec_push6(); } if opcode == 102 { // PUSH7 - return machine.exec_push7(); + return self.exec_push7(); } if opcode == 103 { // PUSH8 - return machine.exec_push8(); + return self.exec_push8(); } if opcode == 104 { // PUSH9 - return machine.exec_push9(); + return self.exec_push9(); } if opcode == 105 { // PUSH10 - return machine.exec_push10(); + return self.exec_push10(); } if opcode == 106 { // PUSH11 - return machine.exec_push11(); + return self.exec_push11(); } if opcode == 107 { // PUSH12 - return machine.exec_push12(); + return self.exec_push12(); } if opcode == 108 { // PUSH13 - return machine.exec_push13(); + return self.exec_push13(); } if opcode == 109 { // PUSH14 - return machine.exec_push14(); + return self.exec_push14(); } if opcode == 110 { // PUSH15 - return machine.exec_push15(); + return self.exec_push15(); } if opcode == 111 { // PUSH16 - return machine.exec_push16(); + return self.exec_push16(); } if opcode == 112 { // PUSH17 - return machine.exec_push17(); + return self.exec_push17(); } if opcode == 113 { // PUSH18 - return machine.exec_push18(); + return self.exec_push18(); } if opcode == 114 { // PUSH19 - return machine.exec_push19(); + return self.exec_push19(); } if opcode == 115 { // PUSH20 - return machine.exec_push20(); + return self.exec_push20(); } if opcode == 116 { // PUSH21 - return machine.exec_push21(); + return self.exec_push21(); } if opcode == 117 { // PUSH22 - return machine.exec_push22(); + return self.exec_push22(); } if opcode == 118 { // PUSH23 - return machine.exec_push23(); + return self.exec_push23(); } if opcode == 119 { // PUSH24 - return machine.exec_push24(); + return self.exec_push24(); } if opcode == 120 { // PUSH25 - return machine.exec_push25(); + return self.exec_push25(); } if opcode == 121 { // PUSH26 - return machine.exec_push26(); + return self.exec_push26(); } if opcode == 122 { // PUSH27 - return machine.exec_push27(); + return self.exec_push27(); } if opcode == 123 { // PUSH28 - return machine.exec_push28(); + return self.exec_push28(); } if opcode == 124 { // PUSH29 - return machine.exec_push29(); + return self.exec_push29(); } if opcode == 125 { // PUSH30 - return machine.exec_push30(); + return self.exec_push30(); } if opcode == 126 { // PUSH31 - return machine.exec_push31(); + return self.exec_push31(); } if opcode == 127 { // PUSH32 - return machine.exec_push32(); + return self.exec_push32(); } if opcode == 128 { // DUP1 - return machine.exec_dup1(); + return self.exec_dup1(); } if opcode == 129 { // DUP2 - return machine.exec_dup2(); + return self.exec_dup2(); } if opcode == 130 { // DUP3 - return machine.exec_dup3(); + return self.exec_dup3(); } if opcode == 131 { // DUP4 - return machine.exec_dup4(); + return self.exec_dup4(); } if opcode == 132 { // DUP5 - return machine.exec_dup5(); + return self.exec_dup5(); } if opcode == 133 { // DUP6 - return machine.exec_dup6(); + return self.exec_dup6(); } if opcode == 134 { // DUP7 - return machine.exec_dup7(); + return self.exec_dup7(); } if opcode == 135 { // DUP8 - return machine.exec_dup8(); + return self.exec_dup8(); } if opcode == 136 { // DUP9 - return machine.exec_dup9(); + return self.exec_dup9(); } if opcode == 137 { // DUP10 - return machine.exec_dup10(); + return self.exec_dup10(); } if opcode == 138 { // DUP11 - return machine.exec_dup11(); + return self.exec_dup11(); } if opcode == 139 { // DUP12 - return machine.exec_dup12(); + return self.exec_dup12(); } if opcode == 140 { // DUP13 - return machine.exec_dup13(); + return self.exec_dup13(); } if opcode == 141 { // DUP14 - return machine.exec_dup14(); + return self.exec_dup14(); } if opcode == 142 { // DUP15 - return machine.exec_dup15(); + return self.exec_dup15(); } if opcode == 143 { // DUP16 - return machine.exec_dup16(); + return self.exec_dup16(); } if opcode == 144 { // SWAP1 - return machine.exec_swap1(); + return self.exec_swap1(); } if opcode == 145 { // SWAP2 - return machine.exec_swap2(); + return self.exec_swap2(); } if opcode == 146 { // SWAP3 - return machine.exec_swap3(); + return self.exec_swap3(); } if opcode == 147 { // SWAP4 - return machine.exec_swap4(); + return self.exec_swap4(); } if opcode == 148 { // SWAP5 - return machine.exec_swap5(); + return self.exec_swap5(); } if opcode == 149 { // SWAP6 - return machine.exec_swap6(); + return self.exec_swap6(); } if opcode == 150 { // SWAP7 - return machine.exec_swap7(); + return self.exec_swap7(); } if opcode == 151 { // SWAP8 - return machine.exec_swap8(); + return self.exec_swap8(); } if opcode == 152 { // SWAP9 - return machine.exec_swap9(); + return self.exec_swap9(); } if opcode == 153 { // SWAP10 - return machine.exec_swap10(); + return self.exec_swap10(); } if opcode == 154 { // SWAP11 - return machine.exec_swap11(); + return self.exec_swap11(); } if opcode == 155 { // SWAP12 - return machine.exec_swap12(); + return self.exec_swap12(); } if opcode == 156 { // SWAP13 - return machine.exec_swap13(); + return self.exec_swap13(); } if opcode == 157 { // SWAP14 - return machine.exec_swap14(); + return self.exec_swap14(); } if opcode == 158 { // SWAP15 - return machine.exec_swap15(); + return self.exec_swap15(); } if opcode == 159 { // SWAP16 - return machine.exec_swap16(); + return self.exec_swap16(); } if opcode == 160 { // LOG0 - return machine.exec_log0(); + return self.exec_log0(); } if opcode == 161 { // LOG1 - return machine.exec_log1(); + return self.exec_log1(); } if opcode == 162 { // LOG2 - return machine.exec_log2(); + return self.exec_log2(); } if opcode == 163 { // LOG3 - return machine.exec_log3(); + return self.exec_log3(); } if opcode == 164 { // LOG4 - return machine.exec_log4(); + return self.exec_log4(); } if opcode == 240 { // CREATE - return machine.exec_create(); + return self.exec_create(); } if opcode == 241 { // CALL - return machine.exec_call(); + return self.exec_call(); } if opcode == 242 { // CALLCODE - return machine.exec_callcode(); + return self.exec_callcode(); } if opcode == 243 { // RETURN - return machine.exec_return(); + return self.exec_return(); } if opcode == 244 { // DELEGATECALL - return machine.exec_delegatecall(); + return self.exec_delegatecall(); } if opcode == 245 { // CREATE2 - return machine.exec_create2(); + return self.exec_create2(); } if opcode == 250 { // STATICCALL - return machine.exec_staticcall(); + return self.exec_staticcall(); } if opcode == 253 { // REVERT - return machine.exec_revert(); + return self.exec_revert(); } if opcode == 254 { // INVALID - return machine.exec_invalid(); + return self.exec_invalid(); } if opcode == 255 { // SELFDESTRUCT - return machine.exec_selfdestruct(); + return self.exec_selfdestruct(); } // Unknown opcode return Result::Err(EVMError::InvalidOpcode(opcode)); } - - /// Finalizes the revert of an execution context. - /// Clears all pending state journal entries, not finalizing the pending state changes applied inside this context. - fn handle_revert(ref self: Machine, maybe_message: Option) { - self.state.clear_context(); - match maybe_message { - Option::Some(msg) => { - let msg_string: u256 = msg.to_string().into(); - let msg_bytes = msg_string.to_bytes(); - self.set_return_data(msg_bytes); - }, - Option::None => {} - } - } - - /// Finalizes the changes performed during a context by applying them to the - /// transactional changes. - fn finalize_context(ref self: EVMInterpreter, ref machine: Machine) -> Result<(), EVMError> { - match machine.ctx_type() { - ExecutionContextType::Root(is_create) => { - // In case of a deploy tx, we need to store the return_data in the account. - if is_create { - let mut deployed_account = machine.state.get_account(machine.address().evm); - deployed_account.set_code(machine.return_data()); - machine.state.set_account(deployed_account); - } - }, - ExecutionContextType::Call(_) => { - machine.finalize_calling_context()?; - self.run(ref machine); - }, - ExecutionContextType::Create(_) => { - machine.finalize_create_context()?; - self.run(ref machine); - } - } - machine.state.commit_context(); - Result::Ok(()) - } } diff --git a/crates/evm/src/lib.cairo b/crates/evm/src/lib.cairo index bb4d754ba..db066622a 100644 --- a/crates/evm/src/lib.cairo +++ b/crates/evm/src/lib.cairo @@ -1,19 +1,12 @@ // Call opcodes helpers mod call_helpers; - -// Context module -mod context; - // Create opcodes helpers mod create_helpers; // Errors module mod errors; -// Kakarot main module -mod execution; - // Gas module mod gas; @@ -23,9 +16,6 @@ mod instructions; // interpreter module mod interpreter; -// Machine module -mod machine; - // Memory module mod memory; diff --git a/crates/evm/src/machine.cairo b/crates/evm/src/machine.cairo deleted file mode 100644 index f2f3cbd4a..000000000 --- a/crates/evm/src/machine.cairo +++ /dev/null @@ -1,314 +0,0 @@ -use evm::errors::{EVMError, MISSING_PARENT_CONTEXT}; -use evm::model::Address; -use evm::state::State; -use evm::{ - context::{ - ExecutionContext, ExecutionContextType, ExecutionContextTrait, DefaultBoxExecutionContext, - CallContext, CallContextTrait, Status, Event - }, - stack::{Stack, StackTrait}, memory::{Memory, MemoryTrait} -}; - -use nullable::{match_nullable, FromNullableResult}; - -use starknet::{EthAddress, ContractAddress}; - -#[derive(Destruct)] -struct Machine { - current_ctx: Box, - ctx_count: usize, - stack: Stack, - memory: Memory, - state: State, -} - -impl DefaultMachine of Default { - fn default() -> Machine { - Machine { - current_ctx: Default::default(), - ctx_count: 1, - stack: Default::default(), - memory: Default::default(), - state: Default::default(), - } - } -} - -#[derive(Destruct)] -struct MachineBuilder { - machine: Machine -} - -#[generate_trait] -impl MachineBuilderImpl of MachineBuilderTrait { - fn new() -> MachineBuilder { - MachineBuilder { machine: Default::default() } - } - - #[inline(always)] - fn set_ctx(mut self: MachineBuilder, ctx: ExecutionContext) -> MachineBuilder { - self.machine.current_ctx = BoxTrait::new(ctx); - self - } - - #[inline(always)] - fn set_state(mut self: MachineBuilder, state: State) -> MachineBuilder { - self.machine.state = state; - self - } - - #[inline(always)] - fn build(self: MachineBuilder) -> Machine { - self.machine - } -} -/// A set of getters and setters for the current context -/// Since current_ctx is a pointer to the current context being executed by the machine we're forced into the following pattern: -/// -/// For getters: -/// Unbox the current ExecutionContext -/// Access a value -/// Rebox the current ExecutionContext -/// -/// For setters: -/// Unbox the current ExecutionContext into a mut variable -/// Modify the desired field -/// Rebox the modified current ExecutionContext -/// -/// Limitations: -/// 1. We're not able to use @Machine as an argument for getters, as the ExecutionContext struct does not derive the Copy trait. -/// 2. We must use a box reference to the current context, as the changes made during execution must be applied -/// to only one ExecutionContext struct instance. Using a pointer ensures we never duplicate structs and thus changes. -#[generate_trait] -impl MachineImpl of MachineTrait { - #[inline(always)] - fn new(ctx: ExecutionContext) -> Machine { - Machine { - current_ctx: BoxTrait::new(ctx), - ctx_count: 1, - stack: Default::default(), - memory: Default::default(), - state: Default::default(), - } - } - - #[inline(always)] - fn id(self: @Machine) -> usize { - self.current_ctx.as_snapshot().unbox().id() - } - - /// Sets the current execution context being executed by the machine. - /// This is an implementation-specific concept that is used - /// to divide a unique Stack/Memory simulated by a dict into - /// multiple sub-structures relative to a single context. - #[inline(always)] - fn set_current_ctx(ref self: Machine, ctx: ExecutionContext) { - self.memory.set_active_segment(ctx.id()); - self.stack.set_active_segment(ctx.id()); - self.current_ctx = BoxTrait::new(ctx); - } - - #[inline(always)] - fn pc(self: @Machine) -> usize { - self.current_ctx.as_snapshot().unbox().pc() - } - - #[inline(always)] - fn set_pc(ref self: Machine, new_pc: u32) { - let mut current_execution_ctx = self.current_ctx.unbox(); - current_execution_ctx.program_counter = new_pc; - self.current_ctx = BoxTrait::new(current_execution_ctx); - } - - #[inline(always)] - fn set_reverted(ref self: Machine) { - let mut current_execution_ctx = self.current_ctx.unbox(); - current_execution_ctx.set_reverted(); - self.current_ctx = BoxTrait::new(current_execution_ctx); - } - - #[inline(always)] - fn reverted(self: @Machine) -> bool { - self.current_ctx.as_snapshot().unbox().reverted() - } - - #[inline(always)] - fn stopped(self: @Machine) -> bool { - self.current_ctx.as_snapshot().unbox().stopped() - } - - #[inline(always)] - fn status(self: @Machine) -> Status { - self.current_ctx.as_snapshot().unbox().status() - } - - #[inline(always)] - fn call_ctx(self: @Machine) -> CallContext { - (*self.current_ctx.as_snapshot().unbox().call_ctx).unbox() - } - - #[inline(always)] - fn gas_used(ref self: Machine) -> u128 { - self.current_ctx.as_snapshot().unbox().gas_used() - } - - #[inline(always)] - fn increment_gas_used_unchecked(ref self: Machine, gas: u128) { - let mut current_execution_ctx = self.current_ctx.unbox(); - current_execution_ctx.increment_gas_used_unchecked(gas); - self.current_ctx = BoxTrait::new(current_execution_ctx); - } - - #[inline(always)] - fn increment_gas_used_checked(ref self: Machine, gas: u128) -> Result<(), EVMError> { - let mut current_execution_ctx = self.current_ctx.unbox(); - let res = current_execution_ctx.increment_gas_used_checked(gas); - match res { - Result::Ok(_) => { - self.current_ctx = BoxTrait::new(current_execution_ctx); - Result::Ok(()) - }, - Result::Err(e) => { - self.current_ctx = BoxTrait::new(current_execution_ctx); - Result::Err(e) - } - } - } - - /// Returns from the sub context by setting the current context - /// to the parent context. - /// - /// # Errors - /// - InvalidMachineState: when the parent context is Null. - #[inline(always)] - fn return_to_parent_ctx(ref self: Machine) -> Result<(), EVMError> { - let mut current_ctx = self.current_ctx.unbox(); - let return_data = current_ctx.return_data(); - let maybe_parent_ctx = current_ctx.parent_ctx; - match match_nullable(maybe_parent_ctx) { - FromNullableResult::Null => { - // These two lines are used to satisfy the compiler, - // otherwise we get a `Value Was Previously Moved` Error - current_ctx.parent_ctx = Default::default(); - self.current_ctx = BoxTrait::new(current_ctx); - return Result::Err(EVMError::InvalidMachineState(MISSING_PARENT_CONTEXT)); - }, - FromNullableResult::NotNull(parent_ctx) => { - let mut parent_ctx = parent_ctx.unbox(); - parent_ctx.return_data = return_data; - current_ctx = parent_ctx; - }, - }; - // We need to rebox the current context after modifying it - // before calling a function - otherwise, we get a variable moved error - self.current_ctx = Default::default(); - self.set_current_ctx(current_ctx); - Result::Ok(()) - } - - #[inline(always)] - fn return_data(self: @Machine) -> Span { - *self.current_ctx.as_snapshot().unbox().return_data - } - - /// Stops the current execution context. - #[inline(always)] - fn set_stopped(ref self: Machine) { - let mut current_execution_ctx = self.current_ctx.unbox(); - current_execution_ctx.status = Status::Stopped; - self.current_ctx = BoxTrait::new(current_execution_ctx); - } - - - #[inline(always)] - fn address(self: @Machine) -> Address { - self.current_ctx.as_snapshot().unbox().address() - } - - #[inline(always)] - fn caller(self: @Machine) -> Address { - self.call_ctx().caller() - } - - #[inline(always)] - fn origin(self: @Machine) -> Address { - self.current_ctx.as_snapshot().unbox().origin() - } - - #[inline(always)] - fn read_only(self: @Machine) -> bool { - self.call_ctx().read_only() - } - - #[inline(always)] - fn gas_limit(self: @Machine) -> u128 { - self.call_ctx().gas_limit() - } - - #[inline(always)] - fn gas_price(self: @Machine) -> u128 { - self.call_ctx().gas_price() - } - - #[inline(always)] - fn value(self: @Machine) -> u256 { - self.call_ctx().value() - } - - #[inline(always)] - fn bytecode(self: @Machine) -> Span { - self.call_ctx().bytecode() - } - - #[inline(always)] - fn calldata(self: @Machine) -> Span { - self.call_ctx().calldata() - } - - - /// Reads and returns `size` elements from bytecode starting from the current value - /// `pc`. - /// # Arguments - /// - /// * `self` - The `Machine` instance to read the data from. - /// * The current execution context is handled implicitly by the Machine. - /// * `len` - The length of the data to read from the bytecode. - #[inline(always)] - fn read_code(ref self: Machine, len: usize) -> Span { - // Copy code slice from [pc, pc+len] - let pc = self.pc(); - let code = self.bytecode().slice(pc, len); - - code - } - - /// Returns the current execution context type (root, call or create). - #[inline(always)] - fn ctx_type(self: @Machine) -> ExecutionContextType { - self.current_ctx.as_snapshot().unbox().ctx_type() - } - - /// Returns whether the current execution context is the root context. - #[inline(always)] - fn is_root(self: @Machine) -> bool { - self.current_ctx.as_snapshot().unbox().is_root() - } - - /// Returns whether the current execution context is a call context. - #[inline(always)] - fn is_call(self: @Machine) -> bool { - self.current_ctx.as_snapshot().unbox().is_call() - } - - /// Sets the `return_data` field of the appropriate execution context, - /// taking into account EVM specs: If the current context is the root - /// context, sets the return_data field of the root context. If the current - /// context is a subcontext, sets the return_data field of the parent. - /// Should be called when returning from a context. - #[inline(always)] - fn set_return_data(ref self: Machine, value: Span) { - let mut current_ctx = self.current_ctx.unbox(); - current_ctx.return_data = value; - self.current_ctx = BoxTrait::new(current_ctx); - } -} diff --git a/crates/evm/src/memory.cairo b/crates/evm/src/memory.cairo index a66f2bbc0..171775aa2 100644 --- a/crates/evm/src/memory.cairo +++ b/crates/evm/src/memory.cairo @@ -17,16 +17,13 @@ const MEMORY_SEGMENT_SIZE: usize = 131072; #[derive(Destruct, Default)] struct Memory { - active_segment: usize, items: Felt252Dict, - bytes_len: Felt252Dict, + bytes_len: usize, } trait MemoryTrait { fn new() -> Memory; - fn set_active_segment(ref self: Memory, active_segment: usize); - fn size(ref self: Memory) -> usize; - fn active_segment(ref self: Memory) -> felt252; + fn size(self: @Memory) -> usize; fn store(ref self: Memory, element: u256, offset: usize); fn store_byte(ref self: Memory, value: u8, offset: usize); fn store_n(ref self: Memory, elements: Span, offset: usize); @@ -34,34 +31,18 @@ trait MemoryTrait { fn ensure_length(ref self: Memory, length: usize); fn load(ref self: Memory, offset: usize) -> u256; fn load_n(ref self: Memory, elements_len: usize, ref elements: Array, offset: usize); - fn compute_active_segment_offset(ref self: Memory, offset: usize) -> usize; } impl MemoryImpl of MemoryTrait { /// Initializes a new `Memory` instance. #[inline(always)] fn new() -> Memory { - Memory { active_segment: 0, items: Default::default(), bytes_len: Default::default() } + Memory { items: Default::default(), bytes_len: Default::default() } } - - /// Sets the current active segment for the `Memory` instance. - /// Active segment are implementation-specific concepts that reflect - /// the execution context being currently executed. - #[inline(always)] - fn set_active_segment(ref self: Memory, active_segment: usize) { - self.active_segment = active_segment; - } - /// Returns the size of the memory. #[inline(always)] - fn size(ref self: Memory) -> usize { - self.bytes_len.get(self.active_segment.into()) - } - - /// Returns the Memory's active segment - #[inline(always)] - fn active_segment(ref self: Memory) -> felt252 { - self.active_segment.into() + fn size(self: @Memory) -> usize { + *self.bytes_len } /// Stores a 32-bytes element into the memory. @@ -76,14 +57,10 @@ impl MemoryImpl of MemoryTrait { fn store(ref self: Memory, element: u256, offset: usize) { let new_min_bytes_len = helpers::ceil_bytes_len_to_next_32_bytes_word(offset + 32); - self.bytes_len.insert(self.active_segment(), cmp::max(new_min_bytes_len, self.size())); - - // Compute actual offset in the dict, given active_segment of Memory (current Execution Context id) - // And Memory Segment Size - let internal_offset = self.compute_active_segment_offset(offset); + self.bytes_len = cmp::max(new_min_bytes_len, self.size()); // Check alignment of offset to bytes16 chunks - let (chunk_index, offset_in_chunk) = u32_safe_divmod(internal_offset, u32_as_non_zero(16)); + let (chunk_index, offset_in_chunk) = u32_safe_divmod(offset, u32_as_non_zero(16)); if offset_in_chunk == 0 { // Offset is aligned. This is the simplest and most efficient case, @@ -115,14 +92,13 @@ impl MemoryImpl of MemoryTrait { #[inline(always)] fn store_byte(ref self: Memory, value: u8, offset: usize) { let new_min_bytes_len = helpers::ceil_bytes_len_to_next_32_bytes_word(offset + 1); - self.bytes_len.insert(self.active_segment(), cmp::max(new_min_bytes_len, self.size())); + self.bytes_len = cmp::max(new_min_bytes_len, self.size()); // Compute actual offset in Memory, given active_segment of Memory (current Execution Context id) // And Memory Segment Size - let internal_offset = self.compute_active_segment_offset(offset); // Get offset's memory word index and left-based offset of byte in word. - let (chunk_index, left_offset) = u32_safe_divmod(internal_offset, u32_as_non_zero(16)); + let (chunk_index, left_offset) = u32_safe_divmod(offset, u32_as_non_zero(16)); // As the memory words are in big-endian order, we need to convert our left-based offset // to a right-based one.a @@ -162,18 +138,15 @@ impl MemoryImpl of MemoryTrait { let new_min_bytes_len = helpers::ceil_bytes_len_to_next_32_bytes_word( offset + elements.len() ); - self.bytes_len.insert(self.active_segment(), cmp::max(new_min_bytes_len, self.size())); + self.bytes_len = cmp::max(new_min_bytes_len, self.size()); // Compute the offset inside the Memory, given its active segment, following the formula: // index = offset + self.active_segment * 125000 - let internal_offset = self.compute_active_segment_offset(offset); // Check alignment of offset to bytes16 chunks. - let (initial_chunk, offset_in_chunk_i) = u32_safe_divmod( - internal_offset, u32_as_non_zero(16) - ); + let (initial_chunk, offset_in_chunk_i) = u32_safe_divmod(offset, u32_as_non_zero(16)); let (final_chunk, mut offset_in_chunk_f) = u32_safe_divmod( - internal_offset + elements.len() - 1, u32_as_non_zero(16) + offset + elements.len() - 1, u32_as_non_zero(16) ); offset_in_chunk_f += 1; let mask_i: u256 = helpers::pow256_rev(offset_in_chunk_i); @@ -260,12 +233,6 @@ impl MemoryImpl of MemoryTrait { self.load_n_internal(elements_len, ref elements, offset); } - - /// Computes the offset in dict to write data given the active segment (active ExecutionContext) and offset - #[inline(always)] - fn compute_active_segment_offset(ref self: Memory, offset: usize) -> usize { - offset + self.active_segment * MEMORY_SEGMENT_SIZE - } } #[generate_trait] @@ -426,9 +393,8 @@ impl InternalMemoryMethods of InternalMemoryTrait { fn load_internal(ref self: Memory, offset: usize) -> u256 { // Compute the offset inside the dict, given its active segment, following the formula: // index = offset + self.active_segment * 125000 - let internal_offset = self.compute_active_segment_offset(offset); - let (chunk_index, offset_in_chunk) = u32_safe_divmod(internal_offset, u32_as_non_zero(16)); + let (chunk_index, offset_in_chunk) = u32_safe_divmod(offset, u32_as_non_zero(16)); if offset_in_chunk == 0 { // Offset is aligned. This is the simplest and most efficient case, @@ -484,14 +450,11 @@ impl InternalMemoryMethods of InternalMemoryTrait { // Compute the offset inside the Memory, given its active segment, following the formula: // index = offset + self.active_segment * 125000 - let internal_offset = self.compute_active_segment_offset(offset); // Check alignment of offset to bytes16 chunks. - let (initial_chunk, offset_in_chunk_i) = u32_safe_divmod( - internal_offset, u32_as_non_zero(16) - ); + let (initial_chunk, offset_in_chunk_i) = u32_safe_divmod(offset, u32_as_non_zero(16)); let (final_chunk, mut offset_in_chunk_f) = u32_safe_divmod( - internal_offset + elements_len - 1, u32_as_non_zero(16) + offset + elements_len - 1, u32_as_non_zero(16) ); offset_in_chunk_f += 1; let mask_i: u256 = helpers::pow256_rev(offset_in_chunk_i); @@ -542,7 +505,7 @@ impl InternalMemoryMethods of InternalMemoryTrait { let new_bytes_len = self.size() + adjusted_length; // Update memory size. - self.bytes_len.insert(self.active_segment(), new_bytes_len); + self.bytes_len = new_bytes_len; } diff --git a/crates/evm/src/model.cairo b/crates/evm/src/model.cairo index 127ac9271..813a98913 100644 --- a/crates/evm/src/model.cairo +++ b/crates/evm/src/model.cairo @@ -1,10 +1,10 @@ mod account; mod contract_account; mod eoa; +mod vm; use contracts::kakarot_core::{KakarotCore, IKakarotCore}; use evm::errors::{EVMError, CONTRACT_SYSCALL_FAILED}; -use evm::execution::Status; use evm::model::account::{Account, AccountTrait}; use evm::model::contract_account::{ContractAccountTrait}; use evm::model::eoa::EOATrait; @@ -12,7 +12,47 @@ use evm::state::State; use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; use starknet::{EthAddress, get_contract_address, ContractAddress}; use utils::helpers::{ResultExTrait}; -use utils::traits::{EthAddressDefault, ContractAddressDefault}; +use utils::traits::{EthAddressDefault, ContractAddressDefault, SpanDefault}; + +#[derive(Destruct, Default)] +struct Environment { + origin: EthAddress, + gas_price: u128, + chain_id: u128, + prevrandao: u256, + block_number: u64, + block_gas_limit: u128, + block_timestamp: u64, + coinbase: EthAddress, + state: State +} +#[derive(Copy, Drop, Default, PartialEq)] +struct Message { + caller: Address, + target: Address, + gas_limit: u128, + data: Span, + code: Span, + value: u256, + should_transfer_value: bool, + depth: usize, + read_only: bool, +} + +#[derive(Drop)] +struct ExecutionResult { + success: bool, + return_data: Span, + gas_used: u128, +} + +#[derive(Destruct)] +struct ExecutionSummary { + state: State, + return_data: Span, + address: EthAddress, + success: bool +} /// The struct representing an EVM event. #[derive(Drop, Clone, Default, PartialEq)] @@ -29,9 +69,9 @@ struct Address { #[generate_trait] impl AddressImpl of AddressTrait { - fn is_deployed(self: EthAddress) -> bool { + fn is_deployed(self: @EthAddress) -> bool { let mut kakarot_state = KakarotCore::unsafe_new_contract_state(); - let maybe_account = kakarot_state.address_registry(self); + let maybe_account = kakarot_state.address_registry(*self); match maybe_account { Option::Some(_) => true, Option::None => false @@ -55,14 +95,6 @@ struct Transfer { amount: u256 } -#[derive(Destruct)] -struct ExecutionResult { - address: Address, - status: Status, - return_data: Span, - state: State, -} - /// An EVM Account is either an EOA or a Contract Account. In both cases, the /// account is identified by an Ethereum address. It has a corresponding /// Starknet Address - The corresponding Starknet Contract for EOAs, and the diff --git a/crates/evm/src/model/account.cairo b/crates/evm/src/model/account.cairo index c05d08b7a..8a965c914 100644 --- a/crates/evm/src/model/account.cairo +++ b/crates/evm/src/model/account.cairo @@ -197,7 +197,7 @@ impl AccountImpl of AccountTrait { /// /// `Ok(())` if the commit was successful, otherwise an `EVMError`. fn commit(self: @Account) -> Result<(), EVMError> { - let is_deployed = self.address().evm.is_deployed(); + let is_deployed = self.evm_address().is_deployed(); let is_ca = self.is_ca(); // If a Starknet account is already deployed for this evm address, we @@ -224,7 +224,7 @@ impl AccountImpl of AccountTrait { (*self.nonce, *self.code) }; ContractAccountTrait::deploy( - self.address().evm, + self.evm_address(), initial_nonce, initial_code, deploy_starknet_contract: !is_deployed @@ -277,7 +277,7 @@ impl AccountImpl of AccountTrait { #[inline(always)] fn is_precompile(self: @Account) -> bool { - let evm_address: felt252 = self.address().evm.into(); + let evm_address: felt252 = self.evm_address().into(); if evm_address.into() < 0x10_u256 { return true; } @@ -297,7 +297,12 @@ impl AccountImpl of AccountTrait { #[inline(always)] fn evm_address(self: @Account) -> EthAddress { - self.address().evm + *self.address.evm + } + + #[inline(always)] + fn starknet_address(self: @Account) -> ContractAddress { + *self.address.starknet } /// Returns the bytecode of the EVM account (EOA or CA) diff --git a/crates/evm/src/model/contract_account.cairo b/crates/evm/src/model/contract_account.cairo index 3dab4b019..0efbbd169 100644 --- a/crates/evm/src/model/contract_account.cairo +++ b/crates/evm/src/model/contract_account.cairo @@ -15,12 +15,10 @@ use contracts::kakarot_core::{ use contracts::uninitialized_account::{ IUninitializedAccountDispatcher, IUninitializedAccountDispatcherTrait }; -use evm::context::Status; use evm::errors::{ EVMError, READ_SYSCALL_FAILED, WRITE_SYSCALL_FAILED, ACCOUNT_EXISTS, DEPLOYMENT_FAILED, CONTRACT_ACCOUNT_EXISTS, CONTRACT_SYSCALL_FAILED }; -use evm::execution::execute; use evm::model::{Address, Account, AccountType, AccountTrait}; use hash::{HashStateTrait, HashStateExTrait}; use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; @@ -97,7 +95,7 @@ impl ContractAccountImpl of ContractAccountTrait { #[inline(always)] fn selfdestruct(self: @Account) -> Result<(), EVMError> { let contract_account = IContractAccountSafeDispatcher { - contract_address: self.address().starknet + contract_address: self.starknet_address() }; contract_account.selfdestruct().map_err(EVMError::SyscallFailed(CONTRACT_SYSCALL_FAILED)) } @@ -126,7 +124,7 @@ impl ContractAccountImpl of ContractAccountTrait { /// Fetches the nonce of a contract account. fn fetch_nonce(self: @Account) -> Result { let contract_account = IContractAccountDispatcher { - contract_address: self.address().starknet + contract_address: self.starknet_address() }; Result::Ok(contract_account.nonce()) } @@ -140,7 +138,7 @@ impl ContractAccountImpl of ContractAccountTrait { #[inline(always)] fn store_nonce(self: @Account, nonce: u64) -> Result<(), EVMError> { let mut contract_account = IContractAccountDispatcher { - contract_address: self.address().starknet + contract_address: self.starknet_address() }; contract_account.set_nonce(nonce); Result::Ok(()) @@ -152,7 +150,7 @@ impl ContractAccountImpl of ContractAccountTrait { #[inline(always)] fn fetch_storage(self: @Account, key: u256) -> Result { let contract_account = IContractAccountDispatcher { - contract_address: self.address().starknet + contract_address: self.starknet_address() }; Result::Ok(contract_account.storage_at(key)) } @@ -167,7 +165,7 @@ impl ContractAccountImpl of ContractAccountTrait { #[inline(always)] fn store_storage(self: @Account, key: u256, value: u256) -> Result<(), EVMError> { let mut contract_account = IContractAccountDispatcher { - contract_address: self.address().starknet + contract_address: self.starknet_address() }; contract_account.set_storage_at(key, value); Result::Ok(()) @@ -180,7 +178,7 @@ impl ContractAccountImpl of ContractAccountTrait { /// * `bytecode` - The bytecode to store fn store_bytecode(self: @Account, bytecode: Span) -> Result<(), EVMError> { let mut contract_account = IContractAccountDispatcher { - contract_address: self.address().starknet + contract_address: self.starknet_address() }; contract_account.set_bytecode(bytecode); Result::Ok(()) @@ -197,7 +195,7 @@ impl ContractAccountImpl of ContractAccountTrait { #[inline(always)] fn is_false_positive_jumpdest(self: @Account, offset: usize) -> Result { let contract_account = IContractAccountDispatcher { - contract_address: self.address().starknet + contract_address: self.starknet_address() }; let is_false_positive_jumpdest = contract_account.is_false_positive_jumpdest(offset); Result::Ok(is_false_positive_jumpdest) @@ -211,7 +209,7 @@ impl ContractAccountImpl of ContractAccountTrait { #[inline(always)] fn set_false_positive_jumpdest(self: @Account, offset: usize) -> Result<(), EVMError> { let mut contract_account = IContractAccountDispatcher { - contract_address: self.address().starknet + contract_address: self.starknet_address() }; contract_account.set_false_positive_jumpdest(offset); Result::Ok(()) diff --git a/crates/evm/src/model/vm.cairo b/crates/evm/src/model/vm.cairo new file mode 100644 index 000000000..83f49d325 --- /dev/null +++ b/crates/evm/src/model/vm.cairo @@ -0,0 +1,114 @@ +use evm::errors::EVMError; +use evm::memory::{Memory, MemoryTrait}; +use evm::model::{Message, Environment}; +use evm::stack::{Stack, StackTrait}; +use utils::traits::{SpanDefault}; + +#[derive(Default, Destruct)] +struct VM { + stack: Stack, + memory: Memory, + pc: usize, + valid_jumpdests: Span, + return_data: Span, + env: Environment, + message: Message, + gas_used: u128, + running: bool, + error: bool +} + + +#[generate_trait] +impl VMImpl of VMTrait { + fn new(message: Message, env: Environment) -> VM { + VM { + stack: Default::default(), + memory: Default::default(), + pc: 0, + valid_jumpdests: Default::default().span(), + return_data: Default::default().span(), + env, + message, + gas_used: 0, + running: true, + error: false + } + } + + /// Increments the gas_used field of the current execution context by the value amount. + /// # Error : returns `EVMError::OutOfGas` if gas_used + new_gas >= limit + #[inline(always)] + fn charge_gas(ref self: VM, value: u128) -> Result<(), EVMError> { + let new_gas_used = self.gas_used + value; + if (new_gas_used >= self.message().gas_limit) { + return Result::Err(EVMError::OutOfGas); + } + self.gas_used = new_gas_used; + Result::Ok(()) + } + + + fn pc(self: @VM) -> usize { + *self.pc + } + + fn set_pc(ref self: VM, pc: usize) { + self.pc = pc; + } + + fn valid_jumpdests(self: @VM) -> Span { + *self.valid_jumpdests + } + + fn set_valid_jumpdests(ref self: VM, valid_jumpdests: Span) { + self.valid_jumpdests = valid_jumpdests; + } + + fn return_data(self: @VM) -> Span { + *self.return_data + } + + fn set_return_data(ref self: VM, return_data: Span) { + self.return_data = return_data; + } + + fn is_running(self: @VM) -> bool { + *self.running + } + + fn stop(ref self: VM) { + self.running = false; + } + + fn set_error(ref self: VM) { + self.error = true; + } + + fn message(self: @VM) -> Message { + *self.message + } + + fn gas_used(self: @VM) -> u128 { + *self.gas_used + } + + /// Reads and return data from bytecode. + /// The program counter is incremented accordingly. + /// + /// # Arguments + /// + /// * `self` - The `ExecutionContext` instance to read the data from. + /// * `len` - The length of the data to read from the bytecode. + #[inline(always)] + fn read_code(self: @VM, len: usize) -> Span { + // Copy code slice from [pc, pc+len] + let code = self.message().code.slice(self.pc(), len); + code + } + + #[inline(always)] + fn increment_gas_used_unchecked(ref self: VM, value: u128) { + self.gas_used += value; + } +} diff --git a/crates/evm/src/stack.cairo b/crates/evm/src/stack.cairo index 5af0a0b9c..da747a211 100644 --- a/crates/evm/src/stack.cairo +++ b/crates/evm/src/stack.cairo @@ -1,3 +1,4 @@ +use core::fmt::{Debug, Formatter, Error, Display}; //! Stack implementation. //! # Example //! ``` @@ -22,16 +23,15 @@ use utils::i256::i256; use utils::traits::{TryIntoResult}; +//TODO(optimization): make len `felt252` based to avoid un-necessary checks #[derive(Destruct, Default)] struct Stack { - active_segment: usize, items: Felt252Dict>, - len: Felt252Dict, + len: usize, } trait StackTrait { fn new() -> Stack; - fn set_active_segment(ref self: Stack, active_segment: usize); fn push(ref self: Stack, item: u256) -> Result<(), EVMError>; fn pop(ref self: Stack) -> Result; fn pop_usize(ref self: Stack) -> Result; @@ -43,10 +43,8 @@ trait StackTrait { fn peek(ref self: Stack) -> Option; fn peek_at(ref self: Stack, index: usize) -> Result; fn swap_i(ref self: Stack, index: usize) -> Result<(), EVMError>; - fn len(ref self: Stack) -> usize; - fn is_empty(ref self: Stack) -> bool; - fn active_segment(self: @Stack) -> usize; - fn compute_active_segment_index(self: @Stack, index: usize) -> felt252; + fn len(self: @Stack) -> usize; + fn is_empty(self: @Stack) -> bool; } impl StackImpl of StackTrait { @@ -55,14 +53,6 @@ impl StackImpl of StackTrait { Default::default() } - /// Sets the current active segment for the `Stack` instance. - /// Active segment are implementation-specific concepts that reflect - /// the execution context being currently executed. - #[inline(always)] - fn set_active_segment(ref self: Stack, active_segment: usize) { - self.active_segment = active_segment; - } - /// Pushes a new bytes32 word onto the stack. /// /// When pushing an item to the stack, we will compute @@ -81,9 +71,9 @@ impl StackImpl of StackTrait { if length == constants::STACK_MAX_DEPTH { return Result::Err(EVMError::StackError(STACK_OVERFLOW)); } - let index = self.compute_active_segment_index(length); + let index = length.into(); self.items.insert(index, NullableTrait::new(item)); - self.len.insert(self.active_segment().into(), length + 1); + self.len += 1; Result::Ok(()) } @@ -98,9 +88,8 @@ impl StackImpl of StackTrait { if length == 0 { return Result::Err(EVMError::StackError(STACK_UNDERFLOW)); } - self.len.insert(self.active_segment().into(), length - 1); - let internal_index = self.compute_active_segment_index(self.len()); - let item = self.items.get(internal_index); + self.len -= 1; + let item = self.items.get(self.len().into()); Result::Ok(item.deref()) } @@ -208,7 +197,7 @@ impl StackImpl of StackTrait { if self.len() == 0 { Option::None(()) } else { - let last_index = self.compute_active_segment_index(self.len() - 1); + let last_index = self.len() - 1; let item = self.items.get(last_index.into()); Option::Some(item.deref()) } @@ -226,7 +215,7 @@ impl StackImpl of StackTrait { return Result::Err(EVMError::StackError(STACK_UNDERFLOW)); } - let position = self.compute_active_segment_index(self.len() - 1 - index); + let position = self.len() - 1 - index; let item = self.items.get(position.into()); Result::Ok(item.deref()) @@ -239,7 +228,7 @@ impl StackImpl of StackTrait { if index >= self.len() { return Result::Err(EVMError::StackError(STACK_UNDERFLOW)); } - let position_0: felt252 = self.compute_active_segment_index(self.len() - 1); + let position_0: felt252 = self.len().into() - 1; let position_item: felt252 = position_0 - index.into(); let top_item = self.items.get(position_0); let swapped_item = self.items.get(position_item); @@ -250,26 +239,13 @@ impl StackImpl of StackTrait { /// Returns the length of the stack. #[inline(always)] - fn len(ref self: Stack) -> usize { - self.len.get(self.active_segment.into()) + fn len(self: @Stack) -> usize { + *self.len } /// Returns true if the stack is empty. #[inline(always)] - fn is_empty(ref self: Stack) -> bool { + fn is_empty(self: @Stack) -> bool { self.len() == 0 } - - /// Returns the current active segment, i.e. the current active execution context's id - #[inline(always)] - fn active_segment(self: @Stack) -> usize { - *self.active_segment - } - - /// Computes the internal index to access the Stack of the current execution context - #[inline(always)] - fn compute_active_segment_index(self: @Stack, index: usize) -> felt252 { - let internal_index = index + self.active_segment() * constants::STACK_MAX_DEPTH; - internal_index.into() - } } diff --git a/crates/evm/src/state.cairo b/crates/evm/src/state.cairo index fcbad7092..8f7fea29c 100644 --- a/crates/evm/src/state.cairo +++ b/crates/evm/src/state.cairo @@ -28,33 +28,22 @@ use utils::traits::{StorageBaseAddressPartialEq, StorageBaseAddressIntoFelt252}; /// /// # Fields /// -/// * `contextual_changes` - A `Felt252Dict` of contextual changes. Tracks the changes applied inside a single execution context. -/// * `contextual_keyset` - An `Array` of contextual keys. -/// * `transactional_changes` - A `Felt252Dict` of transactional changes. Tracks -/// the changes applied in the entire transaction. -/// * `transactional_keyset` - An `Array` of transactional keys. +/// * `changes` - A `Felt252Dict` of contextual changes. Tracks the changes applied inside a single execution context. +/// * `keyset` - An `Array` of contextual keys. struct StateChangeLog { - contextual_changes: Felt252Dict>, - contextual_keyset: Array, - transactional_changes: Felt252Dict>, - transactional_keyset: Array + changes: Felt252Dict>, + keyset: Array, } impl StateChangeLogDestruct> of Destruct> { fn destruct(self: StateChangeLog) nopanic { - self.contextual_changes.squash(); - self.transactional_changes.squash(); + self.changes.squash(); } } impl StateChangeLogDefault> of Default> { fn default() -> StateChangeLog { - StateChangeLog { - contextual_changes: Default::default(), - contextual_keyset: Default::default(), - transactional_changes: Default::default(), - transactional_keyset: Default::default() - } + StateChangeLog { changes: Default::default(), keyset: Default::default(), } } } @@ -74,13 +63,8 @@ impl StateChangeLogImpl, +Copy> of StateChangeLogTrait { /// An `Option` containing the value if it exists, or `None` if it does not. #[inline(always)] fn read(ref self: StateChangeLog, key: felt252) -> Option { - match match_nullable(self.contextual_changes.get(key)) { - FromNullableResult::Null => { - match match_nullable(self.transactional_changes.get(key)) { - FromNullableResult::Null => { Option::None }, - FromNullableResult::NotNull(value) => { Option::Some(value.unbox()) } - } - }, + match match_nullable(self.changes.get(key)) { + FromNullableResult::Null => { Option::None }, FromNullableResult::NotNull(value) => Option::Some(value.unbox()), } } @@ -95,97 +79,24 @@ impl StateChangeLogImpl, +Copy> of StateChangeLogTrait { /// * `value` - The value to write. #[inline(always)] fn write(ref self: StateChangeLog, key: felt252, value: T) { - self.contextual_changes.insert(key, NullableTrait::new(value)); - self.contextual_keyset.append_unique(key); - } - - #[inline(always)] - fn transactional_keyset(self: @StateChangeLog) -> Span { - self.transactional_keyset.span() + self.changes.insert(key, NullableTrait::new(value)); + self.keyset.append_unique(key); } - /// Commits the contextual changes of a `StateChangeLog` to the - /// transactional changes. - /// - /// # Arguments - /// - /// * `self` - A reference to a `StateChangeLog` instance. - fn commit_context(ref self: StateChangeLog) { + fn clone(ref self: StateChangeLog) -> StateChangeLog { + let mut cloned_changes = Default::default(); + let mut keyset_span = self.keyset.span(); loop { - match self.contextual_keyset.pop_front() { + match keyset_span.pop_front() { Option::Some(key) => { - let value = self.contextual_changes.get(key); - self.transactional_changes.insert(key, value); - self.transactional_keyset.append_unique(key); + let value = self.changes.get(*key).deref(); + cloned_changes.insert(*key, NullableTrait::new(value)); }, Option::None => { break; } } }; - self.clear_context(); - } - #[inline(always)] - fn clear_context(ref self: StateChangeLog) { - self.contextual_changes = Default::default(); - self.contextual_keyset = Default::default(); - } -} - - -/// `SimpleLog` is a straightforward logging mechanism. -/// -/// This structure is designed to manage both contextual and transactional logs of a generic type `T`. -/// -/// # Fields -/// -/// - `contextual_logs`: Contains logs that are context-specific. -/// - `transactional_logs`: Contains logs that are transaction-wide. -#[derive(Drop)] -struct SimpleLog { - contextual_logs: Array, - transactional_logs: Array, -} - -/// `SimpleLogTrait` provides a set of methods for managing logs in `SimpleLog`. -/// -/// The trait is generic over type `T` which represents the type of logs stored. -trait SimpleLogTrait { - /// Appends a value to the list of contextual logs. - /// - /// # Arguments - /// - /// - `value`: The value that needs to be logged contextually. - fn append(ref self: SimpleLog, value: T); - - /// Transfers logs from contextual storage to transactional storage. - /// - /// This is essentially 'finalizing' the contextual logs into the transaction state. - fn commit_context(ref self: SimpleLog); - - /// Clears out all contextual logs. - /// - /// Useful when the context has ended and the logs are no longer required. - fn clear_context(ref self: SimpleLog); -} - -impl SimpleLogDefault> of Default> { - fn default() -> SimpleLog { - SimpleLog { contextual_logs: Default::default(), transactional_logs: Default::default() } - } -} - -impl TSimpleLogImpl, +Clone> of SimpleLogTrait { - fn append(ref self: SimpleLog, value: T) { - self.contextual_logs.append(value) - } - - fn commit_context(ref self: SimpleLog) { - self.transactional_logs.append_span(self.contextual_logs.span()); - self.contextual_logs = Default::default(); - } - - fn clear_context(ref self: SimpleLog) { - self.contextual_logs = Default::default(); + StateChangeLog { changes: cloned_changes, keyset: self.keyset.clone(), } } } @@ -201,9 +112,9 @@ struct State { accounts_storage: StateChangeLog<(EthAddress, u256, u256)>, /// Account states /// Pending emitted events - events: SimpleLog, + events: Array, /// Pending transfers - transfers: SimpleLog, + transfers: Array, } #[generate_trait] @@ -280,22 +191,6 @@ impl StateImpl of StateTrait { Result::Ok(()) } - #[inline(always)] - fn commit_context(ref self: State) { - self.accounts.commit_context(); - self.accounts_storage.commit_context(); - self.events.commit_context(); - self.transfers.commit_context(); - } - - #[inline(always)] - fn clear_context(ref self: State) { - self.accounts.clear_context(); - self.accounts_storage.clear_context(); - self.events.clear_context(); - self.transfers.clear_context(); - } - #[inline(always)] fn commit_state(ref self: State) -> Result<(), EVMError> { self.commit_accounts()?; @@ -303,6 +198,15 @@ impl StateImpl of StateTrait { self.commit_storage()?; self.emit_events() } + + fn clone(ref self: State) -> State { + State { + accounts: self.accounts.clone(), + accounts_storage: self.accounts_storage.clone(), + events: self.events.clone(), + transfers: self.transfers.clone(), + } + } } #[generate_trait] impl StateInternalImpl of StateInternalTrait { @@ -311,16 +215,16 @@ impl StateInternalImpl of StateInternalTrait { /// commit_storage MUST be called after commit_accounts. fn commit_storage(ref self: State) -> Result<(), EVMError> { let result = loop { - match self.accounts_storage.transactional_keyset.pop_front() { + match self.accounts_storage.keyset.pop_front() { Option::Some(state_key) => { let (evm_address, key, value) = self .accounts_storage - .transactional_changes + .changes .get(state_key) .deref(); let mut account = self.get_account(evm_address); match account.commit_storage(key, value) { - Result::Ok(()) => {}, + Result::Ok(_) => {}, Result::Err(_) => { //TODO handle error gracefully // break Result::Err(EVMError::SyscallFailed(WRITE_SYSCALL_FAILED)); } @@ -336,7 +240,7 @@ impl StateInternalImpl of StateInternalTrait { /// Iterates through the list of events and emits them. fn emit_events(ref self: State) -> Result<(), EVMError> { loop { - match self.events.transactional_logs.pop_front() { + match self.events.pop_front() { Option::Some(event) => { let mut keys = Default::default(); let mut data = Default::default(); @@ -358,7 +262,7 @@ impl StateInternalImpl of StateInternalTrait { let kakarot_state = KakarotCore::unsafe_new_contract_state(); let native_token = kakarot_state.native_token(); loop { - match self.transfers.transactional_logs.pop_front() { + match self.transfers.pop_front() { Option::Some(transfer) => { IERC20CamelDispatcher { contract_address: native_token } .transferFrom( @@ -373,11 +277,11 @@ impl StateInternalImpl of StateInternalTrait { fn commit_accounts(ref self: State) -> Result<(), EVMError> { loop { - match self.accounts.transactional_keyset.pop_front() { + match self.accounts.keyset.pop_front() { Option::Some(evm_address) => { - let account = self.accounts.transactional_changes.get(evm_address).deref(); + let account = self.accounts.changes.get(evm_address).deref(); match account.commit() { - Result::Ok(()) => {}, + Result::Ok(_) => {}, Result::Err(_) => { //TODO handle error gracefully // break Result::Err(EVMError::SyscallFailed(WRITE_SYSCALL_FAILED)); } diff --git a/crates/evm/src/tests.cairo b/crates/evm/src/tests.cairo index 7c172ce3f..ee21d609b 100644 --- a/crates/evm/src/tests.cairo +++ b/crates/evm/src/tests.cairo @@ -1,9 +1,6 @@ mod test_call_helpers; -mod test_create_helpers; - -mod test_execution; -mod test_execution_context; +mod test_create_helpers; mod test_instructions; diff --git a/crates/evm/src/tests/test_call_helpers.cairo b/crates/evm/src/tests/test_call_helpers.cairo index deaf466a1..32eabaf0e 100644 --- a/crates/evm/src/tests/test_call_helpers.cairo +++ b/crates/evm/src/tests/test_call_helpers.cairo @@ -9,14 +9,12 @@ use core::result::ResultTrait; use core::traits::Destruct; use core::traits::TryInto; - -use evm::call_helpers::{MachineCallHelpers, CallType, CallArgs}; -use evm::machine::Machine; -use evm::machine::MachineTrait; +use evm::call_helpers::{CallHelpers, CallType, CallArgs}; +use evm::model::vm::{VM, VMTrait}; use evm::model::{Address, account::{AccountBuilderTrait}, eoa::EOATrait}; use evm::stack::StackTrait; use evm::state::StateTrait; -use evm::tests::test_utils::{MachineBuilderTestTrait, test_address, other_evm_address}; +use evm::tests::test_utils::{VMBuilderTrait, test_address, other_evm_address, caller}; use starknet::testing::set_contract_address; use starknet::{contract_address_const, EthAddress, ContractAddress}; @@ -33,16 +31,14 @@ struct TestSetupValues { fn prep_machine_prepare_call_test( call_type: CallType, kakarot_core_address: ContractAddress -) -> (Machine, TestSetupValues) { +) -> (VM, TestSetupValues) { let kakarot_core = IExtendedKakarotCoreDispatcher { contract_address: kakarot_core_address }; let caller_address = EthAddress { address: 0xabde2 }; let caller_address = Address { evm: caller_address, starknet: kakarot_core.compute_starknet_address(caller_address) }; - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_caller(caller_address) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_caller(caller_address).build(); let gas: u128 = 1000; let address = other_evm_address(); @@ -51,31 +47,31 @@ fn prep_machine_prepare_call_test( let ret_offset: usize = 15; let ret_size: usize = 20; - machine.stack.push(ret_size.into()).unwrap(); - machine.stack.push(ret_offset.into()).unwrap(); - machine.stack.push(args_size).unwrap(); - machine.stack.push(args_offset).unwrap(); + vm.stack.push(ret_size.into()).unwrap(); + vm.stack.push(ret_offset.into()).unwrap(); + vm.stack.push(args_size).unwrap(); + vm.stack.push(args_offset).unwrap(); let value = match call_type { CallType::Call => { let value = 100; - machine.stack.push(value).unwrap(); + vm.stack.push(value).unwrap(); Option::Some(value) }, CallType::DelegateCall => { Option::None }, CallType::CallCode => { let value = 100; - machine.stack.push(value).unwrap(); + vm.stack.push(value).unwrap(); Option::Some(value) }, CallType::StaticCall => { Option::None }, }; - machine.stack.push(address.address.into()).unwrap(); - machine.stack.push(gas.into()).unwrap(); + vm.stack.push(address.address.into()).unwrap(); + vm.stack.push(gas.into()).unwrap(); ( - machine, + vm, TestSetupValues { gas, address, value, args_offset, args_size, ret_offset, ret_size, caller_address } @@ -87,7 +83,7 @@ fn test_prepare_call_type_call() { let (_, kakarot_core) = setup_contracts_for_testing(); let ( - mut machine, + mut vm, TestSetupValues{gas, address, value, @@ -112,10 +108,11 @@ fn test_prepare_call_type_call() { calldata: array![0x0].span(), ret_offset, ret_size, - should_transfer: true + should_transfer: true, + read_only: false }; - let call_args = machine.prepare_call(@CallType::Call).unwrap(); + let call_args = vm.prepare_call(@CallType::Call).unwrap(); assert!(call_args == expected_call_args, "wrong calls_args prepared"); } @@ -125,7 +122,7 @@ fn test_prepare_call_type_delegate_call() { let (_, kakarot_core) = setup_contracts_for_testing(); let ( - mut machine, + mut vm, TestSetupValues{gas, address, value: _, @@ -149,14 +146,15 @@ fn test_prepare_call_type_delegate_call() { starknet: kakarot_core.compute_starknet_address(test_address().evm) }, gas, - value: machine.call_ctx().value, + value: vm.message().value, calldata: array![0x0].span(), ret_offset, ret_size, - should_transfer: false + should_transfer: false, + read_only: false }; - let call_args = machine.prepare_call(@CallType::DelegateCall).unwrap(); + let call_args = vm.prepare_call(@CallType::DelegateCall).unwrap(); assert!(call_args == expected_call_args, "wrong calls_args prepared"); } @@ -166,7 +164,7 @@ fn test_prepare_call_type_call_code() { let (_, kakarot_core) = setup_contracts_for_testing(); let ( - mut machine, + mut vm, TestSetupValues{gas, address, value, @@ -194,10 +192,11 @@ fn test_prepare_call_type_call_code() { calldata: array![0x0].span(), ret_offset, ret_size, - should_transfer: false + should_transfer: false, + read_only: false }; - let call_args = machine.prepare_call(@CallType::CallCode).unwrap(); + let call_args = vm.prepare_call(@CallType::CallCode).unwrap(); assert!(call_args == expected_call_args, "wrong calls_args prepared"); } @@ -207,7 +206,7 @@ fn test_prepare_call_type_static_call() { let (_, kakarot_core) = setup_contracts_for_testing(); let ( - mut machine, + mut vm, TestSetupValues{gas, address, value: _, @@ -235,75 +234,68 @@ fn test_prepare_call_type_static_call() { calldata: array![0x0].span(), ret_offset, ret_size, - should_transfer: false + should_transfer: false, + read_only: true }; - let call_args = machine.prepare_call(@CallType::StaticCall).unwrap(); + let call_args = vm.prepare_call(@CallType::StaticCall).unwrap(); assert!(call_args == expected_call_args, "wrong calls_args prepared"); } - - #[test] -fn test_init_call_sub_ctx() { +#[ignore] +fn test_generic_call() { let (native_token, kakarot_core) = setup_contracts_for_testing(); set_contract_address(kakarot_core.contract_address); - let caller_address = EthAddress { address: 0xabde2 }; + let caller_address = caller(); let caller_address = Address { evm: caller_address, starknet: kakarot_core.compute_starknet_address(caller_address) }; - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_caller(caller_address) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_caller(caller_address).build(); let gas: u128 = 1000; - let address = other_evm_address(); + let target_address = other_evm_address(); let value = 100; let ret_offset: usize = 15; let ret_size: usize = 20; + let target = Address { + evm: target_address, starknet: kakarot_core.compute_starknet_address(target_address) + }; let call_args = CallArgs { - caller: test_address(), - code_address: Address { - evm: address, starknet: kakarot_core.compute_starknet_address(address) - }, - to: Address { evm: address, starknet: kakarot_core.compute_starknet_address(address) }, + caller: caller_address, + code_address: target, + to: target, gas, value, calldata: array![0x0].span(), ret_offset, ret_size, - should_transfer: true + should_transfer: true, + read_only: false }; - let sender_eoa = EOATrait::deploy(machine.address().evm).expect('failed deploying sender'); - fund_account_with_native_token(sender_eoa.starknet, native_token, 0x10000); + let sender_eoa = kakarot_core.deploy_eoa(caller_address.evm); + fund_account_with_native_token(sender_eoa, native_token, 1000); - EOATrait::deploy(address).expect('failed deploying reciever'); + let receiver_eoa = kakarot_core.deploy_eoa(target.evm); - let ctx_count_prev = machine.ctx_count; - let sender_balance_prev = machine.state.get_account(sender_eoa.evm).balance; - let reciver_balance_prev = machine.state.get_account(address).balance; + let sender_balance_prev = vm.env.state.get_account(caller_address.evm).balance; + let receiver_balance_prev = vm.env.state.get_account(target.evm).balance; - machine.init_call_sub_ctx(call_args, machine.call_ctx().read_only).unwrap(); + // machine.init_call_sub_ctx(call_args, machine.call_ctx().read_only).unwrap(); - let ctx_count_after = machine.ctx_count; - let sender_balance_after = machine.state.get_account(sender_eoa.evm).balance; - let reciver_balance_after = machine.state.get_account(address).balance; + let sender_balance_after = vm.env.state.get_account(caller_address.evm).balance; + let receiver_balance_after = vm.env.state.get_account(target.evm).balance; - assert!( - machine - .address() == Address { - evm: address, starknet: kakarot_core.compute_starknet_address(address) - }, - "wrong execution context address" - ); - - assert!(sender_balance_prev - sender_balance_after == 100, "wrong sender balance"); - assert!(reciver_balance_after - reciver_balance_prev == 100, "wrong reciever balance"); + assert_eq!(vm.stack.peek().expect('stack empty'), 1); - assert!(ctx_count_after - ctx_count_prev == 1, "ctx count increased by wrong value"); + // No return data for calls to EOAs - only value transfers + assert_eq!(vm.return_data().len(), 0); + assert_eq!(sender_balance_prev - sender_balance_after, 100); + assert_eq!(receiver_balance_after - receiver_balance_prev, 100); } + diff --git a/crates/evm/src/tests/test_create_helpers.cairo b/crates/evm/src/tests/test_create_helpers.cairo index a8da62254..499c4b747 100644 --- a/crates/evm/src/tests/test_create_helpers.cairo +++ b/crates/evm/src/tests/test_create_helpers.cairo @@ -1,5 +1,8 @@ use contracts::tests::test_data::counter_evm_bytecode; -use evm::create_helpers::MachineCreateHelpers; -use evm::tests::test_utils::{MachineBuilderTestTrait}; +use evm::create_helpers::CreateHelpers; +use evm::tests::test_utils::{VMBuilderTrait}; use starknet::EthAddress; use utils::address::{compute_contract_address, compute_create2_contract_address}; +//TODO: test create helpers + + diff --git a/crates/evm/src/tests/test_execution.cairo b/crates/evm/src/tests/test_execution.cairo deleted file mode 100644 index 6351b3e47..000000000 --- a/crates/evm/src/tests/test_execution.cairo +++ /dev/null @@ -1,130 +0,0 @@ -use contracts::tests::test_utils as contract_utils; -use core::traits::TryInto; -use evm::errors::{EVMError, EVMErrorTrait, STACK_OVERFLOW}; -use evm::execution::execute; -use evm::interpreter::{EVMInterpreter, EVMInterpreterTrait}; -use evm::machine::{MachineTrait}; -use evm::model::eoa::EOATrait; -use evm::stack::StackTrait; -use evm::state::StateTrait; -use evm::tests::test_utils::{evm_address, other_evm_address, MachineBuilderTestTrait}; -use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; -use starknet::testing::set_nonce; -use utils::helpers::U256Trait; -use utils::traits::EthAddressIntoU256; - -#[test] -fn test_execute_value_transfer() { - let (native_token, _) = contract_utils::setup_contracts_for_testing(); - // Transfer native tokens to sender - let sender = EOATrait::deploy(evm_address()).expect('sender deploy failed'); - let recipient = EOATrait::deploy(other_evm_address()).expect('recipient deploy failed'); - // Transfer native tokens to sender - contract_utils::fund_account_with_native_token(sender.starknet, native_token, 10000); - // When - let mut exec_result = execute( - origin: sender, - target: recipient, - calldata: Default::default().span(), - value: 2000, - gas_price: 0, - gas_limit: 0, - read_only: false, - is_deploy_tx: false, - ); - // `commit_state` is applied in `eth_send_tx` only - to test that `execute` worked correctly, we manually apply it here. - exec_result.state.commit_state().expect('commit state failed'); - - let sender_balance = native_token.balanceOf(sender.starknet); - let recipient_balance = native_token.balanceOf(recipient.starknet); - - assert(sender_balance == 8000, 'wrong sender balance'); - assert(recipient_balance == 2000, 'wrong recipient balance'); -} - -#[test] -fn test_run_evm_error_revert() { - contract_utils::setup_contracts_for_testing(); - // PUSH1 0x01 - let mut bytecode = array![0x60, 0x01].span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); - let mut interpreter = EVMInterpreter {}; - // When - stack already full - machine.stack.len.insert(0, 1024); - interpreter.run(ref machine); - - assert_eq!(machine.reverted(), true); - let error = machine.return_data(); - assert( - error == Into::::into(STACK_OVERFLOW).to_bytes(), 'expected stack overflow', - ); -} - -#[test] -fn test_run_evm_error_revert_subcontext() { - let mut interpreter = EVMInterpreter {}; - contract_utils::setup_contracts_for_testing(); - // Set machine bytecode - // (call 0xffffff 0x100 0 0 0 0 1) - let bytecode = array![ - 0x60, - 0x01, - 0x60, - 0x00, - 0x60, - 0x00, - 0x60, - 0x00, - 0x60, - 0x00, - 0x61, - 0x01, - 0x00, - 0x62, - 0xff, - 0xff, - 0xff, - // CALL - 0xf1, - 0x60, // PUSH1 0x69 (value) - 0x01, - 0x60, // PUSH1 0x01 (key) - 0x69, - 0x55, // SSTORE - 0x00 //STOP - ] - .span(); - // we need to deploy this account so that it's usable directly by the machine - let mut _caller_account = contract_utils::deploy_contract_account(evm_address(), bytecode); - let mut _called_account = contract_utils::deploy_contract_account( - other_evm_address(), array![0xFD].span() // REVERT - ); - - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); - - interpreter.run(ref machine); - - machine.state.commit_state().expect('failed to commit state'); - assert_eq!(machine.state.read_state(evm_address(), 0x69).expect('couldnt read state'), 0x01); - let error = machine.return_data(); - assert_eq!(error.len(), 0); -} - -#[test] -fn test_run_evm_opcopde_revert() { - contract_utils::setup_contracts_for_testing(); - let mut interpreter = EVMInterpreter {}; - - // MSTORE 0 1000 - REVERT 0 32 - let mut bytecode = array![0x52, 0xFD].span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); - machine.stack.push(32).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(1000).expect('push failed'); - machine.stack.push(0).expect('push failed'); - interpreter.run(ref machine); - - assert_eq!(machine.reverted(), true); - let error = machine.return_data(); - assert(error == 1000.to_bytes(), 'expected error == 1000',); -} diff --git a/crates/evm/src/tests/test_execution_context.cairo b/crates/evm/src/tests/test_execution_context.cairo deleted file mode 100644 index 1df6f3b4d..000000000 --- a/crates/evm/src/tests/test_execution_context.cairo +++ /dev/null @@ -1,185 +0,0 @@ -use core::box::BoxTrait; -use core::nullable::{NullableTrait, null}; -use evm::context::{ - CallContext, CallContextTrait, ExecutionContext, ExecutionContextType, ExecutionContextTrait, - DefaultOptionSpanU8 -}; -use evm::errors::{EVMError, DebugEVMError}; -use evm::machine::{MachineTrait}; -use evm::memory::{Memory, MemoryTrait}; -use evm::model::{Event, Address}; -use evm::stack::{Stack, StackTrait}; -use evm::tests::test_utils::{MachineBuilderTestTrait, CallContextPartialEq}; -use evm::tests::test_utils; -use starknet::testing::{set_contract_address, set_caller_address}; -use starknet::{EthAddress, ContractAddress}; - - -use test_utils::{callvalue, test_address}; -use traits::PartialEq; - -#[test] -fn test_call_context_new() { - // When - let bytecode: Span = array![1, 2, 3].span(); - let calldata: Span = array![4, 5, 6].span(); - let value: u256 = callvalue(); - let address = test_address(); - let gas_price = 0xabde1; - let gas_limit = 0xe11a5; - let read_only = false; - let output_offset = 0; - let output_size = 0; - - let call_ctx = CallContextTrait::new( - address, - bytecode, - calldata, - value, - read_only, - gas_limit, - gas_price, - output_offset, - output_size, - ); - - // Then - assert(call_ctx.bytecode() == bytecode, 'wrong bytecode'); - assert(call_ctx.calldata() == calldata, 'wrong calldata'); - assert(call_ctx.value() == callvalue(), 'wrong value'); - assert(call_ctx.gas_limit() == gas_limit, 'wrong gas_limit'); - assert(call_ctx.gas_price() == gas_price, 'wrong gas_price'); - assert(call_ctx.read_only() == read_only, 'wrong read_only'); -} - -#[test] -fn test_execution_context_new() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - // Given - let call_ctx = machine.call_ctx(); - let context_id = ExecutionContextType::Root(false); - let program_counter: u32 = 0; - - let stopped: bool = false; - let return_data: Array = ArrayTrait::new(); - - let address: Address = Default::default(); - let reverted: bool = false; - let _read_only: bool = false; - - let parent_ctx: Nullable = null(); - - // When - let mut execution_context = ExecutionContextTrait::new( - context_id, address, call_ctx, parent_ctx, return_data.span() - ); - - // Then - assert(execution_context.call_ctx() == call_ctx, 'wrong call_ctx'); - assert(execution_context.program_counter == program_counter, 'wrong program_counter'); - assert(execution_context.stopped() == stopped, 'wrong stopped'); - assert(execution_context.return_data() == Default::default().span(), 'wrong return_data'); - assert(execution_context.address() == address, 'wrong evm_address'); - assert(execution_context.reverted() == reverted, 'wrong reverted'); - assert(execution_context.is_create() == false, 'wrong is_create'); - assert(execution_context.gas_used() == 0, 'wrong gas_used'); -} - -#[test] -fn test_execution_context_increment_gas_used_unchecked() { - // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - let mut execution_context = machine.current_ctx.unbox(); - - // When - let gas_used = test_utils::gas_limit(); - execution_context.increment_gas_used_unchecked(gas_used); - - // Then - assert_eq!(execution_context.gas_used(), gas_used); -} - -#[test] -fn test_execution_context_increment_gas_used_checked() { - // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - let mut execution_context = machine.current_ctx.unbox(); - - // When - let gas_used = test_utils::gas_limit(); - let result = execution_context.increment_gas_used_checked(gas_used); - - // Then - assert_eq!(result.unwrap_err(), EVMError::OutOfGas); -} - -#[test] -fn test_execution_context_stop_and_revert() { - // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - let mut execution_context = machine.current_ctx.unbox(); - - // When - execution_context.set_stopped(); - - // Then - assert(execution_context.stopped() == true, 'should be stopped'); -} - -#[test] -fn test_execution_context_revert() { - // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - let mut execution_context = machine.current_ctx.unbox(); - - // When - let _revert_reason = array![0, 1, 2, 3].span(); - execution_context.set_reverted(); - - // Then - assert(execution_context.reverted() == true, 'should be reverted'); -} - -#[test] -fn test_execution_context_read_code() { - // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(array![1, 2, 3].span()) - .build(); - - // When - let len = 2; - let code = machine.current_ctx.unbox().read_code(len); - - // Then - assert(code == array![1, 2].span(), 'wrong code read'); // Compare with expected slice -} - - -#[test] -fn test_is_root() { - // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - let mut execution_context = machine.current_ctx.unbox(); - - // When - let is_root = execution_context.is_root(); - - // Then - assert(is_root, 'should not be a leaf'); -} - - -#[test] -fn test_origin() { - // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_nested_execution_context() - .build(); - let mut context = machine.current_ctx.unbox(); - - // When - let origin = context.origin(); - // Then - assert(origin == test_address(), 'wrong origin'); -} diff --git a/crates/evm/src/tests/test_instructions/test_block_information.cairo b/crates/evm/src/tests/test_instructions/test_block_information.cairo index 8e3d70eb7..0d5ebd929 100644 --- a/crates/evm/src/tests/test_instructions/test_block_information.cairo +++ b/crates/evm/src/tests/test_instructions/test_block_information.cairo @@ -11,42 +11,43 @@ use core::traits::TryInto; use evm::instructions::BlockInformationTrait; use evm::model::contract_account::ContractAccountTrait; use evm::stack::StackTrait; -use evm::tests::test_utils::{evm_address, MachineBuilderTestTrait, gas_limit, gas_price}; +use evm::tests::test_utils::{evm_address, VMBuilderTrait, tx_gas_limit, gas_price}; use openzeppelin::token::erc20::interface::IERC20CamelDispatcherTrait; use starknet::testing::{ set_block_timestamp, set_block_number, set_contract_address, set_sequencer_address, ContractAddress }; +use utils::constants; /// 0x40 - BLOCKHASH #[test] fn test_exec_blockhash_below_bounds() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); set_block_number(500); // When - machine.stack.push(243).expect('push failed'); - machine.exec_blockhash().unwrap(); + vm.stack.push(243).expect('push failed'); + vm.exec_blockhash().unwrap(); // Then - assert(machine.stack.peek().unwrap() == 0, 'stack top should be 0'); + assert(vm.stack.peek().unwrap() == 0, 'stack top should be 0'); } #[test] fn test_exec_blockhash_above_bounds() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); set_block_number(500); // When - machine.stack.push(491).expect('push failed'); - machine.exec_blockhash().unwrap(); + vm.stack.push(491).expect('push failed'); + vm.exec_blockhash().unwrap(); // Then - assert(machine.stack.peek().unwrap() == 0, 'stack top should be 0'); + assert(vm.stack.peek().unwrap() == 0, 'stack top should be 0'); } // TODO: implement exec_blockhash testing for block number within bounds @@ -54,62 +55,62 @@ fn test_exec_blockhash_above_bounds() { #[test] fn test_exec_blockhash_within_bounds() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); set_block_number(500); // When - machine.stack.push(244).expect('push failed'); + vm.stack.push(244).expect('push failed'); //TODO the CASM runner used in tests doesn't implement //`get_block_hash_syscall` yet. As such, this test should fail no if the //queried block is within bounds - assert(machine.exec_blockhash().is_err(), 'CASM Runner cant blockhash'); + assert(vm.exec_blockhash().is_err(), 'CASM Runner cant blockhash'); // Then -// assert(machine.stack.peek().unwrap() == 0xF, 'stack top should be 0xF'); +// assert(vm.stack.peek().unwrap() == 0xF, 'stack top should be 0xF'); } #[test] fn test_block_timestamp_set_to_1692873993() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // 24/08/2023 12h46 33s // If not set the default timestamp is 0. set_block_timestamp(1692873993); // When - machine.exec_timestamp().unwrap(); + vm.exec_timestamp().unwrap(); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 1692873993, 'stack top should be 1692873993'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 1692873993, 'stack top should be 1692873993'); } #[test] fn test_block_number_set_to_32() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // If not set the default block number is 0. set_block_number(32); // When - machine.exec_number().unwrap(); + vm.exec_number().unwrap(); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 32, 'stack top should be 32'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 32, 'stack top should be 32'); } #[test] fn test_gaslimit() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When - machine.exec_gaslimit().unwrap(); + vm.exec_gaslimit().unwrap(); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); // This value is set in [new_with_presets]. - assert(machine.stack.peek().unwrap() == gas_limit().into(), 'stack top should be gas_limit'); + assert_eq!(vm.stack.peek().unwrap(), constants::BLOCK_GAS_LIMIT.into()) } // ************************************************************************* @@ -124,14 +125,14 @@ fn test_exec_selfbalance_eoa() { fund_account_with_native_token(eoa, native_token, 0x1); // And - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When set_contract_address(kakarot_core.contract_address); - machine.exec_selfbalance().unwrap(); + vm.exec_selfbalance().unwrap(); // Then - assert(machine.stack.peek().unwrap() == native_token.balanceOf(eoa), 'wrong balance'); + assert(vm.stack.peek().unwrap() == native_token.balanceOf(eoa), 'wrong balance'); } #[test] @@ -140,14 +141,14 @@ fn test_exec_selfbalance_zero() { let (_, kakarot_core) = setup_contracts_for_testing(); // And - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When set_contract_address(kakarot_core.contract_address); - machine.exec_selfbalance().unwrap(); + vm.exec_selfbalance().unwrap(); // Then - assert(machine.stack.peek().unwrap() == 0x00, 'wrong balance'); + assert(vm.stack.peek().unwrap() == 0x00, 'wrong balance'); } #[test] @@ -157,27 +158,27 @@ fn test_exec_selfbalance_contract_account() { let mut ca_address = deploy_contract_account(evm_address(), array![].span()); fund_account_with_native_token(ca_address.starknet, native_token, 0x1); - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When set_contract_address(kakarot_core.contract_address); - machine.exec_selfbalance().unwrap(); + vm.exec_selfbalance().unwrap(); // Then - assert(machine.stack.peek().unwrap() == 0x1, 'wrong balance'); + assert(vm.stack.peek().unwrap() == 0x1, 'wrong balance'); } #[test] fn test_basefee() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When - machine.exec_basefee().unwrap(); + vm.exec_basefee().unwrap(); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == gas_price().into(), 'stack top should be gas_price'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == gas_price().into(), 'stack top should be gas_price'); } #[test] @@ -185,7 +186,7 @@ fn test_chainid_should_push_chain_id_to_stack() { let (_, kakarot_core) = setup_contracts_for_testing(); // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); let chain_id: u256 = IExtendedKakarotCoreDispatcher { contract_address: kakarot_core.contract_address @@ -194,10 +195,10 @@ fn test_chainid_should_push_chain_id_to_stack() { .into(); // When - machine.exec_chainid().unwrap(); + vm.exec_chainid().unwrap(); // Then - let result = machine.stack.peek().unwrap(); + let result = vm.stack.peek().unwrap(); assert(result == chain_id, 'stack should have chain id'); } @@ -205,13 +206,13 @@ fn test_chainid_should_push_chain_id_to_stack() { #[test] fn test_randao_should_push_zero_to_stack() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When - machine.exec_prevrandao().unwrap(); + vm.exec_prevrandao().unwrap(); // Then - let result = machine.stack.peek().unwrap(); + let result = vm.stack.peek().unwrap(); assert(result == 0x00, 'stack top should be zero'); } @@ -219,20 +220,19 @@ fn test_randao_should_push_zero_to_stack() { // 0x41: COINBASE // ************************************************************************* #[test] -#[available_gas(5000000)] fn test_exec_coinbase() { // Given let (_, kakarot_core) = setup_contracts_for_testing(); let sequencer_eoa = kakarot_core.deploy_eoa(evm_address()); // And - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When set_sequencer_address(sequencer_eoa); - machine.exec_coinbase().unwrap(); + vm.exec_coinbase().unwrap(); - let sequencer_address = machine.stack.pop().unwrap(); + let sequencer_address = vm.stack.pop().unwrap(); // Then assert(evm_address().address.into() == sequencer_address, 'wrong sequencer_address'); diff --git a/crates/evm/src/tests/test_instructions/test_comparison_operations.cairo b/crates/evm/src/tests/test_instructions/test_comparison_operations.cairo index 509099630..aafe0ab5b 100644 --- a/crates/evm/src/tests/test_instructions/test_comparison_operations.cairo +++ b/crates/evm/src/tests/test_instructions/test_comparison_operations.cairo @@ -1,102 +1,100 @@ use evm::instructions::ComparisonAndBitwiseOperationsTrait; use evm::stack::StackTrait; -use evm::tests::test_utils::MachineBuilderTestTrait; +use evm::tests::test_utils::VMBuilderTrait; use integer::BoundedInt; #[test] fn test_eq_same_pair() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm .stack .push(0xFEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210) .expect('push failed'); - machine + vm .stack .push(0xFEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210) .expect('push failed'); // When - machine.exec_eq().expect('exec_eq failed'); + vm.exec_eq().expect('exec_eq failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0x01, 'stack top should be 0x01'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0x01, 'stack top should be 0x01'); } #[test] fn test_eq_different_pair() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm .stack .push(0xAB8765432DCBA98765410F149E87610FDCBA98765432543217654DCBA93210F8) .expect('push failed'); - machine + vm .stack .push(0xFEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210) .expect('push failed'); // When - machine.exec_eq().expect('exec_eq failed'); + vm.exec_eq().expect('exec_eq failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0x00, 'stack top should be 0x00'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0x00, 'stack top should be 0x00'); } #[test] fn test_and_zero_and_max() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(0x00).expect('push failed'); - machine.stack.push(BoundedInt::::max()).unwrap(); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(0x00).expect('push failed'); + vm.stack.push(BoundedInt::::max()).unwrap(); // When - machine.exec_and().expect('exec_and failed'); + vm.exec_and().expect('exec_and failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0x00, 'stack top should be 0x00'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0x00, 'stack top should be 0x00'); } #[test] fn test_and_max_and_max() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(BoundedInt::::max()).unwrap(); - machine.stack.push(BoundedInt::::max()).unwrap(); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(BoundedInt::::max()).unwrap(); + vm.stack.push(BoundedInt::::max()).unwrap(); // When - machine.exec_and().expect('exec_and failed'); + vm.exec_and().expect('exec_and failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert( - machine.stack.peek().unwrap() == BoundedInt::::max(), 'stack top should be 0xFF...FFF' - ); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == BoundedInt::::max(), 'stack top should be 0xFF...FFF'); } #[test] fn test_and_two_random_uint() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm .stack .push(0xAB8765432DCBA98765410F149E87610FDCBA98765432543217654DCBA93210F8) .expect('push failed'); - machine + vm .stack .push(0xFEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210) .expect('push failed'); // When - machine.exec_and().expect('exec_and failed'); + vm.exec_and().expect('exec_and failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine + vm .stack .peek() .unwrap() == 0xAA8420002440200064400A1016042000DC989810541010101644088820101010, @@ -108,96 +106,95 @@ fn test_and_two_random_uint() { #[test] fn test_xor_different_pair() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(0b010101).expect('push failed'); - machine.stack.push(0b101010).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(0b010101).expect('push failed'); + vm.stack.push(0b101010).expect('push failed'); // When - machine.exec_xor().expect('exec_xor failed'); + vm.exec_xor().expect('exec_xor failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0b111111, 'stack top should be 0xFF'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0b111111, 'stack top should be 0xFF'); } #[test] fn test_xor_same_pair() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(0b000111).expect('push failed'); - machine.stack.push(0b000111).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(0b000111).expect('push failed'); + vm.stack.push(0b000111).expect('push failed'); // When - machine.exec_xor().expect('exec_xor failed'); + vm.exec_xor().expect('exec_xor failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0x00, 'stack top should be 0x00'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0x00, 'stack top should be 0x00'); } #[test] fn test_xor_half_same_pair() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(0b111000).expect('push failed'); - machine.stack.push(0b000000).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(0b111000).expect('push failed'); + vm.stack.push(0b000000).expect('push failed'); // When - machine.exec_xor().expect('exec_xor failed'); + vm.exec_xor().expect('exec_xor failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0b111000, 'stack top should be 0xFF'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0b111000, 'stack top should be 0xFF'); } #[test] fn test_not_zero() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(0x00).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(0x00).expect('push failed'); // When - machine.exec_not().expect('exec_not failed'); + vm.exec_not().expect('exec_not failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine.stack.peek().unwrap() == BoundedInt::::max(), - 'stack top should be 0xFFF..FFFF' + vm.stack.peek().unwrap() == BoundedInt::::max(), 'stack top should be 0xFFF..FFFF' ); } #[test] fn test_not_max_uint() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(BoundedInt::::max()).unwrap(); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(BoundedInt::::max()).unwrap(); // When - machine.exec_not().expect('exec_not failed'); + vm.exec_not().expect('exec_not failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0x00, 'stack top should be 0x00'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0x00, 'stack top should be 0x00'); } #[test] fn test_not_random_uint() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm .stack .push(0x123456789ABCDEF123456789ABCDEF123456789ABCDEF123456789ABCDEF1234) .expect('push failed'); // When - machine.exec_not().expect('exec_not failed'); + vm.exec_not().expect('exec_not failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine + vm .stack .peek() .unwrap() == 0xEDCBA9876543210EDCBA9876543210EDCBA9876543210EDCBA9876543210EDCB, @@ -208,99 +205,99 @@ fn test_not_random_uint() { #[test] fn test_is_zero_true() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(0x00).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(0x00).expect('push failed'); // When - machine.exec_iszero().expect('exec_iszero failed'); + vm.exec_iszero().expect('exec_iszero failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0x01, 'stack top should be true'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0x01, 'stack top should be true'); } #[test] fn test_is_zero_false() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(0x01).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(0x01).expect('push failed'); // When - machine.exec_iszero().expect('exec_iszero failed'); + vm.exec_iszero().expect('exec_iszero failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0x00, 'stack top should be false'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0x00, 'stack top should be false'); } #[test] fn test_byte_random_u256() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm .stack .push(0xf7ec8b2ea4a6b7fd5f4ed41b66197fcc14c4a37d68275ea151d899bb4d7c2ae7) .expect('push failed'); - machine.stack.push(0x08).expect('push failed'); + vm.stack.push(0x08).expect('push failed'); // When - machine.exec_byte().expect('exec_byte failed'); + vm.exec_byte().expect('exec_byte failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0x5f, 'stack top should be 0x22'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0x5f, 'stack top should be 0x22'); } #[test] fn test_byte_offset_out_of_range() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm .stack .push(0x01be893aefcfa1592f60622b80d45c2db74281d2b9e10c14b0f6ce7c8f58e209) .expect('push failed'); - machine.stack.push(32_u256).expect('push failed'); + vm.stack.push(32_u256).expect('push failed'); // When - machine.exec_byte().expect('exec_byte failed'); + vm.exec_byte().expect('exec_byte failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0x00, 'stack top should be 0x00'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0x00, 'stack top should be 0x00'); } #[test] fn test_exec_gt_true() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(9_u256).expect('push failed'); - machine.stack.push(10_u256).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(9_u256).expect('push failed'); + vm.stack.push(10_u256).expect('push failed'); // When - machine.exec_gt().expect('exec_gt failed'); + vm.exec_gt().expect('exec_gt failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 1, 'stack top should be 1'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 1, 'stack top should be 1'); } #[test] fn test_exec_shl() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm .stack .push(0xff00000000000000000000000000000000000000000000000000000000000000) .expect('push failed'); - machine.stack.push(4_u256).expect('push failed'); + vm.stack.push(4_u256).expect('push failed'); // When - machine.exec_shl().expect('exec_shl failed'); + vm.exec_shl().expect('exec_shl failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine + vm .stack .peek() .unwrap() == 0xf000000000000000000000000000000000000000000000000000000000000000, @@ -311,49 +308,49 @@ fn test_exec_shl() { #[test] fn test_exec_shl_wrapping() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm .stack .push(0xff00000000000000000000000000000000000000000000000000000000000000) .expect('push failed'); - machine.stack.push(256_u256).expect('push failed'); + vm.stack.push(256_u256).expect('push failed'); // When - machine.exec_shl().expect('exec_shl failed'); + vm.exec_shl().expect('exec_shl failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0, 'if shift > 255 should return 0'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0, 'if shift > 255 should return 0'); } #[test] fn test_exec_gt_false() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(10_u256).expect('push failed'); - machine.stack.push(9_u256).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(10_u256).expect('push failed'); + vm.stack.push(9_u256).expect('push failed'); // When - machine.exec_gt().expect('exec_gt failed'); + vm.exec_gt().expect('exec_gt failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0, 'stack top should be 0'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0, 'stack top should be 0'); } #[test] fn test_exec_gt_false_equal() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(10_u256).expect('push failed'); - machine.stack.push(10_u256).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(10_u256).expect('push failed'); + vm.stack.push(10_u256).expect('push failed'); // When - machine.exec_gt().expect('exec_gt failed'); + vm.exec_gt().expect('exec_gt failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0, 'stack top should be 0'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0, 'stack top should be 0'); } #[test] @@ -588,16 +585,16 @@ fn test_exec_slt() { fn assert_slt(b: u256, a: u256, expected: u256) { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(b).expect('push failed'); - machine.stack.push(a).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(b).expect('push failed'); + vm.stack.push(a).expect('push failed'); // When - machine.exec_slt().expect('exec_slt failed'); + vm.exec_slt().expect('exec_slt failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == expected, 'slt failed'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == expected, 'slt failed'); } #[test] @@ -832,16 +829,16 @@ fn test_exec_sgt() { fn assert_sgt(b: u256, a: u256, expected: u256) { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(b).expect('push failed'); - machine.stack.push(a).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(b).expect('push failed'); + vm.stack.push(a).expect('push failed'); // When - machine.exec_sgt().expect('exec_sgt failed'); + vm.exec_sgt().expect('exec_sgt failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == expected, 'sgt failed'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == expected, 'sgt failed'); } #[test] @@ -1256,16 +1253,16 @@ fn test_exec_shr() { fn assert_shr(a: u256, b: u256, expected: u256) { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(a).expect('push failed'); - machine.stack.push(b).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(a).expect('push failed'); + vm.stack.push(b).expect('push failed'); // When - machine.exec_shr().expect('exec_shr failed'); + vm.exec_shr().expect('exec_shr failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == expected, 'shr failed'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == expected, 'shr failed'); } #[test] @@ -1680,106 +1677,106 @@ fn test_exec_sar() { fn assert_sar(a: u256, b: u256, expected: u256) { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(a).expect('push failed'); - machine.stack.push(b).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(a).expect('push failed'); + vm.stack.push(b).expect('push failed'); // When - machine.exec_sar().expect('exec_sar failed'); + vm.exec_sar().expect('exec_sar failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == expected, 'sar failed'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == expected, 'sar failed'); } #[test] fn test_exec_or_should_pop_0_and_1_and_push_0xCD_when_0_is_0x89_and_1_is_0xC5() { //Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(0x89).expect('push failed'); - machine.stack.push(0xC5).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(0x89).expect('push failed'); + vm.stack.push(0xC5).expect('push failed'); //When - machine.exec_or().expect('exec_or failed'); + vm.exec_or().expect('exec_or failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0xCD, 'stack top should be 0xCD'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xCD, 'stack top should be 0xCD'); } #[test] fn test_or_true() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(0x01).expect('push failed'); - machine.stack.push(0x00).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(0x01).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); // When - machine.exec_or().expect('exec_or failed'); + vm.exec_or().expect('exec_or failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0x01, 'stack top should be 0x01'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0x01, 'stack top should be 0x01'); } #[test] fn test_or_false() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(0x00).expect('push failed'); - machine.stack.push(0x00).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(0x00).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); // When - machine.exec_or().expect('exec_or failed'); + vm.exec_or().expect('exec_or failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0x00, 'stack top should be 0x00'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0x00, 'stack top should be 0x00'); } #[test] fn test_exec_lt_true() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(10_u256).expect('push failed'); - machine.stack.push(9_u256).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(10_u256).expect('push failed'); + vm.stack.push(9_u256).expect('push failed'); // When - machine.exec_lt().expect('exec_lt failed'); + vm.exec_lt().expect('exec_lt failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0x01, 'stack top should be true'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0x01, 'stack top should be true'); } #[test] fn test_exec_lt_false() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(10_u256).expect('push failed'); - machine.stack.push(20_u256).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(10_u256).expect('push failed'); + vm.stack.push(20_u256).expect('push failed'); // When - machine.exec_lt().expect('exec_lt failed'); + vm.exec_lt().expect('exec_lt failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0x00, 'stack top should be false'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0x00, 'stack top should be false'); } #[test] fn test_exec_lt_false_eq() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(10_u256).expect('push failed'); - machine.stack.push(10_u256).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(10_u256).expect('push failed'); + vm.stack.push(10_u256).expect('push failed'); // When - machine.exec_lt().expect('exec_lt failed'); + vm.exec_lt().expect('exec_lt failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0x00, 'stack top should be false'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0x00, 'stack top should be false'); } diff --git a/crates/evm/src/tests/test_instructions/test_duplication_operations.cairo b/crates/evm/src/tests/test_instructions/test_duplication_operations.cairo index 118826b6b..300abcc9b 100644 --- a/crates/evm/src/tests/test_instructions/test_duplication_operations.cairo +++ b/crates/evm/src/tests/test_instructions/test_duplication_operations.cairo @@ -1,7 +1,7 @@ use evm::instructions::DuplicationOperationsTrait; use evm::stack::Stack; use evm::stack::StackTrait; -use evm::tests::test_utils::MachineBuilderTestTrait; +use evm::tests::test_utils::VMBuilderTrait; use integer::BoundedInt; @@ -38,414 +38,414 @@ fn push_zeros(ref stack: Stack, n: u8) { #[test] fn test_dup1() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - let initial_len = machine.stack.len(); + let initial_len = vm.stack.len(); - machine.stack.push(0x01).expect('push failed'); + vm.stack.push(0x01).expect('push failed'); - let old_stack_len = machine.stack.len(); + let old_stack_len = vm.stack.len(); // When - machine.exec_dup1().expect('exec_dup1 failed'); + vm.exec_dup1().expect('exec_dup1 failed'); // Then - let new_stack_len = machine.stack.len(); + let new_stack_len = vm.stack.len(); assert(new_stack_len == old_stack_len + 1, 'len should increase by 1'); - assert(machine.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); - assert(machine.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); + assert(vm.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); + assert(vm.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); - ensures_zeros(ref machine.stack, initial_len + 1, new_stack_len - 1); + ensures_zeros(ref vm.stack, initial_len + 1, new_stack_len - 1); } #[test] fn test_dup2() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - let initial_len = machine.stack.len(); + let initial_len = vm.stack.len(); - machine.stack.push(0x01).expect('push failed'); - push_zeros(ref machine.stack, 1); + vm.stack.push(0x01).expect('push failed'); + push_zeros(ref vm.stack, 1); - let old_stack_len = machine.stack.len(); + let old_stack_len = vm.stack.len(); // When - machine.exec_dup2().expect('exec_dup2 failed'); + vm.exec_dup2().expect('exec_dup2 failed'); // Then - let new_stack_len = machine.stack.len(); + let new_stack_len = vm.stack.len(); assert(new_stack_len == old_stack_len + 1, 'len should increase by 1'); - assert(machine.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); - assert(machine.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); + assert(vm.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); + assert(vm.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); - ensures_zeros(ref machine.stack, initial_len + 1, new_stack_len - 1); + ensures_zeros(ref vm.stack, initial_len + 1, new_stack_len - 1); } #[test] fn test_dup3() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - let initial_len = machine.stack.len(); + let initial_len = vm.stack.len(); - machine.stack.push(0x01).expect('push failed'); - push_zeros(ref machine.stack, 2); + vm.stack.push(0x01).expect('push failed'); + push_zeros(ref vm.stack, 2); - let old_stack_len = machine.stack.len(); + let old_stack_len = vm.stack.len(); // When - machine.exec_dup3().expect('exec_dup3 failed'); + vm.exec_dup3().expect('exec_dup3 failed'); // Then - let new_stack_len = machine.stack.len(); + let new_stack_len = vm.stack.len(); assert(new_stack_len == old_stack_len + 1, 'len should increase by 1'); - assert(machine.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); - assert(machine.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); + assert(vm.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); + assert(vm.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); - ensures_zeros(ref machine.stack, initial_len + 1, new_stack_len - 1); + ensures_zeros(ref vm.stack, initial_len + 1, new_stack_len - 1); } #[test] fn test_dup4() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - let initial_len = machine.stack.len(); + let initial_len = vm.stack.len(); - machine.stack.push(0x01).expect('push failed'); - push_zeros(ref machine.stack, 3); + vm.stack.push(0x01).expect('push failed'); + push_zeros(ref vm.stack, 3); - let old_stack_len = machine.stack.len(); + let old_stack_len = vm.stack.len(); // When - machine.exec_dup4().expect('exec_dup4 failed'); + vm.exec_dup4().expect('exec_dup4 failed'); // Then - let new_stack_len = machine.stack.len(); + let new_stack_len = vm.stack.len(); assert(new_stack_len == old_stack_len + 1, 'len should increase by 1'); - assert(machine.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); - assert(machine.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); + assert(vm.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); + assert(vm.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); - ensures_zeros(ref machine.stack, initial_len + 1, new_stack_len - 1); + ensures_zeros(ref vm.stack, initial_len + 1, new_stack_len - 1); } #[test] fn test_dup5() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - let initial_len = machine.stack.len(); + let initial_len = vm.stack.len(); - machine.stack.push(0x01).expect('push failed'); - push_zeros(ref machine.stack, 4); + vm.stack.push(0x01).expect('push failed'); + push_zeros(ref vm.stack, 4); - let old_stack_len = machine.stack.len(); + let old_stack_len = vm.stack.len(); // When - machine.exec_dup5().expect('exec_dup5 failed'); + vm.exec_dup5().expect('exec_dup5 failed'); // Then - let new_stack_len = machine.stack.len(); + let new_stack_len = vm.stack.len(); assert(new_stack_len == old_stack_len + 1, 'len should increase by 1'); - assert(machine.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); - assert(machine.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); + assert(vm.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); + assert(vm.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); - ensures_zeros(ref machine.stack, initial_len + 1, new_stack_len - 1); + ensures_zeros(ref vm.stack, initial_len + 1, new_stack_len - 1); } #[test] fn test_dup6() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - let initial_len = machine.stack.len(); + let initial_len = vm.stack.len(); - machine.stack.push(0x01).expect('push failed'); - push_zeros(ref machine.stack, 5); + vm.stack.push(0x01).expect('push failed'); + push_zeros(ref vm.stack, 5); - let old_stack_len = machine.stack.len(); + let old_stack_len = vm.stack.len(); // When - machine.exec_dup6().expect('exec_dup6 failed'); + vm.exec_dup6().expect('exec_dup6 failed'); // Then - let new_stack_len = machine.stack.len(); + let new_stack_len = vm.stack.len(); assert(new_stack_len == old_stack_len + 1, 'len should increase by 1'); - assert(machine.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); - assert(machine.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); + assert(vm.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); + assert(vm.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); - ensures_zeros(ref machine.stack, initial_len + 1, new_stack_len - 1); + ensures_zeros(ref vm.stack, initial_len + 1, new_stack_len - 1); } #[test] fn test_dup7() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - let initial_len = machine.stack.len(); + let initial_len = vm.stack.len(); - machine.stack.push(0x01).expect('push failed'); - push_zeros(ref machine.stack, 6); + vm.stack.push(0x01).expect('push failed'); + push_zeros(ref vm.stack, 6); - let old_stack_len = machine.stack.len(); + let old_stack_len = vm.stack.len(); // When - machine.exec_dup7().expect('exec_dup7 failed'); + vm.exec_dup7().expect('exec_dup7 failed'); // Then - let new_stack_len = machine.stack.len(); + let new_stack_len = vm.stack.len(); assert(new_stack_len == old_stack_len + 1, 'len should increase by 1'); - assert(machine.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); - assert(machine.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); + assert(vm.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); + assert(vm.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); - ensures_zeros(ref machine.stack, initial_len + 1, new_stack_len - 1); + ensures_zeros(ref vm.stack, initial_len + 1, new_stack_len - 1); } #[test] fn test_dup8() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - let initial_len = machine.stack.len(); + let initial_len = vm.stack.len(); - machine.stack.push(0x01).expect('push failed'); - push_zeros(ref machine.stack, 7); + vm.stack.push(0x01).expect('push failed'); + push_zeros(ref vm.stack, 7); - let old_stack_len = machine.stack.len(); + let old_stack_len = vm.stack.len(); // When - machine.exec_dup8().expect('exec_dup8 failed'); + vm.exec_dup8().expect('exec_dup8 failed'); // Then - let new_stack_len = machine.stack.len(); + let new_stack_len = vm.stack.len(); assert(new_stack_len == old_stack_len + 1, 'len should increase by 1'); - assert(machine.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); - assert(machine.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); + assert(vm.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); + assert(vm.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); - ensures_zeros(ref machine.stack, initial_len + 1, new_stack_len - 1); + ensures_zeros(ref vm.stack, initial_len + 1, new_stack_len - 1); } #[test] fn test_dup9() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - let initial_len = machine.stack.len(); + let initial_len = vm.stack.len(); - machine.stack.push(0x01).expect('push failed'); - push_zeros(ref machine.stack, 8); + vm.stack.push(0x01).expect('push failed'); + push_zeros(ref vm.stack, 8); - let old_stack_len = machine.stack.len(); + let old_stack_len = vm.stack.len(); // When - machine.exec_dup9().expect('exec_dup9 failed'); + vm.exec_dup9().expect('exec_dup9 failed'); // Then - let new_stack_len = machine.stack.len(); + let new_stack_len = vm.stack.len(); assert(new_stack_len == old_stack_len + 1, 'len should increase by 1'); - assert(machine.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); - assert(machine.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); + assert(vm.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); + assert(vm.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); - ensures_zeros(ref machine.stack, initial_len + 1, new_stack_len - 1); + ensures_zeros(ref vm.stack, initial_len + 1, new_stack_len - 1); } #[test] fn test_dup10() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - let initial_len = machine.stack.len(); + let initial_len = vm.stack.len(); - machine.stack.push(0x01).expect('push failed'); - push_zeros(ref machine.stack, 9); + vm.stack.push(0x01).expect('push failed'); + push_zeros(ref vm.stack, 9); - let old_stack_len = machine.stack.len(); + let old_stack_len = vm.stack.len(); // When - machine.exec_dup10().expect('exec_dup10 failed'); + vm.exec_dup10().expect('exec_dup10 failed'); // Then - let new_stack_len = machine.stack.len(); + let new_stack_len = vm.stack.len(); assert(new_stack_len == old_stack_len + 1, 'len should increase by 1'); - assert(machine.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); - assert(machine.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); + assert(vm.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); + assert(vm.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); - ensures_zeros(ref machine.stack, initial_len + 1, new_stack_len - 1); + ensures_zeros(ref vm.stack, initial_len + 1, new_stack_len - 1); } #[test] fn test_dup11() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - let initial_len = machine.stack.len(); + let initial_len = vm.stack.len(); - machine.stack.push(0x01).expect('push failed'); - push_zeros(ref machine.stack, 10); + vm.stack.push(0x01).expect('push failed'); + push_zeros(ref vm.stack, 10); - let old_stack_len = machine.stack.len(); + let old_stack_len = vm.stack.len(); // When - machine.exec_dup11().expect('exec_dup11 failed'); + vm.exec_dup11().expect('exec_dup11 failed'); // Then - let new_stack_len = machine.stack.len(); + let new_stack_len = vm.stack.len(); assert(new_stack_len == old_stack_len + 1, 'len should increase by 1'); - assert(machine.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); - assert(machine.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); + assert(vm.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); + assert(vm.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); - ensures_zeros(ref machine.stack, initial_len + 1, new_stack_len - 1); + ensures_zeros(ref vm.stack, initial_len + 1, new_stack_len - 1); } #[test] fn test_dup12() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - let initial_len = machine.stack.len(); + let initial_len = vm.stack.len(); - machine.stack.push(0x01).expect('push failed'); - push_zeros(ref machine.stack, 11); + vm.stack.push(0x01).expect('push failed'); + push_zeros(ref vm.stack, 11); - let old_stack_len = machine.stack.len(); + let old_stack_len = vm.stack.len(); // When - machine.exec_dup12().expect('exec_dup12 failed'); + vm.exec_dup12().expect('exec_dup12 failed'); // Then - let new_stack_len = machine.stack.len(); + let new_stack_len = vm.stack.len(); assert(new_stack_len == old_stack_len + 1, 'len should increase by 1'); - assert(machine.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); - assert(machine.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); + assert(vm.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); + assert(vm.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); - ensures_zeros(ref machine.stack, initial_len + 1, new_stack_len - 1); + ensures_zeros(ref vm.stack, initial_len + 1, new_stack_len - 1); } #[test] fn test_dup13() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - let initial_len = machine.stack.len(); + let initial_len = vm.stack.len(); - machine.stack.push(0x01).expect('push failed'); - push_zeros(ref machine.stack, 12); + vm.stack.push(0x01).expect('push failed'); + push_zeros(ref vm.stack, 12); - let old_stack_len = machine.stack.len(); + let old_stack_len = vm.stack.len(); // When - machine.exec_dup13().expect('exec_dup13 failed'); + vm.exec_dup13().expect('exec_dup13 failed'); // Then - let new_stack_len = machine.stack.len(); + let new_stack_len = vm.stack.len(); assert(new_stack_len == old_stack_len + 1, 'len should increase by 1'); - assert(machine.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); - assert(machine.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); + assert(vm.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); + assert(vm.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); - ensures_zeros(ref machine.stack, initial_len + 1, new_stack_len - 1); + ensures_zeros(ref vm.stack, initial_len + 1, new_stack_len - 1); } #[test] fn test_dup14() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - let initial_len = machine.stack.len(); + let initial_len = vm.stack.len(); - machine.stack.push(0x01).expect('push failed'); - push_zeros(ref machine.stack, 13); + vm.stack.push(0x01).expect('push failed'); + push_zeros(ref vm.stack, 13); - let old_stack_len = machine.stack.len(); + let old_stack_len = vm.stack.len(); // When - machine.exec_dup14().expect('exec_dup14 failed'); + vm.exec_dup14().expect('exec_dup14 failed'); // Then - let new_stack_len = machine.stack.len(); + let new_stack_len = vm.stack.len(); assert(new_stack_len == old_stack_len + 1, 'len should increase by 1'); - assert(machine.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); - assert(machine.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); + assert(vm.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); + assert(vm.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); - ensures_zeros(ref machine.stack, initial_len + 1, new_stack_len - 1); + ensures_zeros(ref vm.stack, initial_len + 1, new_stack_len - 1); } #[test] fn test_dup15() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - let initial_len = machine.stack.len(); + let initial_len = vm.stack.len(); - machine.stack.push(0x01).expect('push failed'); - push_zeros(ref machine.stack, 14); + vm.stack.push(0x01).expect('push failed'); + push_zeros(ref vm.stack, 14); - let old_stack_len = machine.stack.len(); + let old_stack_len = vm.stack.len(); // When - machine.exec_dup15().expect('exec_dup15 failed'); + vm.exec_dup15().expect('exec_dup15 failed'); // Then - let new_stack_len = machine.stack.len(); + let new_stack_len = vm.stack.len(); assert(new_stack_len == old_stack_len + 1, 'len should increase by 1'); - assert(machine.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); - assert(machine.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); + assert(vm.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); + assert(vm.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); - ensures_zeros(ref machine.stack, initial_len + 1, new_stack_len - 1); + ensures_zeros(ref vm.stack, initial_len + 1, new_stack_len - 1); } #[test] fn test_dup16() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - let initial_len = machine.stack.len(); + let initial_len = vm.stack.len(); - machine.stack.push(0x01).expect('push failed'); - push_zeros(ref machine.stack, 15); + vm.stack.push(0x01).expect('push failed'); + push_zeros(ref vm.stack, 15); - let old_stack_len = machine.stack.len(); + let old_stack_len = vm.stack.len(); // When - machine.exec_dup16().expect('exec_dup16 failed'); + vm.exec_dup16().expect('exec_dup16 failed'); // Then - let new_stack_len = machine.stack.len(); + let new_stack_len = vm.stack.len(); assert(new_stack_len == old_stack_len + 1, 'len should increase by 1'); - assert(machine.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); - assert(machine.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); + assert(vm.stack.peek_at(initial_len).unwrap() == 0x01, 'first inserted spot should be 1'); + assert(vm.stack.peek_at(new_stack_len - 1).unwrap() == 0x01, 'top of stack should be 1'); - ensures_zeros(ref machine.stack, initial_len + 1, new_stack_len - 1); + ensures_zeros(ref vm.stack, initial_len + 1, new_stack_len - 1); } diff --git a/crates/evm/src/tests/test_instructions/test_environment_information.cairo b/crates/evm/src/tests/test_instructions/test_environment_information.cairo index d0ab51d56..8cee1c14a 100644 --- a/crates/evm/src/tests/test_instructions/test_environment_information.cairo +++ b/crates/evm/src/tests/test_instructions/test_environment_information.cairo @@ -5,15 +5,15 @@ use contracts::tests::test_utils::{ }; use evm::errors::{EVMError, TYPE_CONVERSION_ERROR, RETURNDATA_OUT_OF_BOUNDS_ERROR}; use evm::instructions::EnvironmentInformationTrait; -use evm::machine::{Machine, MachineTrait}; use evm::memory::{InternalMemoryTrait, MemoryTrait}; use evm::model::contract_account::ContractAccountTrait; +use evm::model::vm::{VM, VMTrait}; use evm::model::{Account, AccountType}; use evm::stack::StackTrait; use evm::state::StateTrait; use evm::tests::test_utils::{ - MachineBuilderTestTrait, evm_address, callvalue, return_from_subcontext, native_token, - other_address, gas_price, gas_limit + VMBuilderTrait, evm_address, origin, callvalue, native_token, other_address, gas_price, + tx_gas_limit }; use integer::u32_overflowing_add; use openzeppelin::token::erc20::interface::IERC20CamelDispatcherTrait; @@ -29,14 +29,14 @@ use utils::traits::{EthAddressIntoU256}; #[test] fn test_address_basic() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When - machine.exec_address().expect('exec_address failed'); + vm.exec_address().expect('exec_address failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.pop_eth_address().unwrap() == evm_address(), 'should be `evm_address`'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.pop_eth_address().unwrap() == evm_address(), 'should be `evm_address`'); } #[test] @@ -58,16 +58,16 @@ fn test_exec_balance_eoa() { fund_account_with_native_token(eoa, native_token, 0x1); // And - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(evm_address().into()).unwrap(); + vm.stack.push(evm_address().into()).unwrap(); // When set_contract_address(kakarot_core.contract_address); - machine.exec_balance().expect('exec_balance failed'); + vm.exec_balance().expect('exec_balance failed'); // Then - assert(machine.stack.peek().unwrap() == native_token.balanceOf(eoa), 'wrong balance'); + assert(vm.stack.peek().unwrap() == native_token.balanceOf(eoa), 'wrong balance'); } #[test] @@ -76,16 +76,16 @@ fn test_exec_balance_zero() { let (_, kakarot_core) = setup_contracts_for_testing(); // And - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(evm_address().into()).unwrap(); + vm.stack.push(evm_address().into()).unwrap(); // When set_contract_address(kakarot_core.contract_address); - machine.exec_balance().expect('exec_balance failed'); + vm.exec_balance().expect('exec_balance failed'); // Then - assert(machine.stack.peek().unwrap() == 0x00, 'wrong balance'); + assert(vm.stack.peek().unwrap() == 0x00, 'wrong balance'); } #[test] @@ -97,16 +97,16 @@ fn test_exec_balance_contract_account() { fund_account_with_native_token(ca_address.starknet, native_token, 0x1); // And - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(evm_address().into()).unwrap(); + vm.stack.push(evm_address().into()).unwrap(); // When set_contract_address(kakarot_core.contract_address); - machine.exec_balance().expect('exec_balance failed'); + vm.exec_balance().expect('exec_balance failed'); // Then - assert(machine.stack.peek().unwrap() == 0x1, 'wrong balance'); + assert(vm.stack.peek().unwrap() == 0x1, 'wrong balance'); } @@ -116,49 +116,31 @@ fn test_exec_balance_contract_account() { #[test] fn test_caller() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When - machine.exec_caller().expect('exec_caller failed'); + vm.exec_caller().expect('exec_caller failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == evm_address().into(), 'should be evm_address'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == origin().into(), 'should be evm_address'); } // ************************************************************************* // 0x32: ORIGIN // ************************************************************************* -#[test] -fn test_origin() { - // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_nested_execution_context() - .build(); - - // When - machine.exec_origin().expect('exec_origin failed'); - - // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == evm_address().into(), 'should be `evm_address`'); - - // And - assert(machine.caller() == other_address(), 'should be another_evm_address'); -} - #[test] fn test_origin_nested_ctx() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When - machine.exec_origin().expect('exec_origin failed'); + vm.exec_origin().expect('exec_origin failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == evm_address().into(), 'should be `evm_address`'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == origin().into(), 'should be `evm_address`'); } @@ -169,14 +151,14 @@ fn test_origin_nested_ctx() { #[test] fn test_exec_callvalue() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When - machine.exec_callvalue().expect('exec_callvalue failed'); + vm.exec_callvalue().expect('exec_callvalue failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.pop().unwrap() == callvalue(), 'should be `123456789'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.pop().unwrap() == callvalue(), 'should be `123456789'); } // ************************************************************************* @@ -189,18 +171,16 @@ fn test_calldataload() { let calldata = u256_to_bytes_array( 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ); - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_calldata(calldata.span()) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_calldata(calldata.span()).build(); let offset: u32 = 0; - machine.stack.push(offset.into()).expect('push failed'); + vm.stack.push(offset.into()).expect('push failed'); // When - machine.exec_calldataload().expect('exec_calldataload failed'); + vm.exec_calldataload().expect('exec_calldataload failed'); // Then - let result: u256 = machine.stack.pop().unwrap(); + let result: u256 = vm.stack.pop().unwrap(); assert( result == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'wrong data value' @@ -214,18 +194,16 @@ fn test_calldataload_with_offset() { 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ); - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_calldata(calldata.span()) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_calldata(calldata.span()).build(); let offset: u32 = 31; - machine.stack.push(offset.into()).expect('push failed'); + vm.stack.push(offset.into()).expect('push failed'); // When - machine.exec_calldataload().expect('exec_calldataload failed'); + vm.exec_calldataload().expect('exec_calldataload failed'); // Then - let result: u256 = machine.stack.pop().unwrap(); + let result: u256 = vm.stack.pop().unwrap(); assert( result == 0xFF00000000000000000000000000000000000000000000000000000000000000, @@ -239,18 +217,16 @@ fn test_calldataload_with_offset_beyond_calldata() { let calldata = u256_to_bytes_array( 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ); - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_calldata(calldata.span()) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_calldata(calldata.span()).build(); let offset: u32 = calldata.len() + 1; - machine.stack.push(offset.into()).expect('push failed'); + vm.stack.push(offset.into()).expect('push failed'); // When - machine.exec_calldataload().expect('exec_calldataload failed'); + vm.exec_calldataload().expect('exec_calldataload failed'); // Then - let result: u256 = machine.stack.pop().unwrap(); + let result: u256 = vm.stack.pop().unwrap(); assert(result == 0, 'result should be 0'); } @@ -258,18 +234,16 @@ fn test_calldataload_with_offset_beyond_calldata() { fn test_calldataload_with_function_selector() { // Given let calldata = array![0x6d, 0x4c, 0xe6, 0x3c]; - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_calldata(calldata.span()) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_calldata(calldata.span()).build(); let offset: u32 = 0; - machine.stack.push(offset.into()).expect('push failed'); + vm.stack.push(offset.into()).expect('push failed'); // When - machine.exec_calldataload().expect('exec_calldataload failed'); + vm.exec_calldataload().expect('exec_calldataload failed'); // Then - let result: u256 = machine.stack.pop().unwrap(); + let result: u256 = vm.stack.pop().unwrap(); assert( result == 0x6d4ce63c00000000000000000000000000000000000000000000000000000000, 'wrong result' ); @@ -282,14 +256,12 @@ fn test_calldataload_with_offset_conversion_error() { let calldata = u256_to_bytes_array( 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ); - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_calldata(calldata.span()) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_calldata(calldata.span()).build(); let offset: u256 = 5000000000; - machine.stack.push(offset).expect('push failed'); + vm.stack.push(offset).expect('push failed'); // When - let result = machine.exec_calldataload(); + let result = vm.exec_calldataload(); // Then assert(result.is_err(), 'should return error'); @@ -306,16 +278,16 @@ fn test_calldataload_with_offset_conversion_error() { #[test] fn test_calldata_size() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - let calldata: Span = machine.calldata(); + let calldata: Span = vm.message.data; // When - machine.exec_calldatasize().expect('exec_calldatasize failed'); + vm.exec_calldatasize().expect('exec_calldatasize failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == calldata.len().into(), 'stack top is not calldatasize'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == calldata.len().into(), 'stack top is not calldatasize'); } // ************************************************************************* @@ -325,23 +297,23 @@ fn test_calldata_size() { #[test] fn test_calldatacopy_type_conversion_error() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine + vm .stack .push(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) .expect('push failed'); - machine + vm .stack .push(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) .expect('push failed'); - machine + vm .stack .push(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) .expect('push failed'); // When - let res = machine.exec_calldatacopy(); + let res = vm.exec_calldatacopy(); // Then assert(res.is_err(), 'should return error'); @@ -381,13 +353,13 @@ fn test_calldatacopy_with_out_of_bound_bytes_multiple_words() { fn test_calldatacopy(dest_offset: u32, offset: u32, mut size: u32, expected: Span) { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - let _calldata: Span = machine.calldata(); + let _calldata: Span = vm.message.data; - machine.stack.push(size.into()).expect('push failed'); - machine.stack.push(offset.into()).expect('push failed'); - machine.stack.push(dest_offset.into()).expect('push failed'); + vm.stack.push(size.into()).expect('push failed'); + vm.stack.push(offset.into()).expect('push failed'); + vm.stack.push(dest_offset.into()).expect('push failed'); // Memory initialization with a value to verify that if the offset + size is out of the bound bytes, 0's have been copied. // Otherwise, the memory value would be 0, and we wouldn't be able to check it. @@ -397,14 +369,14 @@ fn test_calldatacopy(dest_offset: u32, offset: u32, mut size: u32, expected: Spa break; } - machine + vm .memory .store( 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, dest_offset + (i * 32) ); - let initial: u256 = machine.memory.load_internal(dest_offset + (i * 32)).into(); + let initial: u256 = vm.memory.load_internal(dest_offset + (i * 32)).into(); assert( initial == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, @@ -415,13 +387,13 @@ fn test_calldatacopy(dest_offset: u32, offset: u32, mut size: u32, expected: Spa }; // When - machine.exec_calldatacopy().expect('exec_calldatacopy failed'); + vm.exec_calldatacopy().expect('exec_calldatacopy failed'); // Then - assert(machine.stack.is_empty(), 'stack should be empty'); + assert(vm.stack.is_empty(), 'stack should be empty'); let mut results: Array = ArrayTrait::new(); - machine.memory.load_n_internal(size, ref results, dest_offset); + vm.memory.load_n_internal(size, ref results, dest_offset); assert(results.span() == expected, 'wrong data value'); } @@ -435,14 +407,14 @@ fn test_codesize() { // Given let bytecode: Span = array![1, 2, 3, 4, 5].span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); // When - machine.exec_codesize().expect('exec_codesize failed'); + vm.exec_codesize().expect('exec_codesize failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.pop().unwrap() == bytecode.len().into(), 'wrong codesize'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.pop().unwrap() == bytecode.len().into(), 'wrong codesize'); } // ************************************************************************* @@ -454,23 +426,23 @@ fn test_codecopy_type_conversion_error() { // Given let bytecode: Span = array![1, 2, 3, 4, 5].span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); - machine + vm .stack .push(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) .expect('push failed'); - machine + vm .stack .push(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) .expect('push failed'); - machine + vm .stack .push(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) .expect('push failed'); // When - let res = machine.exec_codecopy(); + let res = vm.exec_codecopy(); // Then assert(res.is_err(), 'should return error'); @@ -504,32 +476,32 @@ fn test_codecopy(dest_offset: u32, offset: u32, mut size: u32) { // Given let bytecode: Span = array![1, 2, 3, 4, 5].span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); if (size == 0) { size = bytecode.len() - offset; } - machine.stack.push(size.into()).expect('push failed'); - machine.stack.push(offset.into()).expect('push failed'); - machine.stack.push(dest_offset.into()).expect('push failed'); + vm.stack.push(size.into()).expect('push failed'); + vm.stack.push(offset.into()).expect('push failed'); + vm.stack.push(dest_offset.into()).expect('push failed'); - machine + vm .memory .store(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, dest_offset); - let initial: u256 = machine.memory.load_internal(dest_offset).into(); + let initial: u256 = vm.memory.load_internal(dest_offset).into(); assert( initial == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'memory has not been initialized' ); // When - machine.exec_codecopy().expect('exec_codecopy failed'); + vm.exec_codecopy().expect('exec_codecopy failed'); // Then - assert(machine.stack.is_empty(), 'stack should be empty'); + assert(vm.stack.is_empty(), 'stack should be empty'); - let result: u256 = machine.memory.load_internal(dest_offset).into(); + let result: u256 = vm.memory.load_internal(dest_offset).into(); let mut results: Array = u256_to_bytes_array(result); let mut i = 0; @@ -556,14 +528,14 @@ fn test_codecopy(dest_offset: u32, offset: u32, mut size: u32) { #[test] fn test_gasprice() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When - machine.exec_gasprice().expect('exec_gasprice failed'); + vm.exec_gasprice().expect('exec_gasprice failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == gas_price().into(), 'stack top should be gas_price'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == gas_price().into(), 'stack top should be gas_price'); } // ************************************************************************* @@ -573,17 +545,17 @@ fn test_gasprice() { fn test_exec_extcodesize_eoa() { // Given let evm_address = evm_address(); - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); let (_, kakarot_core) = setup_contracts_for_testing(); let _expected_eoa_starknet_address = kakarot_core.deploy_eoa(evm_address); - machine.stack.push(evm_address.into()).expect('push failed'); + vm.stack.push(evm_address.into()).expect('push failed'); // When - machine.exec_extcodesize().unwrap(); + vm.exec_extcodesize().unwrap(); // Then - assert(machine.stack.peek().unwrap() == 0, 'expected code size 0'); + assert(vm.stack.peek().unwrap() == 0, 'expected code size 0'); } @@ -591,20 +563,20 @@ fn test_exec_extcodesize_eoa() { fn test_exec_extcodesize_ca_empty() { // Given let evm_address = evm_address(); - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); setup_contracts_for_testing(); // The bytecode remains empty, and we expect the empty hash in return let _ca_address = deploy_contract_account(evm_address(), array![].span()); - machine.stack.push(evm_address.into()).expect('push failed'); + vm.stack.push(evm_address.into()).expect('push failed'); // When - machine.exec_extcodesize().unwrap(); + vm.exec_extcodesize().unwrap(); // Then - assert(machine.stack.peek().unwrap() == 0, 'expected code size 0'); + assert(vm.stack.peek().unwrap() == 0, 'expected code size 0'); } @@ -612,20 +584,20 @@ fn test_exec_extcodesize_ca_empty() { fn test_exec_extcodesize_ca_with_bytecode() { // Given let evm_address = evm_address(); - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); setup_contracts_for_testing(); // The bytecode stored is the bytecode of a Counter.sol smart contract deploy_contract_account(evm_address(), counter_evm_bytecode()); - machine.stack.push(evm_address.into()).expect('push failed'); + vm.stack.push(evm_address.into()).expect('push failed'); // When - machine.exec_extcodesize().unwrap(); + vm.exec_extcodesize().unwrap(); // Then assert( - machine.stack.peek() // extcodesize(Counter.sol) := 275 (source: remix) + vm.stack.peek() // extcodesize(Counter.sol) := 275 (source: remix) .unwrap() == 473, 'expected counter SC code size' ); @@ -636,7 +608,7 @@ fn test_exec_extcodesize_ca_with_bytecode() { fn test_exec_extcodecopy_ca() { // Given let evm_address = evm_address(); - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); setup_contracts_for_testing(); @@ -644,19 +616,19 @@ fn test_exec_extcodecopy_ca() { deploy_contract_account(evm_address(), counter_evm_bytecode()); // size - machine.stack.push(50).expect('push failed'); + vm.stack.push(50).expect('push failed'); // offset - machine.stack.push(200).expect('push failed'); + vm.stack.push(200).expect('push failed'); // destOffset (memory offset) - machine.stack.push(20).expect('push failed'); - machine.stack.push(evm_address.into()).unwrap(); + vm.stack.push(20).expect('push failed'); + vm.stack.push(evm_address.into()).unwrap(); // When - machine.exec_extcodecopy().unwrap(); + vm.exec_extcodecopy().unwrap(); // Then let mut bytecode_slice = array![]; - machine.memory.load_n(50, ref bytecode_slice, 20); + vm.memory.load_n(50, ref bytecode_slice, 20); assert(bytecode_slice.span() == counter_evm_bytecode().slice(200, 50), 'wrong bytecode'); } @@ -667,7 +639,7 @@ fn test_exec_extcodecopy_ca() { fn test_exec_extcodecopy_ca_offset_out_of_bounds() { // Given let evm_address = evm_address(); - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); setup_contracts_for_testing(); @@ -675,43 +647,43 @@ fn test_exec_extcodecopy_ca_offset_out_of_bounds() { deploy_contract_account(evm_address(), counter_evm_bytecode()); // size - machine.stack.push(5).expect('push failed'); + vm.stack.push(5).expect('push failed'); // offset - machine.stack.push(5000).expect('push failed'); + vm.stack.push(5000).expect('push failed'); // destOffset - machine.stack.push(20).expect('push failed'); - machine.stack.push(evm_address.into()).expect('push failed'); + vm.stack.push(20).expect('push failed'); + vm.stack.push(evm_address.into()).expect('push failed'); // When - machine.exec_extcodecopy().unwrap(); + vm.exec_extcodecopy().unwrap(); // Then let mut bytecode_slice = array![]; - machine.memory.load_n(5, ref bytecode_slice, 20); + vm.memory.load_n(5, ref bytecode_slice, 20); assert(bytecode_slice.span() == array![0, 0, 0, 0, 0].span(), 'wrong bytecode'); } fn test_exec_extcodecopy_eoa() { // Given let evm_address = evm_address(); - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); let (_, kakarot_core) = setup_contracts_for_testing(); kakarot_core.deploy_eoa(evm_address); // size - machine.stack.push(5).expect('push failed'); + vm.stack.push(5).expect('push failed'); // offset - machine.stack.push(5000).expect('push failed'); + vm.stack.push(5000).expect('push failed'); // destOffset - machine.stack.push(20).expect('push failed'); - machine.stack.push(evm_address.into()).expect('push failed'); + vm.stack.push(20).expect('push failed'); + vm.stack.push(evm_address.into()).expect('push failed'); // When - machine.exec_extcodecopy().unwrap(); + vm.exec_extcodecopy().unwrap(); // Then let mut bytecode_slice = array![]; - machine.memory.load_n(5, ref bytecode_slice, 20); + vm.memory.load_n(5, ref bytecode_slice, 20); assert(bytecode_slice.span() == array![0, 0, 0, 0, 0].span(), 'wrong bytecode'); } @@ -719,45 +691,42 @@ fn test_exec_extcodecopy_eoa() { fn test_exec_extcodecopy_account_none() { // Given let evm_address = evm_address(); - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); setup_contracts_for_testing(); // size - machine.stack.push(5).expect('push failed'); + vm.stack.push(5).expect('push failed'); // offset - machine.stack.push(5000).expect('push failed'); + vm.stack.push(5000).expect('push failed'); // destOffset - machine.stack.push(20).expect('push failed'); - machine.stack.push(evm_address.into()).expect('push failed'); + vm.stack.push(20).expect('push failed'); + vm.stack.push(evm_address.into()).expect('push failed'); // When - machine.exec_extcodecopy().unwrap(); + vm.exec_extcodecopy().unwrap(); // Then let mut bytecode_slice = array![]; - machine.memory.load_n(5, ref bytecode_slice, 20); + vm.memory.load_n(5, ref bytecode_slice, 20); assert(bytecode_slice.span() == array![0, 0, 0, 0, 0].span(), 'wrong bytecode'); } #[test] -fn test_returndatasize() { +fn test_exec_returndatasize() { // Given let return_data: Array = array![1, 2, 3, 4, 5]; let size = return_data.len(); - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_nested_execution_context() - .build(); - - return_from_subcontext(ref machine, return_data.span()); + let mut vm = VMBuilderTrait::new_with_presets().with_return_data(return_data.span()).build(); + println!("vmdata: {:?}", vm.return_data().len()); - machine.exec_returndatasize().expect('exec_returndatasize failed'); + vm.exec_returndatasize().expect('exec_returndatasize failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.pop().unwrap() == size.into(), 'wrong returndatasize'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.pop().unwrap() == size.into(), 'wrong returndatasize'); } // ************************************************************************* @@ -767,23 +736,24 @@ fn test_returndatasize() { #[test] fn test_returndata_copy_type_conversion_error() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let return_data: Array = array![1, 2, 3, 4, 5]; + let mut vm = VMBuilderTrait::new_with_presets().with_return_data(return_data.span()).build(); - machine + vm .stack .push(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) .expect('push failed'); - machine + vm .stack .push(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) .expect('push failed'); - machine + vm .stack .push(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) .expect('push failed'); // When - let res = machine.exec_returndatacopy(); + let res = vm.exec_returndatacopy(); // Then assert( @@ -819,11 +789,7 @@ fn test_returndata_copy_with_multiple_words() { fn test_returndata_copy(dest_offset: u32, offset: u32, mut size: u32) { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_nested_execution_context() - .build(); // Set the return data of the current context - let return_data = array![ 1, 2, @@ -862,23 +828,21 @@ fn test_returndata_copy(dest_offset: u32, offset: u32, mut size: u32) { 35, 36 ]; - - return_from_subcontext(ref machine, return_data.span()); - let return_data: Span = machine.return_data(); + let mut vm = VMBuilderTrait::new_with_presets().with_return_data(return_data.span()).build(); if (size == 0) { size = return_data.len() - offset; } - machine.stack.push(size.into()).expect('push failed'); - machine.stack.push(offset.into()).expect('push failed'); - machine.stack.push(dest_offset.into()).expect('push failed'); + vm.stack.push(size.into()).expect('push failed'); + vm.stack.push(offset.into()).expect('push failed'); + vm.stack.push(dest_offset.into()).expect('push failed'); // When - let res = machine.exec_returndatacopy(); + let res = vm.exec_returndatacopy(); // Then - assert(machine.stack.is_empty(), 'stack should be empty'); + assert(vm.stack.is_empty(), 'stack should be empty'); match u32_overflowing_add(offset, size) { Result::Ok(x) => { @@ -899,7 +863,7 @@ fn test_returndata_copy(dest_offset: u32, offset: u32, mut size: u32) { } } - let _result: u256 = machine.memory.load_internal(dest_offset).into(); + let _result: u256 = vm.memory.load_internal(dest_offset).into(); let mut results: Array = ArrayTrait::new(); let mut i = 0; @@ -908,7 +872,7 @@ fn test_returndata_copy(dest_offset: u32, offset: u32, mut size: u32) { break; } - let result: u256 = machine.memory.load_internal(dest_offset + (i * 32)).into(); + let result: u256 = vm.memory.load_internal(dest_offset + (i * 32)).into(); let result_span = u256_to_bytes_array(result).span(); if ((i + 1) * 32 > size) { @@ -919,7 +883,7 @@ fn test_returndata_copy(dest_offset: u32, offset: u32, mut size: u32) { i += 1; }; - assert(results.span() == return_data.slice(offset, size), 'wrong data value'); + assert(results.span() == return_data.span().slice(offset, size), 'wrong data value'); } // ************************************************************************* @@ -929,25 +893,25 @@ fn test_returndata_copy(dest_offset: u32, offset: u32, mut size: u32) { fn test_exec_extcodehash_precompile() { // Given let evm_address = 0x05.try_into().unwrap(); - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); let (_, kakarot_core) = setup_contracts_for_testing(); kakarot_core.deploy_eoa(evm_address); - machine.stack.push(evm_address.into()).expect('push failed'); + vm.stack.push(evm_address.into()).expect('push failed'); set_contract_address(kakarot_core.contract_address); // When - machine.exec_extcodehash().unwrap(); + vm.exec_extcodehash().unwrap(); // Then - assert(machine.stack.peek().unwrap() == 0, 'expected 0'); + assert(vm.stack.peek().unwrap() == 0, 'expected 0'); } #[test] fn test_exec_extcodehash_selfdestructed() { // Given let evm_address = evm_address(); - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); setup_contracts_for_testing(); @@ -963,14 +927,14 @@ fn test_exec_extcodehash_selfdestructed() { }; account.selfdestruct().expect('CA selfdestruct failed'); - machine.stack.push(evm_address.into()).expect('push failed'); + vm.stack.push(evm_address.into()).expect('push failed'); // When - machine.exec_extcodehash().unwrap(); + vm.exec_extcodehash().unwrap(); // Then assert( - machine + vm .stack .peek() .unwrap() == 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470, @@ -982,18 +946,18 @@ fn test_exec_extcodehash_selfdestructed() { fn test_exec_extcodehash_eoa() { // Given let evm_address = evm_address(); - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); let (_, kakarot_core) = setup_contracts_for_testing(); kakarot_core.deploy_eoa(evm_address); - machine.stack.push(evm_address.into()).expect('push failed'); + vm.stack.push(evm_address.into()).expect('push failed'); // When - machine.exec_extcodehash().unwrap(); + vm.exec_extcodehash().unwrap(); // Then assert( - machine + vm .stack .peek() .unwrap() == 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470, @@ -1006,20 +970,20 @@ fn test_exec_extcodehash_eoa() { fn test_exec_extcodehash_ca_empty() { // Given let evm_address = evm_address(); - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); setup_contracts_for_testing(); // The bytecode remains empty, and we expect the empty hash in return deploy_contract_account(evm_address(), array![].span()); - machine.stack.push(evm_address.into()).expect('push failed'); + vm.stack.push(evm_address.into()).expect('push failed'); // When - machine.exec_extcodehash().unwrap(); + vm.exec_extcodehash().unwrap(); // Then assert( - machine + vm .stack .peek() .unwrap() == 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470, @@ -1031,37 +995,37 @@ fn test_exec_extcodehash_ca_empty() { fn test_exec_extcodehash_unknown_account() { // Given let evm_address = evm_address(); - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); setup_contracts_for_testing(); - machine.stack.push(evm_address.into()).expect('push failed'); + vm.stack.push(evm_address.into()).expect('push failed'); // When - machine.exec_extcodehash().unwrap(); + vm.exec_extcodehash().unwrap(); // Then - assert(machine.stack.peek().unwrap() == 0, 'expected stack top to be 0'); + assert(vm.stack.peek().unwrap() == 0, 'expected stack top to be 0'); } #[test] fn test_exec_extcodehash_ca_with_bytecode() { // Given let evm_address = evm_address(); - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); setup_contracts_for_testing(); // The bytecode stored is the bytecode of a Counter.sol smart contract deploy_contract_account(evm_address(), counter_evm_bytecode()); - machine.stack.push(evm_address.into()).expect('push failed'); + vm.stack.push(evm_address.into()).expect('push failed'); // When - machine.exec_extcodehash().unwrap(); + vm.exec_extcodehash().unwrap(); // Then assert( - machine + vm .stack .peek() // extcodehash(Counter.sol) := 0x82abf19c13d2262cc530f54956af7e4ec1f45f637238ed35ed7400a3409fd275 (source: remix) @@ -1074,7 +1038,7 @@ fn test_exec_extcodehash_ca_with_bytecode() { #[test] fn test_exec_extcodehash_precompiles() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); setup_contracts_for_testing(); let mut i = 0; @@ -1082,12 +1046,12 @@ fn test_exec_extcodehash_precompiles() { if i == 0x10 { break; } - machine.stack.push(i.into()).expect('push failed'); + vm.stack.push(i.into()).expect('push failed'); // When - machine.exec_extcodehash().unwrap(); + vm.exec_extcodehash().unwrap(); // Then - assert(machine.stack.pop().unwrap() == 0, 'expected 0 for precompiles'); + assert(vm.stack.pop().unwrap() == 0, 'expected 0 for precompiles'); i += 1; }; } diff --git a/crates/evm/src/tests/test_instructions/test_exchange_operations.cairo b/crates/evm/src/tests/test_instructions/test_exchange_operations.cairo index 4d86b4a25..6530a7daa 100644 --- a/crates/evm/src/tests/test_instructions/test_exchange_operations.cairo +++ b/crates/evm/src/tests/test_instructions/test_exchange_operations.cairo @@ -1,308 +1,306 @@ use array::ArrayTrait; -use evm::context::ExecutionContextTrait; use evm::instructions::exchange_operations::ExchangeOperationsTrait; -use evm::machine::Machine; use evm::stack::StackTrait; -use evm::tests::test_utils::MachineBuilderTestTrait; +use evm::tests::test_utils::VMBuilderTrait; #[test] fn test_exec_swap1() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // given - machine.stack.push(0xf).expect('push failed'); - machine.stack.push(1).expect('push failed'); - machine.exec_swap1().expect('exec_swap1 failed'); + vm.stack.push(0xf).expect('push failed'); + vm.stack.push(1).expect('push failed'); + vm.exec_swap1().expect('exec_swap1 failed'); - assert(machine.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); - assert(machine.stack.peek_at(1).unwrap() == 1, 'val at index 1 should be now 1'); + assert(vm.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); + assert(vm.stack.peek_at(1).unwrap() == 1, 'val at index 1 should be now 1'); } #[test] fn test_exec_swap2() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // given - machine.stack.push(0xf).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(1).expect('push failed'); - machine.exec_swap2().expect('exec_swap2 failed'); - assert(machine.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); - assert(machine.stack.peek_at(2).unwrap() == 1, 'val at index 2 should be now 1'); + vm.stack.push(0xf).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(1).expect('push failed'); + vm.exec_swap2().expect('exec_swap2 failed'); + assert(vm.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); + assert(vm.stack.peek_at(2).unwrap() == 1, 'val at index 2 should be now 1'); } #[test] fn test_exec_swap3() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // given - machine.stack.push(0xf).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(1).expect('push failed'); - machine.exec_swap3().expect('exec_swap3 failed'); - assert(machine.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); - assert(machine.stack.peek_at(3).unwrap() == 1, 'val at index 3 should be now 1'); + vm.stack.push(0xf).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(1).expect('push failed'); + vm.exec_swap3().expect('exec_swap3 failed'); + assert(vm.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); + assert(vm.stack.peek_at(3).unwrap() == 1, 'val at index 3 should be now 1'); } #[test] fn test_exec_swap4() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // given - machine.stack.push(0xf).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(1).expect('push failed'); - machine.exec_swap4().expect('exec_swap4 failed'); - assert(machine.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); - assert(machine.stack.peek_at(4).unwrap() == 1, 'val at index 4 should be now 1'); + vm.stack.push(0xf).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(1).expect('push failed'); + vm.exec_swap4().expect('exec_swap4 failed'); + assert(vm.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); + assert(vm.stack.peek_at(4).unwrap() == 1, 'val at index 4 should be now 1'); } #[test] fn test_exec_swap5() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // given - machine.stack.push(0xf).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(1).expect('push failed'); - machine.exec_swap5().expect('exec_swap5 failed'); - assert(machine.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); - assert(machine.stack.peek_at(5).unwrap() == 1, 'val at index 5 should be now 1'); + vm.stack.push(0xf).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(1).expect('push failed'); + vm.exec_swap5().expect('exec_swap5 failed'); + assert(vm.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); + assert(vm.stack.peek_at(5).unwrap() == 1, 'val at index 5 should be now 1'); } #[test] fn test_exec_swap6() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // given - machine.stack.push(0xf).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(1).expect('push failed'); - machine.exec_swap6().expect('exec_swap6 failed'); - assert(machine.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); - assert(machine.stack.peek_at(6).unwrap() == 1, 'val at index 6 should be now 1'); + vm.stack.push(0xf).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(1).expect('push failed'); + vm.exec_swap6().expect('exec_swap6 failed'); + assert(vm.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); + assert(vm.stack.peek_at(6).unwrap() == 1, 'val at index 6 should be now 1'); } #[test] fn test_exec_swap7() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // given - machine.stack.push(0xf).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(1).expect('push failed'); - machine.exec_swap7().expect('exec_swap7 failed'); - assert(machine.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); - assert(machine.stack.peek_at(7).unwrap() == 1, 'val at index 7 should be now 1'); + vm.stack.push(0xf).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(1).expect('push failed'); + vm.exec_swap7().expect('exec_swap7 failed'); + assert(vm.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); + assert(vm.stack.peek_at(7).unwrap() == 1, 'val at index 7 should be now 1'); } #[test] fn test_exec_swap8() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // given - machine.stack.push(0xf).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(1).expect('push failed'); - machine.exec_swap8().expect('exec_swap8 failed'); - assert(machine.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); - assert(machine.stack.peek_at(8).unwrap() == 1, 'val at index 8 should be now 1'); + vm.stack.push(0xf).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(1).expect('push failed'); + vm.exec_swap8().expect('exec_swap8 failed'); + assert(vm.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); + assert(vm.stack.peek_at(8).unwrap() == 1, 'val at index 8 should be now 1'); } #[test] fn test_exec_swap9() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // given - machine.stack.push(0xf).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(1).expect('push failed'); - machine.exec_swap9().expect('exec_swap9 failed'); - assert(machine.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); - assert(machine.stack.peek_at(9).unwrap() == 1, 'val at index 9 should be now 1'); + vm.stack.push(0xf).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(1).expect('push failed'); + vm.exec_swap9().expect('exec_swap9 failed'); + assert(vm.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); + assert(vm.stack.peek_at(9).unwrap() == 1, 'val at index 9 should be now 1'); } #[test] fn test_exec_swap10() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // given - machine.stack.push(0xf).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(1).expect('push failed'); - machine.exec_swap10().expect('exec_swap10 failed'); - assert(machine.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); - assert(machine.stack.peek_at(10).unwrap() == 1, 'val at index 10 should be now 1'); + vm.stack.push(0xf).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(1).expect('push failed'); + vm.exec_swap10().expect('exec_swap10 failed'); + assert(vm.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); + assert(vm.stack.peek_at(10).unwrap() == 1, 'val at index 10 should be now 1'); } #[test] fn test_exec_swap11() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // given - machine.stack.push(0xf).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(1).expect('push failed'); - machine.exec_swap11().expect('exec_swap11 failed'); - assert(machine.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); - assert(machine.stack.peek_at(11).unwrap() == 1, 'val at index 11 should be now 1'); + vm.stack.push(0xf).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(1).expect('push failed'); + vm.exec_swap11().expect('exec_swap11 failed'); + assert(vm.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); + assert(vm.stack.peek_at(11).unwrap() == 1, 'val at index 11 should be now 1'); } #[test] fn test_exec_swap12() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // given - machine.stack.push(0xf).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(1).expect('push failed'); - machine.exec_swap12().expect('exec_swap12 failed'); - assert(machine.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); - assert(machine.stack.peek_at(12).unwrap() == 1, 'val at index 12 should be now 1'); + vm.stack.push(0xf).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(1).expect('push failed'); + vm.exec_swap12().expect('exec_swap12 failed'); + assert(vm.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); + assert(vm.stack.peek_at(12).unwrap() == 1, 'val at index 12 should be now 1'); } #[test] fn test_exec_swap13() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // given - machine.stack.push(0xf).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(1).expect('push failed'); - machine.exec_swap13().expect('exec_swap13 failed'); - assert(machine.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); - assert(machine.stack.peek_at(13).unwrap() == 1, 'val at index 13 should be now 1'); + vm.stack.push(0xf).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(1).expect('push failed'); + vm.exec_swap13().expect('exec_swap13 failed'); + assert(vm.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); + assert(vm.stack.peek_at(13).unwrap() == 1, 'val at index 13 should be now 1'); } #[test] fn test_exec_swap14() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // given - machine.stack.push(0xf).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(1).expect('push failed'); - machine.exec_swap14().expect('exec_swap14 failed'); - assert(machine.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); - assert(machine.stack.peek_at(14).unwrap() == 1, 'val at index 14 should be now 1'); + vm.stack.push(0xf).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(1).expect('push failed'); + vm.exec_swap14().expect('exec_swap14 failed'); + assert(vm.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); + assert(vm.stack.peek_at(14).unwrap() == 1, 'val at index 14 should be now 1'); } #[test] fn test_exec_swap15() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // given - machine.stack.push(0xf).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(1).expect('push failed'); - machine.exec_swap15().expect('exec_swap15 failed'); - assert(machine.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); - assert(machine.stack.peek_at(15).unwrap() == 1, 'val at index 15 should be now 1'); + vm.stack.push(0xf).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(1).expect('push failed'); + vm.exec_swap15().expect('exec_swap15 failed'); + assert(vm.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); + assert(vm.stack.peek_at(15).unwrap() == 1, 'val at index 15 should be now 1'); } #[test] fn test_exec_swap16() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // given - machine.stack.push(0xf).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.stack.push(1).expect('push failed'); - machine.exec_swap16().expect('exec_swap16 failed'); - assert(machine.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); - assert(machine.stack.peek_at(16).unwrap() == 1, 'val at index 16 should be now 1'); + vm.stack.push(0xf).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(1).expect('push failed'); + vm.exec_swap16().expect('exec_swap16 failed'); + assert(vm.stack.peek().unwrap() == 0xf, 'Top should be now 0xf'); + assert(vm.stack.peek_at(16).unwrap() == 1, 'val at index 16 should be now 1'); } diff --git a/crates/evm/src/tests/test_instructions/test_logging_operations.cairo b/crates/evm/src/tests/test_instructions/test_logging_operations.cairo index 31d115bbb..5270ddf3b 100644 --- a/crates/evm/src/tests/test_instructions/test_logging_operations.cairo +++ b/crates/evm/src/tests/test_instructions/test_logging_operations.cairo @@ -1,31 +1,30 @@ use evm::errors::{EVMError, WRITE_IN_STATIC_CONTEXT, TYPE_CONVERSION_ERROR}; use evm::instructions::LoggingOperationsTrait; -use evm::machine::{Machine, MachineTrait}; use evm::memory::MemoryTrait; use evm::stack::StackTrait; use evm::state::StateTrait; -use evm::tests::test_utils::{MachineBuilderTestTrait}; +use evm::tests::test_utils::{VMBuilderTrait}; use integer::BoundedInt; use utils::helpers::u256_to_bytes_array; #[test] fn test_exec_log0() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.memory.store(BoundedInt::::max(), 0); + vm.memory.store(BoundedInt::::max(), 0); - machine.stack.push(0x1F).expect('push failed'); - machine.stack.push(0x00).expect('push failed'); + vm.stack.push(0x1F).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); // When - let result = machine.exec_log0(); + let result = vm.exec_log0(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.stack.len() == 0, 'stack should be empty'); + assert(vm.stack.len() == 0, 'stack should be empty'); - let mut events = machine.state.events.contextual_logs; + let mut events = vm.env.state.events; assert(events.len() == 1, 'context should have one event'); let event = events.pop_front().unwrap(); @@ -39,22 +38,22 @@ fn test_exec_log0() { #[test] fn test_exec_log1() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.memory.store(BoundedInt::::max(), 0); + vm.memory.store(BoundedInt::::max(), 0); - machine.stack.push(0x0123456789ABCDEF).expect('push failed'); - machine.stack.push(0x20).expect('push failed'); - machine.stack.push(0x00).expect('push failed'); + vm.stack.push(0x0123456789ABCDEF).expect('push failed'); + vm.stack.push(0x20).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); // When - let result = machine.exec_log1(); + let result = vm.exec_log1(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.stack.len() == 0, 'stack should be empty'); + assert(vm.stack.len() == 0, 'stack should be empty'); - let mut events = machine.state.events.contextual_logs; + let mut events = vm.env.state.events; assert(events.len() == 1, 'context should have one event'); let event = events.pop_front().unwrap(); @@ -69,23 +68,23 @@ fn test_exec_log1() { #[test] fn test_exec_log2() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.memory.store(BoundedInt::::max(), 0); + vm.memory.store(BoundedInt::::max(), 0); - machine.stack.push(BoundedInt::::max()).expect('push failed'); - machine.stack.push(0x0123456789ABCDEF).expect('push failed'); - machine.stack.push(0x05).expect('push failed'); - machine.stack.push(0x05).expect('push failed'); + vm.stack.push(BoundedInt::::max()).expect('push failed'); + vm.stack.push(0x0123456789ABCDEF).expect('push failed'); + vm.stack.push(0x05).expect('push failed'); + vm.stack.push(0x05).expect('push failed'); // When - let result = machine.exec_log2(); + let result = vm.exec_log2(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.stack.len() == 0, 'stack should be empty'); + assert(vm.stack.len() == 0, 'stack should be empty'); - let mut events = machine.state.events.contextual_logs; + let mut events = vm.env.state.events; assert(events.len() == 1, 'context should have one event'); let event = events.pop_front().unwrap(); @@ -101,25 +100,25 @@ fn test_exec_log2() { #[test] fn test_exec_log3() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.memory.store(BoundedInt::::max(), 0); - machine.memory.store(0x0123456789ABCDEF000000000000000000000000000000000000000000000000, 0x20); + vm.memory.store(BoundedInt::::max(), 0); + vm.memory.store(0x0123456789ABCDEF000000000000000000000000000000000000000000000000, 0x20); - machine.stack.push(0x00).expect('push failed'); - machine.stack.push(BoundedInt::::max()).expect('push failed'); - machine.stack.push(0x0123456789ABCDEF).expect('push failed'); - machine.stack.push(0x28).expect('push failed'); - machine.stack.push(0x00).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); + vm.stack.push(BoundedInt::::max()).expect('push failed'); + vm.stack.push(0x0123456789ABCDEF).expect('push failed'); + vm.stack.push(0x28).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); // When - let result = machine.exec_log3(); + let result = vm.exec_log3(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.stack.len() == 0, 'stack should be empty'); + assert(vm.stack.len() == 0, 'stack should be empty'); - let mut events = machine.state.events.contextual_logs; + let mut events = vm.env.state.events; assert(events.len() == 1, 'context should have one event'); let event = events.pop_front().unwrap(); @@ -138,26 +137,26 @@ fn test_exec_log3() { #[test] fn test_exec_log4() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.memory.store(BoundedInt::::max(), 0); - machine.memory.store(0x0123456789ABCDEF000000000000000000000000000000000000000000000000, 0x20); + vm.memory.store(BoundedInt::::max(), 0); + vm.memory.store(0x0123456789ABCDEF000000000000000000000000000000000000000000000000, 0x20); - machine.stack.push(BoundedInt::::max()).expect('push failed'); - machine.stack.push(0x00).expect('push failed'); - machine.stack.push(BoundedInt::::max()).expect('push failed'); - machine.stack.push(0x0123456789ABCDEF).expect('push failed'); - machine.stack.push(0x0A).expect('push failed'); - machine.stack.push(0x20).expect('push failed'); + vm.stack.push(BoundedInt::::max()).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); + vm.stack.push(BoundedInt::::max()).expect('push failed'); + vm.stack.push(0x0123456789ABCDEF).expect('push failed'); + vm.stack.push(0x0A).expect('push failed'); + vm.stack.push(0x20).expect('push failed'); // When - let result = machine.exec_log4(); + let result = vm.exec_log4(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.stack.len() == 0, 'stack should be empty'); + assert(vm.stack.len() == 0, 'stack should be empty'); - let mut events = machine.state.events.contextual_logs; + let mut events = vm.env.state.events; assert(events.len() == 1, 'context should have one event'); let event = events.pop_front().unwrap(); @@ -175,16 +174,16 @@ fn test_exec_log4() { #[test] fn test_exec_log1_read_only_context() { // Given - let mut machine = MachineBuilderTestTrait::new().with_read_only().build(); + let mut vm = VMBuilderTrait::new().with_read_only().build(); - machine.memory.store(BoundedInt::::max(), 0); + vm.memory.store(BoundedInt::::max(), 0); - machine.stack.push(0x0123456789ABCDEF).expect('push failed'); - machine.stack.push(0x20).expect('push failed'); - machine.stack.push(0x00).expect('push failed'); + vm.stack.push(0x0123456789ABCDEF).expect('push failed'); + vm.stack.push(0x20).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); // When - let result = machine.exec_log1(); + let result = vm.exec_log1(); // Then assert(result.is_err(), 'should have returned an error'); @@ -197,22 +196,22 @@ fn test_exec_log1_read_only_context() { #[test] fn test_exec_log1_size_0_offset_0() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.memory.store(BoundedInt::::max(), 0); + vm.memory.store(BoundedInt::::max(), 0); - machine.stack.push(0x0123456789ABCDEF).expect('push failed'); - machine.stack.push(0x00).expect('push failed'); - machine.stack.push(0x00).expect('push failed'); + vm.stack.push(0x0123456789ABCDEF).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); // When - let result = machine.exec_log1(); + let result = vm.exec_log1(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.stack.len() == 0, 'stack should be empty'); + assert(vm.stack.len() == 0, 'stack should be empty'); - let mut events = machine.state.events.contextual_logs; + let mut events = vm.env.state.events; assert(events.len() == 1, 'context should have one event'); let event = events.pop_front().unwrap(); @@ -225,16 +224,16 @@ fn test_exec_log1_size_0_offset_0() { #[test] fn test_exec_log1_size_too_big() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.memory.store(BoundedInt::::max(), 0); + vm.memory.store(BoundedInt::::max(), 0); - machine.stack.push(0x0123456789ABCDEF).expect('push failed'); - machine.stack.push(BoundedInt::::max()).expect('push failed'); - machine.stack.push(0x00).expect('push failed'); + vm.stack.push(0x0123456789ABCDEF).expect('push failed'); + vm.stack.push(BoundedInt::::max()).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); // When - let result = machine.exec_log1(); + let result = vm.exec_log1(); // Then assert(result.is_err(), 'should return an error'); @@ -247,16 +246,16 @@ fn test_exec_log1_size_too_big() { #[test] fn test_exec_log1_offset_too_big() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.memory.store(BoundedInt::::max(), 0); + vm.memory.store(BoundedInt::::max(), 0); - machine.stack.push(0x0123456789ABCDEF).expect('push failed'); - machine.stack.push(0x20).expect('push failed'); - machine.stack.push(BoundedInt::::max()).expect('push failed'); + vm.stack.push(0x0123456789ABCDEF).expect('push failed'); + vm.stack.push(0x20).expect('push failed'); + vm.stack.push(BoundedInt::::max()).expect('push failed'); // When - let result = machine.exec_log1(); + let result = vm.exec_log1(); // Then assert(result.is_err(), 'should return an error'); @@ -269,32 +268,32 @@ fn test_exec_log1_offset_too_big() { #[test] fn test_exec_log_multiple_events() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - - machine.memory.store(BoundedInt::::max(), 0); - machine.memory.store(0x0123456789ABCDEF000000000000000000000000000000000000000000000000, 0x20); - - machine.stack.push(BoundedInt::::max()).expect('push failed'); - machine.stack.push(0x00).expect('push failed'); - machine.stack.push(BoundedInt::::max()).expect('push failed'); - machine.stack.push(0x0123456789ABCDEF).expect('push failed'); - machine.stack.push(0x0A).expect('push failed'); - machine.stack.push(0x20).expect('push failed'); - machine.stack.push(0x00).expect('push failed'); - machine.stack.push(BoundedInt::::max()).expect('push failed'); - machine.stack.push(0x0123456789ABCDEF).expect('push failed'); - machine.stack.push(0x28).expect('push failed'); - machine.stack.push(0x00).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + + vm.memory.store(BoundedInt::::max(), 0); + vm.memory.store(0x0123456789ABCDEF000000000000000000000000000000000000000000000000, 0x20); + + vm.stack.push(BoundedInt::::max()).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); + vm.stack.push(BoundedInt::::max()).expect('push failed'); + vm.stack.push(0x0123456789ABCDEF).expect('push failed'); + vm.stack.push(0x0A).expect('push failed'); + vm.stack.push(0x20).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); + vm.stack.push(BoundedInt::::max()).expect('push failed'); + vm.stack.push(0x0123456789ABCDEF).expect('push failed'); + vm.stack.push(0x28).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); // When - let result = machine.exec_log3(); - let result = machine.exec_log4(); + let result = vm.exec_log3(); + let result = vm.exec_log4(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.stack.len() == 0, 'stack size should be 0'); + assert(vm.stack.len() == 0, 'stack size should be 0'); - let mut events = machine.state.events.contextual_logs; + let mut events = vm.env.state.events; assert(events.len() == 2, 'context should have 2 events'); let event1 = events.pop_front().unwrap(); diff --git a/crates/evm/src/tests/test_instructions/test_memory_operations.cairo b/crates/evm/src/tests/test_instructions/test_memory_operations.cairo index 243a52cc4..9978667c6 100644 --- a/crates/evm/src/tests/test_instructions/test_memory_operations.cairo +++ b/crates/evm/src/tests/test_instructions/test_memory_operations.cairo @@ -2,42 +2,42 @@ use contracts::tests::test_utils::{setup_contracts_for_testing, deploy_contract_ use core::result::ResultTrait; use evm::errors::{EVMError, STACK_UNDERFLOW, INVALID_DESTINATION, WRITE_IN_STATIC_CONTEXT}; use evm::instructions::{MemoryOperationTrait, EnvironmentInformationTrait}; -use evm::machine::{Machine, MachineTrait}; use evm::memory::{InternalMemoryTrait, MemoryTrait}; use evm::model::contract_account::{ContractAccountTrait}; +use evm::model::vm::{VM, VMTrait}; use evm::model::{Account, AccountType}; use evm::stack::StackTrait; use evm::state::{StateTrait, StateInternalTrait, compute_storage_address}; -use evm::tests::test_utils::{evm_address, MachineBuilderTestTrait}; +use evm::tests::test_utils::{evm_address, VMBuilderTrait}; use integer::BoundedInt; use starknet::get_contract_address; #[test] fn test_pc_basic() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When - machine.exec_pc().expect('exec_pc failed'); + vm.exec_pc().expect('exec_pc failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.pop().unwrap() == 0, 'PC should be 0'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.pop().unwrap() == 0, 'PC should be 0'); } #[test] fn test_pc_gets_updated_properly_1() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When - machine.set_pc(9000); - machine.exec_pc().expect('exec_pc failed'); + vm.set_pc(9000); + vm.exec_pc().expect('exec_pc failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.pop().unwrap() == 9000, 'updating PC failed'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.pop().unwrap() == 9000, 'updating PC failed'); } // 0x51 - MLOAD @@ -59,44 +59,44 @@ fn test_exec_mload_should_load_a_value_from_memory_with_offset_larger_than_msize fn assert_mload(value: u256, offset: u256, expected_value: u256, expected_memory_size: u32) { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.memory.store(value, 0); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.memory.store(value, 0); - machine.stack.push(offset).expect('push failed'); + vm.stack.push(offset).expect('push failed'); // When - machine.exec_mload().expect('exec_mload failed'); + vm.exec_mload().expect('exec_mload failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.pop().unwrap() == expected_value, 'mload failed'); - assert(machine.memory.size() == expected_memory_size, 'memory size error'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.pop().unwrap() == expected_value, 'mload failed'); + assert(vm.memory.size() == expected_memory_size, 'memory size error'); } #[test] fn test_exec_pop_should_pop_an_item_from_stack() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(0x01).expect('push failed'); - machine.stack.push(0x02).expect('push failed'); + vm.stack.push(0x01).expect('push failed'); + vm.stack.push(0x02).expect('push failed'); // When - let result = machine.exec_pop(); + let result = vm.exec_pop(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0x01, 'stack peek should return 0x01'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0x01, 'stack peek should return 0x01'); } #[test] fn test_exec_pop_should_stack_underflow() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When - let result = machine.exec_pop(); + let result = vm.exec_pop(); // Then assert(result.is_err(), 'should return Err '); @@ -108,111 +108,111 @@ fn test_exec_pop_should_stack_underflow() { #[test] fn test_exec_mstore_should_store_max_uint256_offset_0() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(BoundedInt::::max()).expect('push failed'); - machine.stack.push(0x00).expect('push failed'); + vm.stack.push(BoundedInt::::max()).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); // When - let result = machine.exec_mstore(); + let result = vm.exec_mstore(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.memory.size() == 32, 'memory should be 32 bytes long'); - let stored = machine.memory.load(0); + assert(vm.memory.size() == 32, 'memory should be 32 bytes long'); + let stored = vm.memory.load(0); assert(stored == BoundedInt::::max(), 'should have stored max_uint256'); } #[test] fn test_exec_mstore_should_store_max_uint256_offset_1() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(BoundedInt::::max()).expect('push failed'); - machine.stack.push(0x01).expect('push failed'); + vm.stack.push(BoundedInt::::max()).expect('push failed'); + vm.stack.push(0x01).expect('push failed'); // When - let result = machine.exec_mstore(); + let result = vm.exec_mstore(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.memory.size() == 64, 'memory should be 64 bytes long'); - let stored = machine.memory.load(1); + assert(vm.memory.size() == 64, 'memory should be 64 bytes long'); + let stored = vm.memory.load(1); assert(stored == BoundedInt::::max(), 'should have stored max_uint256'); } #[test] fn test_exec_mstore8_should_store_uint8_offset_31() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(0xAB).expect('push failed'); - machine.stack.push(31).expect('push failed'); + vm.stack.push(0xAB).expect('push failed'); + vm.stack.push(31).expect('push failed'); // When - let result = machine.exec_mstore8(); + let result = vm.exec_mstore8(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.memory.size() == 32, 'memory should be 32 bytes long'); - let stored = machine.memory.load(0); + assert(vm.memory.size() == 32, 'memory should be 32 bytes long'); + let stored = vm.memory.load(0); assert(stored == 0xAB, 'mstore8 failed'); } #[test] fn test_exec_mstore8_should_store_uint8_offset_30() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(0xAB).expect('push failed'); - machine.stack.push(30).expect('push failed'); + vm.stack.push(0xAB).expect('push failed'); + vm.stack.push(30).expect('push failed'); // When - let result = machine.exec_mstore8(); + let result = vm.exec_mstore8(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.memory.size() == 32, 'memory should be 32 bytes long'); - let stored = machine.memory.load(0); + assert(vm.memory.size() == 32, 'memory should be 32 bytes long'); + let stored = vm.memory.load(0); assert(stored == 0xAB00, 'mstore8 failed'); } #[test] fn test_exec_mstore8_should_store_uint8_offset_31_then_uint8_offset_30() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(0xAB).expect('push failed'); - machine.stack.push(30).expect('push failed'); - machine.stack.push(0xCD).expect('push failed'); - machine.stack.push(31).expect('push failed'); + vm.stack.push(0xAB).expect('push failed'); + vm.stack.push(30).expect('push failed'); + vm.stack.push(0xCD).expect('push failed'); + vm.stack.push(31).expect('push failed'); // When - let result1 = machine.exec_mstore8(); - let result2 = machine.exec_mstore8(); + let result1 = vm.exec_mstore8(); + let result2 = vm.exec_mstore8(); // Then assert(result1.is_ok() && result2.is_ok(), 'should have succeeded'); - assert(machine.memory.size() == 32, 'memory should be 32 bytes long'); - let stored = machine.memory.load(0); + assert(vm.memory.size() == 32, 'memory should be 32 bytes long'); + let stored = vm.memory.load(0); assert(stored == 0xABCD, 'mstore8 failed'); } #[test] fn test_exec_mstore8_should_store_last_uint8_offset_31() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(0x123456789ABCDEF).expect('push failed'); - machine.stack.push(31).expect('push failed'); + vm.stack.push(0x123456789ABCDEF).expect('push failed'); + vm.stack.push(31).expect('push failed'); // When - let result = machine.exec_mstore8(); + let result = vm.exec_mstore8(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.memory.size() == 32, 'memory should be 32 bytes long'); - let stored = machine.memory.load(0); + assert(vm.memory.size() == 32, 'memory should be 32 bytes long'); + let stored = vm.memory.load(0); assert(stored == 0xEF, 'mstore8 failed'); } @@ -220,63 +220,63 @@ fn test_exec_mstore8_should_store_last_uint8_offset_31() { #[test] fn test_exec_mstore8_should_store_last_uint8_offset_63() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(0x123456789ABCDEF).expect('push failed'); - machine.stack.push(63).expect('push failed'); + vm.stack.push(0x123456789ABCDEF).expect('push failed'); + vm.stack.push(63).expect('push failed'); // When - let result = machine.exec_mstore8(); + let result = vm.exec_mstore8(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.memory.size() == 64, 'memory should be 64 bytes long'); - let stored = machine.memory.load(32); + assert(vm.memory.size() == 64, 'memory should be 64 bytes long'); + let stored = vm.memory.load(32); assert(stored == 0xEF, 'mstore8 failed'); } #[test] fn test_msize_initial() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When - let result = machine.exec_msize(); + let result = vm.exec_msize(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.pop().unwrap() == 0, 'initial memory size should be 0'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.pop().unwrap() == 0, 'initial memory size should be 0'); } #[test] fn test_exec_msize_store_max_offset_0() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.memory.store(BoundedInt::::max(), 0x00); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.memory.store(BoundedInt::::max(), 0x00); // When - let result = machine.exec_msize(); + let result = vm.exec_msize(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.pop().unwrap() == 32, 'should 32 bytes after MSTORE'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.pop().unwrap() == 32, 'should 32 bytes after MSTORE'); } #[test] fn test_exec_msize_store_max_offset_1() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.memory.store(BoundedInt::::max(), 0x01); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.memory.store(BoundedInt::::max(), 0x01); // When - let result = machine.exec_msize(); + let result = vm.exec_msize(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.pop().unwrap() == 64, 'should 64 bytes after MSTORE'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.pop().unwrap() == 64, 'should 64 bytes after MSTORE'); } #[test] @@ -284,16 +284,16 @@ fn test_exec_jump_valid() { // Given let bytecode: Span = array![0x01, 0x02, 0x03, 0x5B, 0x04, 0x05].span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); let counter = 0x03; - machine.stack.push(counter).expect('push failed'); + vm.stack.push(counter).expect('push failed'); // When - machine.exec_jump().expect('exec_jump failed'); + vm.exec_jump().expect('exec_jump failed'); // Then - let pc = machine.pc(); + let pc = vm.pc(); assert(pc == 0x03, 'PC should be JUMPDEST'); } @@ -303,13 +303,13 @@ fn test_exec_jump_invalid() { // Given let bytecode: Span = array![0x01, 0x02, 0x03, 0x5B, 0x04, 0x05].span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); let counter = 0x02; - machine.stack.push(counter).expect('push failed'); + vm.stack.push(counter).expect('push failed'); // When - let result = machine.exec_jump(); + let result = vm.exec_jump(); // Then assert(result.is_err(), 'invalid jump dest'); @@ -321,13 +321,13 @@ fn test_exec_jump_out_of_bounds() { // Given let bytecode: Span = array![0x01, 0x02, 0x03, 0x5B, 0x04, 0x05].span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); let counter = 0xFF; - machine.stack.push(counter).expect('push failed'); + vm.stack.push(counter).expect('push failed'); // When - let result = machine.exec_jump(); + let result = vm.exec_jump(); // Then assert(result.is_err(), 'invalid jump dest'); @@ -344,13 +344,13 @@ fn test_exec_jump_inside_pushn() { // Given let bytecode: Span = array![0x60, 0x5B, 0x60, 0x00].span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); let counter = 0x01; - machine.stack.push(counter).expect('push failed'); + vm.stack.push(counter).expect('push failed'); // When - let result = machine.exec_jump(); + let result = vm.exec_jump(); // Then assert(result.is_err(), 'exec_jump should throw error'); @@ -365,18 +365,18 @@ fn test_exec_jumpi_valid_non_zero_1() { // Given let bytecode: Span = array![0x01, 0x02, 0x03, 0x5B, 0x04, 0x05].span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); let b = 0x1; - machine.stack.push(b).expect('push failed'); + vm.stack.push(b).expect('push failed'); let counter = 0x03; - machine.stack.push(counter).expect('push failed'); + vm.stack.push(counter).expect('push failed'); // When - machine.exec_jumpi().expect('exec_jumpi failed'); + vm.exec_jumpi().expect('exec_jumpi failed'); // Then - let pc = machine.pc(); + let pc = vm.pc(); assert(pc == 0x03, 'PC should be JUMPDEST'); } @@ -385,18 +385,18 @@ fn test_exec_jumpi_valid_non_zero_2() { // Given let bytecode: Span = array![0x01, 0x02, 0x03, 0x5B, 0x04, 0x05].span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); let b = 0x69; - machine.stack.push(b).expect('push failed'); + vm.stack.push(b).expect('push failed'); let counter = 0x03; - machine.stack.push(counter).expect('push failed'); + vm.stack.push(counter).expect('push failed'); // When - machine.exec_jumpi().expect('exec_jumpi failed'); + vm.exec_jumpi().expect('exec_jumpi failed'); // Then - let pc = machine.pc(); + let pc = vm.pc(); assert(pc == 0x03, 'PC should be JUMPDEST'); } @@ -405,19 +405,19 @@ fn test_exec_jumpi_valid_zero() { // Given let bytecode: Span = array![0x01, 0x02, 0x03, 0x5B, 0x04, 0x05].span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); let b = 0x0; - machine.stack.push(b).expect('push failed'); + vm.stack.push(b).expect('push failed'); let counter = 0x03; - machine.stack.push(counter).expect('push failed'); - let old_pc = machine.pc(); + vm.stack.push(counter).expect('push failed'); + let old_pc = vm.pc(); // When - machine.exec_jumpi().expect('exec_jumpi failed'); + vm.exec_jumpi().expect('exec_jumpi failed'); // Then - let pc = machine.pc(); + let pc = vm.pc(); // ideally we should assert that it incremented, but incrementing is done by `decode_and_execute` // so we can assume that will be done assert(pc == old_pc, 'PC should be same'); @@ -428,15 +428,15 @@ fn test_exec_jumpi_invalid_non_zero() { // Given let bytecode: Span = array![0x60, 0x5B, 0x60, 0x00].span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); let b = 0x69; - machine.stack.push(b).expect('push failed'); + vm.stack.push(b).expect('push failed'); let counter = 0x69; - machine.stack.push(counter).expect('push failed'); + vm.stack.push(counter).expect('push failed'); // When - let result = machine.exec_jumpi(); + let result = vm.exec_jumpi(); // Then assert(result.is_err(), 'invalid jump dest'); @@ -449,19 +449,19 @@ fn test_exec_jumpi_invalid_zero() { // Given let bytecode: Span = array![0x01, 0x02, 0x03, 0x5B, 0x04, 0x05].span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); let b = 0x0; - machine.stack.push(b).expect('push failed'); + vm.stack.push(b).expect('push failed'); let counter = 0x69; - machine.stack.push(counter).expect('push failed'); - let old_pc = machine.pc(); + vm.stack.push(counter).expect('push failed'); + let old_pc = vm.pc(); // When - machine.exec_jumpi().expect('exec_jumpi failed'); + vm.exec_jumpi().expect('exec_jumpi failed'); // Then - let pc = machine.pc(); + let pc = vm.pc(); // ideally we should assert that it incremented, but incrementing is done by `decode_and_execute` // so we can assume that will be done assert(pc == old_pc, 'PC should be same'); @@ -477,15 +477,15 @@ fn test_exec_jumpi_inside_pushn() { // Given let bytecode: Span = array![0x60, 0x5B, 0x60, 0x00].span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); let b = 0x00; - machine.stack.push(b).expect('push failed'); + vm.stack.push(b).expect('push failed'); let counter = 0x01; - machine.stack.push(counter).expect('push failed'); + vm.stack.push(counter).expect('push failed'); // When - let result = machine.exec_jumpi(); + let result = vm.exec_jumpi(); // Then assert(result.is_err(), 'exec_jump should throw error'); @@ -498,29 +498,29 @@ fn test_exec_jumpi_inside_pushn() { #[test] fn test_exec_sload_from_state() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); let key: u256 = 0x100000000000000000000000000000001; let value = 0x02; - // `evm_address` must match the one used to instantiate the machine - machine.state.write_state(machine.address().evm, key, value); + // `evm_address` must match the one used to instantiate the vm + vm.env.state.write_state(vm.message().target.evm, key, value); - machine.stack.push(key.into()).expect('push failed'); + vm.stack.push(key.into()).expect('push failed'); // When - let result = machine.exec_sload(); + let result = vm.exec_sload(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.pop().unwrap() == value, 'sload failed'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.pop().unwrap() == value, 'sload failed'); } #[test] fn test_exec_sload_from_storage() { // Given setup_contracts_for_testing(); - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - let mut ca_address = deploy_contract_account(machine.address().evm, array![].span()); + let mut vm = VMBuilderTrait::new_with_presets().build(); + let mut ca_address = deploy_contract_account(vm.message().target.evm, array![].span()); let account = Account { account_type: AccountType::ContractAccount, address: ca_address, @@ -533,44 +533,44 @@ fn test_exec_sload_from_storage() { let value: u256 = 0xABDE1E11A5; account.store_storage(key, value).expect('store failed'); - machine.stack.push(key.into()).expect('push failed'); + vm.stack.push(key.into()).expect('push failed'); // When - let result = machine.exec_sload(); + let result = vm.exec_sload(); // Then assert(result.is_ok(), 'should have succeeded'); - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.pop().unwrap() == value, 'sload failed'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.pop().unwrap() == value, 'sload failed'); } #[test] fn test_exec_sstore_from_state() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); let key: u256 = 0x100000000000000000000000000000001; let value: u256 = 0xABDE1E11A5; - machine.stack.push(value).expect('push failed'); - machine.stack.push(key).expect('push failed'); + vm.stack.push(value).expect('push failed'); + vm.stack.push(key).expect('push failed'); // When - machine.exec_sstore().expect('exec sstore failed'); + vm.exec_sstore().expect('exec sstore failed'); // Then - assert(machine.state.read_state(evm_address(), key).unwrap() == value, 'wrong value in state') + assert(vm.env.state.read_state(evm_address(), key).unwrap() == value, 'wrong value in state') } #[test] fn test_exec_sstore_static_call() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().with_read_only().build(); + let mut vm = VMBuilderTrait::new_with_presets().with_read_only().build(); let key: u256 = 0x100000000000000000000000000000001; let value: u256 = 0xABDE1E11A5; - machine.stack.push(value).expect('push failed'); - machine.stack.push(key).expect('push failed'); + vm.stack.push(value).expect('push failed'); + vm.stack.push(key).expect('push failed'); // When - let result = machine.exec_sstore(); + let result = vm.exec_sstore(); // Then assert(result.is_err(), 'should have errored'); @@ -586,9 +586,9 @@ fn test_exec_sstore_finalized() { // Setting the contract address is required so that `get_contract_address` in // `CA::deploy` returns the kakarot address setup_contracts_for_testing(); - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // Deploys the contract account to be able to commit storage changes. - let ca_address = deploy_contract_account(machine.address().evm, array![].span()); + let ca_address = deploy_contract_account(vm.message().target.evm, array![].span()); let account = Account { account_type: AccountType::ContractAccount, address: ca_address, @@ -599,13 +599,12 @@ fn test_exec_sstore_finalized() { }; let key: u256 = 0x100000000000000000000000000000001; let value: u256 = 0xABDE1E11A5; - machine.stack.push(value).expect('push failed'); - machine.stack.push(key).expect('push failed'); + vm.stack.push(value).expect('push failed'); + vm.stack.push(key).expect('push failed'); // When - machine.exec_sstore().expect('exec_sstore failed'); - machine.state.commit_context(); - machine.state.commit_storage().expect('commit storage failed'); + vm.exec_sstore().expect('exec_sstore failed'); + vm.env.state.commit_storage().expect('commit storage failed'); // Then assert(account.fetch_storage(key).unwrap() == value, 'wrong committed value') @@ -614,12 +613,12 @@ fn test_exec_sstore_finalized() { #[test] fn test_gas_should_push_gas_used_to_stack() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When - machine.exec_gas().unwrap(); + vm.exec_gas().unwrap(); // Then - let result = machine.stack.peek().unwrap(); - assert(result == machine.gas_used().into(), 'stack top should be gas_limit'); + let result = vm.stack.peek().unwrap(); + assert(result == vm.gas_used().into(), 'stack top should be gas_limit'); } diff --git a/crates/evm/src/tests/test_instructions/test_push_operations.cairo b/crates/evm/src/tests/test_instructions/test_push_operations.cairo index 24a5c7362..81562fbb7 100644 --- a/crates/evm/src/tests/test_instructions/test_push_operations.cairo +++ b/crates/evm/src/tests/test_instructions/test_push_operations.cairo @@ -1,7 +1,6 @@ -use evm::context::ExecutionContextTrait; use evm::instructions::PushOperationsTrait; use evm::stack::StackTrait; -use evm::tests::test_utils::{MachineBuilderTestTrait}; +use evm::tests::test_utils::{VMBuilderTrait}; fn get_n_0xFF(mut n: u8) -> Span { let mut array: Array = ArrayTrait::new(); @@ -18,322 +17,270 @@ fn get_n_0xFF(mut n: u8) -> Span { #[test] fn test_push0() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(0)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(0)).build(); // When - machine.exec_push0().expect('exec_push0 failed'); + vm.exec_push0().expect('exec_push0 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0, 'invalid stack top'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0, 'invalid stack top'); } #[test] fn test_push1() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(1)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(1)).build(); // When - machine.exec_push1().expect('exec_push1 failed'); + vm.exec_push1().expect('exec_push1 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0xFF, 'invalid stack top'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xFF, 'invalid stack top'); } #[test] fn test_push2() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(2)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(2)).build(); // When - machine.exec_push2().expect('exec_push2 failed'); + vm.exec_push2().expect('exec_push2 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0xFFFF, 'invalid stack top'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xFFFF, 'invalid stack top'); } #[test] fn test_push3() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(3)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(3)).build(); // When - machine.exec_push3().expect('exec_push3 failed'); + vm.exec_push3().expect('exec_push3 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0xFFFFFF, 'invalid stack top'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xFFFFFF, 'invalid stack top'); } #[test] fn test_push4() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(4)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(4)).build(); // When - machine.exec_push4().expect('exec_push4 failed'); + vm.exec_push4().expect('exec_push4 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0xFFFFFFFF, 'invalid stack top'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xFFFFFFFF, 'invalid stack top'); } #[test] fn test_push5() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(5)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(5)).build(); // When - machine.exec_push5().expect('exec_push5 failed'); + vm.exec_push5().expect('exec_push5 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0xFFFFFFFFFF, 'invalid stack top'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xFFFFFFFFFF, 'invalid stack top'); } #[test] fn test_push6() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(6)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(6)).build(); // When - machine.exec_push6().expect('exec_push6 failed'); + vm.exec_push6().expect('exec_push6 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0xFFFFFFFFFFFF, 'invalid stack top'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xFFFFFFFFFFFF, 'invalid stack top'); } #[test] fn test_push7() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(7)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(7)).build(); // When - machine.exec_push7().expect('exec_push7 failed'); + vm.exec_push7().expect('exec_push7 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFF, 'invalid stack top'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFF, 'invalid stack top'); } #[test] fn test_push8() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(8)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(8)).build(); // When - machine.exec_push8().expect('exec_push8 failed'); + vm.exec_push8().expect('exec_push8 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFF, 'invalid stack top'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFF, 'invalid stack top'); } #[test] fn test_push9() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(9)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(9)).build(); // When - machine.exec_push9().expect('exec_push9 failed'); + vm.exec_push9().expect('exec_push9 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFF, 'invalid stack top'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFF, 'invalid stack top'); } #[test] fn test_push10() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(10)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(10)).build(); // When - machine.exec_push10().expect('exec_push10 failed'); + vm.exec_push10().expect('exec_push10 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFF, 'invalid stack top'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFF, 'invalid stack top'); } #[test] fn test_push11() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(11)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(11)).build(); // When - machine.exec_push11().expect('exec_push11 failed'); + vm.exec_push11().expect('exec_push11 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top'); } #[test] fn test_push12() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(12)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(12)).build(); // When - machine.exec_push12().expect('exec_push12 failed'); + vm.exec_push12().expect('exec_push12 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top'); } #[test] fn test_push13() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(13)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(13)).build(); // When - machine.exec_push13().expect('exec_push13 failed'); + vm.exec_push13().expect('exec_push13 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top'); } #[test] fn test_push14() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(14)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(14)).build(); // When - machine.exec_push14().expect('exec_push14 failed'); + vm.exec_push14().expect('exec_push14 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top'); } #[test] fn test_push15() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(15)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(15)).build(); // When - machine.exec_push15().expect('exec_push15 failed'); + vm.exec_push15().expect('exec_push15 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top'); } #[test] fn test_push16() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(16)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(16)).build(); // When - machine.exec_push16().expect('exec_push16 failed'); + vm.exec_push16().expect('exec_push16 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert( - machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top' - ); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top'); } #[test] fn test_push17() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(17)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(17)).build(); // When - machine.exec_push17().expect('exec_push17 failed'); + vm.exec_push17().expect('exec_push17 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert( - machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top' - ); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top'); } #[test] fn test_push18() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(18)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(18)).build(); // When - machine.exec_push18().expect('exec_push18 failed'); + vm.exec_push18().expect('exec_push18 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert( - machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top' - ); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top'); } #[test] fn test_push19() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(19)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(19)).build(); // When - machine.exec_push19().expect('exec_push19 failed'); + vm.exec_push19().expect('exec_push19 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, - 'invalid stack top' + vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top' ); } #[test] fn test_push20() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(20)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(20)).build(); // When - machine.exec_push20().expect('exec_push20 failed'); + vm.exec_push20().expect('exec_push20 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, - 'invalid stack top' + vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top' ); } #[test] fn test_push21() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(21)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(21)).build(); // When - machine.exec_push21().expect('exec_push21 failed'); + vm.exec_push21().expect('exec_push21 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, + vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top' ); } @@ -341,48 +288,42 @@ fn test_push21() { #[test] fn test_push22() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(22)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(22)).build(); // When - machine.exec_push22().expect('exec_push22 failed'); + vm.exec_push22().expect('exec_push22 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, + vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top' ); } #[test] fn test_push23() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(23)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(23)).build(); // When - machine.exec_push23().expect('exec_push23 failed'); + vm.exec_push23().expect('exec_push23 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, + vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top' ); } #[test] fn test_push24() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(24)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(24)).build(); // When - machine.exec_push24().expect('exec_push24 failed'); + vm.exec_push24().expect('exec_push24 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, + vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top' ); } @@ -390,16 +331,14 @@ fn test_push24() { #[test] fn test_push25() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(25)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(25)).build(); // When - machine.exec_push25().expect('exec_push25 failed'); + vm.exec_push25().expect('exec_push25 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, + vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top' ); } @@ -407,16 +346,14 @@ fn test_push25() { #[test] fn test_push26() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(26)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(26)).build(); // When - machine.exec_push26().expect('exec_push26 failed'); + vm.exec_push26().expect('exec_push26 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, + vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top' ); } @@ -424,16 +361,14 @@ fn test_push26() { #[test] fn test_push27() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(27)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(27)).build(); // When - machine.exec_push27().expect('exec_push27 failed'); + vm.exec_push27().expect('exec_push27 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, + vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top' ); } @@ -441,16 +376,14 @@ fn test_push27() { #[test] fn test_push28() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(28)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(28)).build(); // When - machine.exec_push28().expect('exec_push28 failed'); + vm.exec_push28().expect('exec_push28 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, + vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top' ); } @@ -458,19 +391,14 @@ fn test_push28() { #[test] fn test_push29() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(29)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(29)).build(); // When - machine.exec_push29().expect('exec_push29 failed'); + vm.exec_push29().expect('exec_push29 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine - .stack - .peek() - .unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, + vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top' ); } @@ -478,19 +406,14 @@ fn test_push29() { #[test] fn test_push30() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(30)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(30)).build(); // When - machine.exec_push30().expect('exec_push30 failed'); + vm.exec_push30().expect('exec_push30 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine - .stack - .peek() - .unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, + vm.stack.peek().unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 'invalid stack top' ); } @@ -498,16 +421,14 @@ fn test_push30() { #[test] fn test_push31() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(31)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(31)).build(); // When - machine.exec_push31().expect('exec_push31 failed'); + vm.exec_push31().expect('exec_push31 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine + vm .stack .peek() .unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, @@ -518,16 +439,14 @@ fn test_push31() { #[test] fn test_push32() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_bytecode(get_n_0xFF(32)) - .build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(get_n_0xFF(32)).build(); // When - machine.exec_push32().expect('exec_push32 failed'); + vm.exec_push32().expect('exec_push32 failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine + vm .stack .peek() .unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, diff --git a/crates/evm/src/tests/test_instructions/test_sha3.cairo b/crates/evm/src/tests/test_instructions/test_sha3.cairo index f7e8d8881..ae1bc4040 100644 --- a/crates/evm/src/tests/test_instructions/test_sha3.cairo +++ b/crates/evm/src/tests/test_instructions/test_sha3.cairo @@ -1,311 +1,308 @@ -use evm::context::{ExecutionContext, ExecutionContextTrait,}; use evm::errors::{EVMError, TYPE_CONVERSION_ERROR}; use evm::instructions::Sha3Trait; use evm::instructions::sha3::internal; use evm::memory::{InternalMemoryTrait, MemoryTrait}; use evm::stack::StackTrait; -use evm::tests::test_utils::MachineBuilderTestTrait; +use evm::tests::test_utils::VMBuilderTrait; #[test] fn test_exec_sha3_size_0_offset_0() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(0x00).expect('push failed'); - machine.stack.push(0x00).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); - machine.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); // When - machine.exec_sha3().expect('exec_sha3 failed'); + vm.exec_sha3().expect('exec_sha3 failed'); // Then - let result = machine.stack.peek().unwrap(); + let result = vm.stack.peek().unwrap(); assert( result == 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470, 'wrong result' ); - assert(machine.memory.size() == 32, 'wrong memory size'); + assert(vm.memory.size() == 32, 'wrong memory size'); } #[test] fn test_exec_sha3_size_5_offset_4() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(0x05).expect('push failed'); - machine.stack.push(0x04).expect('push failed'); + vm.stack.push(0x05).expect('push failed'); + vm.stack.push(0x04).expect('push failed'); - machine.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); // When - machine.exec_sha3().expect('exec_sha3 failed'); + vm.exec_sha3().expect('exec_sha3 failed'); // Then - let result = machine.stack.peek().unwrap(); + let result = vm.stack.peek().unwrap(); assert( result == 0xc41589e7559804ea4a2080dad19d876a024ccb05117835447d72ce08c1d020ec, 'wrong result' ); - assert(machine.memory.size() == 64, 'wrong memory size'); + assert(vm.memory.size() == 64, 'wrong memory size'); } #[test] fn test_exec_sha3_size_10_offset_10() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(10).expect('push failed'); - machine.stack.push(10).expect('push failed'); + vm.stack.push(10).expect('push failed'); + vm.stack.push(10).expect('push failed'); - machine.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); // When - machine.exec_sha3().expect('exec_sha3 failed'); + vm.exec_sha3().expect('exec_sha3 failed'); // Then - let result = machine.stack.peek().unwrap(); + let result = vm.stack.peek().unwrap(); assert( result == 0x6bd2dd6bd408cbee33429358bf24fdc64612fbf8b1b4db604518f40ffd34b607, 'wrong result' ); - assert(machine.memory.size() == 64, 'wrong memory size'); + assert(vm.memory.size() == 64, 'wrong memory size'); } #[test] fn test_exec_sha3_size_0xFFFFF_offset_1000() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(0xFFFFF).expect('push failed'); - machine.stack.push(1000).expect('push failed'); + vm.stack.push(0xFFFFF).expect('push failed'); + vm.stack.push(1000).expect('push failed'); - machine.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); // When - machine.exec_sha3().expect('exec_sha3 failed'); + vm.exec_sha3().expect('exec_sha3 failed'); // Then - let result = machine.stack.peek().unwrap(); + let result = vm.stack.peek().unwrap(); assert( result == 0xbe6f1b42b34644f918560a07f959d23e532dea5338e4b9f63db0caeb608018fa, 'wrong result' ); - assert(machine.memory.size() == (((0xFFFFF + 1000) + 31) / 32) * 32, 'wrong memory size'); + assert(vm.memory.size() == (((0xFFFFF + 1000) + 31) / 32) * 32, 'wrong memory size'); } #[test] fn test_exec_sha3_size_1000000_offset_2() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(1000000).expect('push failed'); - machine.stack.push(2).expect('push failed'); + vm.stack.push(1000000).expect('push failed'); + vm.stack.push(2).expect('push failed'); - machine.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); // When - machine.exec_sha3().expect('exec_sha3 failed'); + vm.exec_sha3().expect('exec_sha3 failed'); // Then - let result = machine.stack.peek().unwrap(); + let result = vm.stack.peek().unwrap(); assert( result == 0x4aa461ae9513f3b03ae397740ade979809dd02ae2c14e101b32842fbee21f0a, 'wrong result' ); - assert(machine.memory.size() == (((1000000 + 2) + 31) / 32) * 32, 'wrong memory size'); + assert(vm.memory.size() == (((1000000 + 2) + 31) / 32) * 32, 'wrong memory size'); } #[test] fn test_exec_sha3_size_1000000_offset_23() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(1000000).expect('push failed'); - machine.stack.push(2).expect('push failed'); + vm.stack.push(1000000).expect('push failed'); + vm.stack.push(2).expect('push failed'); - machine.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); - machine.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); // When - machine.exec_sha3().expect('exec_sha3 failed'); + vm.exec_sha3().expect('exec_sha3 failed'); // Then - let result = machine.stack.peek().unwrap(); + let result = vm.stack.peek().unwrap(); assert( result == 0x4aa461ae9513f3b03ae397740ade979809dd02ae2c14e101b32842fbee21f0a, 'wrong result' ); - assert(machine.memory.size() == (((1000000 + 23) + 31) / 32) * 32, 'wrong memory size'); + assert(vm.memory.size() == (((1000000 + 23) + 31) / 32) * 32, 'wrong memory size'); } #[test] fn test_exec_sha3_size_1_offset_2048() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(1).expect('push failed'); - machine.stack.push(2048).expect('push failed'); + vm.stack.push(1).expect('push failed'); + vm.stack.push(2048).expect('push failed'); - machine.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); // When - machine.exec_sha3().expect('exec_sha3 failed'); + vm.exec_sha3().expect('exec_sha3 failed'); // Then - let result = machine.stack.peek().unwrap(); + let result = vm.stack.peek().unwrap(); assert( result == 0xbc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a, 'wrong result' ); - assert(machine.memory.size() == (((2048 + 1) + 31) / 32) * 32, 'wrong memory size'); + assert(vm.memory.size() == (((2048 + 1) + 31) / 32) * 32, 'wrong memory size'); } #[test] fn test_exec_sha3_size_0_offset_1024() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(0).expect('push failed'); - machine.stack.push(1024).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(1024).expect('push failed'); - machine.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); // When - machine.exec_sha3().expect('exec_sha3 failed'); + vm.exec_sha3().expect('exec_sha3 failed'); // Then - let result = machine.stack.peek().unwrap(); + let result = vm.stack.peek().unwrap(); assert( result == 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470, 'wrong result' ); - assert(machine.memory.size() == 1024, 'wrong memory size'); + assert(vm.memory.size() == 1024, 'wrong memory size'); } #[test] fn test_exec_sha3_size_32_offset_2016() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(32).expect('push failed'); - machine.stack.push(2016).expect('push failed'); + vm.stack.push(32).expect('push failed'); + vm.stack.push(2016).expect('push failed'); - machine.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); + vm.memory.store(0xFFFFFFFF00000000000000000000000000000000000000000000000000000000, 0); // When - machine.exec_sha3().expect('exec_sha3 failed'); + vm.exec_sha3().expect('exec_sha3 failed'); // Then - let result = machine.stack.peek().unwrap(); + let result = vm.stack.peek().unwrap(); assert( result == 0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563, 'wrong result' ); - assert(machine.memory.size() == (((2016 + 32) + 31) / 32) * 32, 'wrong memory size'); + assert(vm.memory.size() == (((2016 + 32) + 31) / 32) * 32, 'wrong memory size'); } #[test] fn test_exec_sha3_size_32_offset_0() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(32).expect('push failed'); - machine.stack.push(0).expect('push failed'); + vm.stack.push(32).expect('push failed'); + vm.stack.push(0).expect('push failed'); - machine.memory.store(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); + vm.memory.store(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); // When - machine.exec_sha3().expect('exec_sha3 failed'); + vm.exec_sha3().expect('exec_sha3 failed'); // Then - let result = machine.stack.peek().unwrap(); + let result = vm.stack.peek().unwrap(); assert( result == 0x567d6b045256961aee949d6bb4d5f814c5b42e6b8bb49a833e8e89fbcddee86c, 'wrong result' ); - assert(machine.memory.size() == 32, 'wrong memory size'); + assert(vm.memory.size() == 32, 'wrong memory size'); } #[test] fn test_exec_sha3_size_31_offset_0() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(31).expect('push failed'); - machine.stack.push(0).expect('push failed'); + vm.stack.push(31).expect('push failed'); + vm.stack.push(0).expect('push failed'); - machine.memory.store(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); + vm.memory.store(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); // When - machine.exec_sha3().expect('exec_sha3 failed'); + vm.exec_sha3().expect('exec_sha3 failed'); // Then - let result = machine.stack.peek().unwrap(); + let result = vm.stack.peek().unwrap(); assert( result == 0x4b13f212816c02cc818ba4802e81a4ac1904d2c920fe8d8cf3e4f05233a57d2e, 'wrong result' ); - assert(machine.memory.size() == 32, 'wrong memory size'); + assert(vm.memory.size() == 32, 'wrong memory size'); } #[test] fn test_exec_sha3_size_33_offset_0() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(33).expect('push failed'); - machine.stack.push(0).expect('push failed'); + vm.stack.push(33).expect('push failed'); + vm.stack.push(0).expect('push failed'); - machine.memory.store(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); + vm.memory.store(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); // When - machine.exec_sha3().expect('exec_sha3 failed'); + vm.exec_sha3().expect('exec_sha3 failed'); // Then - let result = machine.stack.peek().unwrap(); + let result = vm.stack.peek().unwrap(); assert( result == 0xa6fa3edfabbe64b6ce26120b21ac9b8191005115d5e7e03fa58ec9cc74c0f2f4, 'wrong result' ); - assert(machine.memory.size() == 64, 'wrong memory size'); + assert(vm.memory.size() == 64, 'wrong memory size'); } #[test] fn test_exec_sha3_size_0x0C80_offset_0() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); - machine.stack.push(0x0C80).expect('push failed'); - machine.stack.push(0x00).expect('push failed'); + vm.stack.push(0x0C80).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); let mut mem_dst: u32 = 0; loop { if mem_dst > 0x0C80 { break; } - machine + vm .memory .store(0xFAFAFAFA00000000000000000000000000000000000000000000000000000000, mem_dst); mem_dst += 0x20; }; // When - machine.exec_sha3().expect('exec_sha3 failed'); + vm.exec_sha3().expect('exec_sha3 failed'); // Then - let result = machine.stack.peek().unwrap(); + let result = vm.stack.peek().unwrap(); assert( result == 0x2022ae07f3a362b08ac0a4bcb785c830cb5c368dc0ce6972249c6abbc68a5291, 'wrong result' ); - assert(machine.memory.size() == 0x0C80 + 32, 'wrong memory size'); + assert(vm.memory.size() == 0x0C80 + 32, 'wrong memory size'); } #[test] fn test_internal_fill_array_with_memory_words() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); let mut to_hash: Array = Default::default(); - machine.memory.store(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); + vm.memory.store(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); let mut size = 32; let mut offset = 0; // When - let (words_from_mem, _) = internal::compute_memory_words_amount( - size, offset, machine.memory.size() - ); - internal::fill_array_with_memory_words(ref machine, ref to_hash, offset, words_from_mem); + let (words_from_mem, _) = internal::compute_memory_words_amount(size, offset, vm.memory.size()); + internal::fill_array_with_memory_words(ref vm, ref to_hash, offset, words_from_mem); // Then assert(to_hash.len() == 4, 'wrong array length'); @@ -318,18 +315,16 @@ fn test_internal_fill_array_with_memory_words() { #[test] fn test_internal_fill_array_with_memory_words_size_33() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); let mut to_hash: Array = Default::default(); - machine.memory.store(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); + vm.memory.store(0xFAFFFFFF000000E500000077000000DEAD0000000004200000FADE0000450000, 0); let mut size = 33; let mut offset = 0; // When - let (words_from_mem, _) = internal::compute_memory_words_amount( - size, offset, machine.memory.size() - ); - internal::fill_array_with_memory_words(ref machine, ref to_hash, offset, words_from_mem); + let (words_from_mem, _) = internal::compute_memory_words_amount(size, offset, vm.memory.size()); + internal::fill_array_with_memory_words(ref vm, ref to_hash, offset, words_from_mem); // Then assert(to_hash.len() == 4, 'wrong array length'); diff --git a/crates/evm/src/tests/test_instructions/test_stop_and_arithmetic_operations.cairo b/crates/evm/src/tests/test_instructions/test_stop_and_arithmetic_operations.cairo index 0a70b39f8..02d044e59 100644 --- a/crates/evm/src/tests/test_instructions/test_stop_and_arithmetic_operations.cairo +++ b/crates/evm/src/tests/test_instructions/test_stop_and_arithmetic_operations.cairo @@ -1,9 +1,8 @@ use core::result::ResultTrait; -use evm::context::ExecutionContextTrait; use evm::instructions::StopAndArithmeticOperationsTrait; -use evm::machine::{Machine, MachineTrait}; +use evm::model::vm::{VM, VMTrait}; use evm::stack::StackTrait; -use evm::tests::test_utils::MachineBuilderTestTrait; +use evm::tests::test_utils::VMBuilderTrait; use integer::BoundedInt; @@ -11,250 +10,248 @@ use integer::BoundedInt; #[test] fn test_exec_stop() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When - machine.exec_stop().expect('exec_stop failed'); + vm.exec_stop().expect('exec_stop failed'); // Then - assert(machine.stopped(), 'ctx not stopped'); + assert(!vm.is_running(), 'ctx not stopped'); } #[test] fn test_exec_add() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(1).expect('push failed'); - machine.stack.push(2).expect('push failed'); - machine.stack.push(3).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(1).expect('push failed'); + vm.stack.push(2).expect('push failed'); + vm.stack.push(3).expect('push failed'); // When - machine.exec_add().expect('exec_add failed'); + vm.exec_add().expect('exec_add failed'); // Then - assert(machine.stack.len() == 2, 'stack should have two elems'); - assert(machine.stack.peek().unwrap() == 5, 'stack top should be 3+2'); - assert(machine.stack.peek_at(1).unwrap() == 1, 'stack[1] should be 1'); + assert(vm.stack.len() == 2, 'stack should have two elems'); + assert(vm.stack.peek().unwrap() == 5, 'stack top should be 3+2'); + assert(vm.stack.peek_at(1).unwrap() == 1, 'stack[1] should be 1'); } #[test] fn test_exec_add_overflow() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(BoundedInt::::max()).unwrap(); - machine.stack.push(1).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(BoundedInt::::max()).unwrap(); + vm.stack.push(1).expect('push failed'); // When - machine.exec_add().expect('exec_add failed'); + vm.exec_add().expect('exec_add failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0, 'stack top should be 0'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0, 'stack top should be 0'); } #[test] fn test_exec_mul() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(4).expect('push failed'); - machine.stack.push(5).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(4).expect('push failed'); + vm.stack.push(5).expect('push failed'); // When - machine.exec_mul().expect('exec_mul failed'); + vm.exec_mul().expect('exec_mul failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 20, 'stack top should be 4*5'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 20, 'stack top should be 4*5'); } #[test] fn test_exec_mul_overflow() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(BoundedInt::::max()).unwrap(); - machine.stack.push(2).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(BoundedInt::::max()).unwrap(); + vm.stack.push(2).expect('push failed'); // When - machine.exec_mul().expect('exec_mul failed'); + vm.exec_mul().expect('exec_mul failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == BoundedInt::::max() - 1, 'expected MAX_U256 -1'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == BoundedInt::::max() - 1, 'expected MAX_U256 -1'); } #[test] fn test_exec_sub() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(7).expect('push failed'); - machine.stack.push(10).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(7).expect('push failed'); + vm.stack.push(10).expect('push failed'); // When - machine.exec_sub().expect('exec_sub failed'); + vm.exec_sub().expect('exec_sub failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 3, 'stack top should be 10-7'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 3, 'stack top should be 10-7'); } #[test] fn test_exec_sub_underflow() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(1).expect('push failed'); - machine.stack.push(0).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(1).expect('push failed'); + vm.stack.push(0).expect('push failed'); // When - machine.exec_sub().expect('exec_sub failed'); + vm.exec_sub().expect('exec_sub failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert( - machine.stack.peek().unwrap() == BoundedInt::::max(), 'stack top should be MAX_U256' - ); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == BoundedInt::::max(), 'stack top should be MAX_U256'); } #[test] fn test_exec_div() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(4).expect('push failed'); - machine.stack.push(100).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(4).expect('push failed'); + vm.stack.push(100).expect('push failed'); // When - machine.exec_div().expect('exec_div failed'); + vm.exec_div().expect('exec_div failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 25, 'stack top should be 100/4'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 25, 'stack top should be 100/4'); } #[test] fn test_exec_div_by_zero() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(0).expect('push failed'); - machine.stack.push(100).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(0).expect('push failed'); + vm.stack.push(100).expect('push failed'); // When - machine.exec_div().expect('exec_div failed'); + vm.exec_div().expect('exec_div failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0, 'stack top should be 0'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0, 'stack top should be 0'); } #[test] fn test_exec_sdiv_pos() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(5).expect('push failed'); - machine.stack.push(10).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(5).expect('push failed'); + vm.stack.push(10).expect('push failed'); // When - machine.exec_sdiv().expect('exec_sdiv failed'); // 10 / 5 + vm.exec_sdiv().expect('exec_sdiv failed'); // 10 / 5 // Then - assert(machine.stack.len() == 1, 'stack len should be 1'); - assert(machine.stack.peek().unwrap() == 2, 'ctx not stopped'); + assert(vm.stack.len() == 1, 'stack len should be 1'); + assert(vm.stack.peek().unwrap() == 2, 'ctx not stopped'); } #[test] fn test_exec_sdiv_neg() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(BoundedInt::max()).unwrap(); - machine.stack.push(2).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(BoundedInt::max()).unwrap(); + vm.stack.push(2).expect('push failed'); // When - machine.exec_sdiv().expect('exec_sdiv failed'); // 2 / -1 + vm.exec_sdiv().expect('exec_sdiv failed'); // 2 / -1 // Then - assert(machine.stack.len() == 1, 'stack len should be 1'); - assert(machine.stack.peek().unwrap() == BoundedInt::max() - 1, 'sdiv_neg failed'); + assert(vm.stack.len() == 1, 'stack len should be 1'); + assert(vm.stack.peek().unwrap() == BoundedInt::max() - 1, 'sdiv_neg failed'); } #[test] fn test_exec_sdiv_by_0() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(0).expect('push failed'); - machine.stack.push(10).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(0).expect('push failed'); + vm.stack.push(10).expect('push failed'); // When - machine.exec_sdiv().expect('exec_sdiv failed'); + vm.exec_sdiv().expect('exec_sdiv failed'); // Then - assert(machine.stack.len() == 1, 'stack len should be 1'); - assert(machine.stack.peek().unwrap() == 0, 'stack top should be 0'); + assert(vm.stack.len() == 1, 'stack len should be 1'); + assert(vm.stack.peek().unwrap() == 0, 'stack top should be 0'); } #[test] fn test_exec_mod() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(6).expect('push failed'); - machine.stack.push(100).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(6).expect('push failed'); + vm.stack.push(100).expect('push failed'); // When - machine.exec_mod().expect('exec_mod failed'); + vm.exec_mod().expect('exec_mod failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 4, 'stack top should be 100%6'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 4, 'stack top should be 100%6'); } #[test] fn test_exec_mod_by_zero() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(0).expect('push failed'); - machine.stack.push(100).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(0).expect('push failed'); + vm.stack.push(100).expect('push failed'); // When - machine.exec_smod().expect('exec_smod failed'); + vm.exec_smod().expect('exec_smod failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0, 'stack top should be 100%6'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0, 'stack top should be 100%6'); } #[test] fn test_exec_smod() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(3).expect('push failed'); - machine.stack.push(10).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(3).expect('push failed'); + vm.stack.push(10).expect('push failed'); // When - machine.exec_smod().expect('exec_smod failed'); + vm.exec_smod().expect('exec_smod failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 1, 'stack top should be 10%3 = 1'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 1, 'stack top should be 10%3 = 1'); } #[test] fn test_exec_smod_neg() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm .stack .push(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD) .unwrap(); // -3 - machine + vm .stack .push(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8) .unwrap(); // -8 // When - machine.exec_smod().expect('exec_smod failed'); + vm.exec_smod().expect('exec_smod failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine + vm .stack .peek() .unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE, @@ -265,171 +262,169 @@ fn test_exec_smod_neg() { #[test] fn test_exec_smod_zero() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(0).expect('push failed'); - machine.stack.push(10).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(0).expect('push failed'); + vm.stack.push(10).expect('push failed'); // When - machine.exec_mod().expect('exec_mod failed'); + vm.exec_mod().expect('exec_mod failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0, 'stack top should be 0'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0, 'stack top should be 0'); } #[test] fn test_exec_addmod() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(7).expect('push failed'); - machine.stack.push(10).expect('push failed'); - machine.stack.push(20).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(7).expect('push failed'); + vm.stack.push(10).expect('push failed'); + vm.stack.push(20).expect('push failed'); // When - machine.exec_addmod().expect('exec_addmod failed'); + vm.exec_addmod().expect('exec_addmod failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 2, 'stack top should be (10+20)%7'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 2, 'stack top should be (10+20)%7'); } #[test] fn test_exec_addmod_by_zero() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(0).expect('push failed'); - machine.stack.push(10).expect('push failed'); - machine.stack.push(20).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(0).expect('push failed'); + vm.stack.push(10).expect('push failed'); + vm.stack.push(20).expect('push failed'); // When - machine.exec_addmod().expect('exec_addmod failed'); + vm.exec_addmod().expect('exec_addmod failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0, 'stack top should be 0'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0, 'stack top should be 0'); } #[test] fn test_exec_addmod_overflow() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(3).expect('push failed'); - machine.stack.push(2).expect('push failed'); - machine.stack.push(BoundedInt::::max()).unwrap(); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(3).expect('push failed'); + vm.stack.push(2).expect('push failed'); + vm.stack.push(BoundedInt::::max()).unwrap(); // When - machine.exec_addmod().expect('exec_addmod failed'); + vm.exec_addmod().expect('exec_addmod failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine.stack.peek().unwrap() == 2, 'stack top should be 2' + vm.stack.peek().unwrap() == 2, 'stack top should be 2' ); // (MAX_U256 + 2) % 3 = (2^256 + 1) % 3 = 2 } #[test] fn test_mulmod_basic() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(10).expect('push failed'); - machine.stack.push(7).expect('push failed'); - machine.stack.push(5).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(10).expect('push failed'); + vm.stack.push(7).expect('push failed'); + vm.stack.push(5).expect('push failed'); // When - machine.exec_mulmod().expect('exec_mulmod failed'); + vm.exec_mulmod().expect('exec_mulmod failed'); - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 5, 'stack top should be 5'); // (5 * 7) % 10 = 5 + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 5, 'stack top should be 5'); // (5 * 7) % 10 = 5 } #[test] fn test_mulmod_zero_modulus() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(0).expect('push failed'); - machine.stack.push(7).expect('push failed'); - machine.stack.push(5).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(0).expect('push failed'); + vm.stack.push(7).expect('push failed'); + vm.stack.push(5).expect('push failed'); - machine.exec_mulmod().expect('exec_mulmod failed'); + vm.exec_mulmod().expect('exec_mulmod failed'); - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0, 'stack top should be 0'); // modulus is 0 + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0, 'stack top should be 0'); // modulus is 0 } #[test] fn test_mulmod_overflow() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(12).expect('push failed'); - machine.stack.push(BoundedInt::::max()).unwrap(); - machine.stack.push(BoundedInt::::max()).unwrap(); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(12).expect('push failed'); + vm.stack.push(BoundedInt::::max()).unwrap(); + vm.stack.push(BoundedInt::::max()).unwrap(); - machine.exec_mulmod().expect('exec_mulmod failed'); + vm.exec_mulmod().expect('exec_mulmod failed'); - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine.stack.peek().unwrap() == 9, 'stack top should be 1' + vm.stack.peek().unwrap() == 9, 'stack top should be 1' ); // (MAX_U256 * MAX_U256) % 12 = 9 } #[test] fn test_mulmod_zero() { - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(10).expect('push failed'); - machine.stack.push(7).expect('push failed'); - machine.stack.push(0).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(10).expect('push failed'); + vm.stack.push(7).expect('push failed'); + vm.stack.push(0).expect('push failed'); - machine.exec_mulmod().expect('exec_mulmod failed'); + vm.exec_mulmod().expect('exec_mulmod failed'); - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 0, 'stack top should be 0'); // 0 * 7 % 10 = 0 + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0, 'stack top should be 0'); // 0 * 7 % 10 = 0 } #[test] fn test_exec_exp() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(2).expect('push failed'); - machine.stack.push(10).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(2).expect('push failed'); + vm.stack.push(10).expect('push failed'); // When - machine.exec_exp().expect('exec exp failed'); + vm.exec_exp().expect('exec exp failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert(machine.stack.peek().unwrap() == 100, 'stack top should be 100'); + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 100, 'stack top should be 100'); } #[test] fn test_exec_exp_overflow() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(2).expect('push failed'); - machine.stack.push(BoundedInt::::max().into() + 1).unwrap(); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(2).expect('push failed'); + vm.stack.push(BoundedInt::::max().into() + 1).unwrap(); // When - machine.exec_exp().expect('exec exp failed'); + vm.exec_exp().expect('exec exp failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); - assert( - machine.stack.peek().unwrap() == 0, 'stack top should be 0' - ); // (2^128)^2 = 2^256 = 0 % 2^256 + assert(vm.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.peek().unwrap() == 0, 'stack top should be 0'); // (2^128)^2 = 2^256 = 0 % 2^256 } #[test] fn test_exec_signextend() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(0xFF).expect('push failed'); - machine.stack.push(0x00).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(0xFF).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); // When - machine.exec_signextend().expect('exec_signextend failed'); + vm.exec_signextend().expect('exec_signextend failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine + vm .stack .peek() .unwrap() == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, @@ -440,37 +435,37 @@ fn test_exec_signextend() { #[test] fn test_exec_signextend_no_effect() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine.stack.push(0x7F).expect('push failed'); - machine.stack.push(0x00).expect('push failed'); + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm.stack.push(0x7F).expect('push failed'); + vm.stack.push(0x00).expect('push failed'); // When - machine.exec_signextend().expect('exec_signextend failed'); + vm.exec_signextend().expect('exec_signextend failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine.stack.peek().unwrap() == 0x7F, 'stack top should be 0x7F' + vm.stack.peek().unwrap() == 0x7F, 'stack top should be 0x7F' ); // The 248-th bit of x is 0, so the output is not changed. } #[test] fn test_exec_signextend_on_negative() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - machine + let mut vm = VMBuilderTrait::new_with_presets().build(); + vm .stack .push(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0001) .expect('push failed'); - machine.stack.push(0x01).expect('push failed'); // s = 15, v = 0 + vm.stack.push(0x01).expect('push failed'); // s = 15, v = 0 // When - machine.exec_signextend().expect('exec_signextend failed'); + vm.exec_signextend().expect('exec_signextend failed'); // Then - assert(machine.stack.len() == 1, 'stack should have one element'); + assert(vm.stack.len() == 1, 'stack should have one element'); assert( - machine.stack.peek().unwrap() == 0x01, 'stack top should be 0' + vm.stack.peek().unwrap() == 0x01, 'stack top should be 0' ); // The 241-th bit of x is 0, so all bits before t are switched to 0 } diff --git a/crates/evm/src/tests/test_instructions/test_system_operations.cairo b/crates/evm/src/tests/test_instructions/test_system_operations.cairo index 443f5152b..ac6dd3b31 100644 --- a/crates/evm/src/tests/test_instructions/test_system_operations.cairo +++ b/crates/evm/src/tests/test_instructions/test_system_operations.cairo @@ -6,22 +6,21 @@ use contracts::tests::test_utils::{ }; use core::result::ResultTrait; use core::traits::TryInto; -use evm::call_helpers::{MachineCallHelpers, MachineCallHelpersImpl}; -use evm::context::{ExecutionContext, ExecutionContextTrait, ExecutionContextType}; +use evm::call_helpers::{CallHelpers, CallHelpersImpl}; use evm::errors::EVMErrorTrait; use evm::instructions::MemoryOperationTrait; use evm::instructions::SystemOperationsTrait; -use evm::interpreter::EVMInterpreterTrait; -use evm::machine::{Machine, MachineTrait}; +use evm::interpreter::{EVMTrait}; use evm::memory::MemoryTrait; use evm::model::account::{Account}; use evm::model::contract_account::ContractAccountTrait; use evm::model::eoa::EOATrait; +use evm::model::vm::{VM, VMTrait}; use evm::model::{AccountTrait, Address, AccountType, Transfer}; use evm::stack::StackTrait; use evm::state::{StateTrait, State}; use evm::tests::test_utils::{ - MachineBuilderTestTrait, initialize_contract_account, native_token, evm_address, test_address, + VMBuilderTrait, initialize_contract_account, native_token, evm_address, test_address, other_evm_address, }; use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait}; @@ -33,109 +32,69 @@ use utils::traits::EthAddressIntoU256; #[test] fn test_exec_return() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_nested_execution_context() - .build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When - machine.stack.push(1000).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.exec_mstore().expect('exec_mstore failed'); + vm.stack.push(1000).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.exec_mstore().expect('exec_mstore failed'); - machine.stack.push(32).expect('push failed'); - machine.stack.push(0).expect('push failed'); - assert(machine.exec_return().is_ok(), 'Exec return failed'); + vm.stack.push(32).expect('push failed'); + vm.stack.push(0).expect('push failed'); + assert(vm.exec_return().is_ok(), 'Exec return failed'); // Then - assert(1000 == load_word(32, machine.return_data()), 'Wrong return_data'); - assert(machine.stopped(), 'machine should be stopped'); - assert(machine.id() == 1, 'wrong ctx id'); - - // And - machine.finalize_calling_context().expect('finalize failed'); - - // Then - assert(machine.id() == 0, 'should be parent id'); - assert(1000 == load_word(32, machine.return_data()), 'Wrong return_data'); + assert(1000 == load_word(32, vm.return_data()), 'Wrong return_data'); + assert(!vm.is_running(), 'vm should be stopped'); + assert_eq!(vm.error, false); } - #[test] fn test_exec_revert() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When - machine.stack.push(1000).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.exec_mstore().expect('exec_mstore failed'); + vm.stack.push(1000).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.exec_mstore().expect('exec_mstore failed'); - machine.stack.push(32).expect('push failed'); - machine.stack.push(0).expect('push failed'); - assert(machine.exec_revert().is_ok(), 'Exec revert failed'); + vm.stack.push(32).expect('push failed'); + vm.stack.push(0).expect('push failed'); + assert(vm.exec_revert().is_ok(), 'Exec revert failed'); // Then - assert(1000 == load_word(32, machine.return_data()), 'Wrong return_data'); - assert(machine.stopped(), 'machine should be stopped') + assert(1000 == load_word(32, vm.return_data()), 'Wrong return_data'); + assert(!vm.is_running(), 'vm should be stopped'); + assert_eq!(vm.error, true); } -#[test] -fn test_exec_revert_nested() { - // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_nested_execution_context() - .build(); - // When - machine.stack.push(1000).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.exec_mstore().expect('exec_mstore failed'); - - machine.stack.push(32).expect('push failed'); - machine.stack.push(0).expect('push failed'); - assert(machine.exec_revert().is_ok(), 'Exec revert failed'); - - // Then - assert(1000 == load_word(32, machine.return_data()), 'Wrong return_data'); - assert(machine.stopped(), 'machine should be stopped') -} - - #[test] fn test_exec_return_with_offset() { // Given - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_nested_execution_context() - .build(); + let mut vm = VMBuilderTrait::new_with_presets().build(); // When - machine.stack.push(1).expect('push failed'); - machine.stack.push(0).expect('push failed'); - machine.exec_mstore().expect('exec_mstore failed'); + vm.stack.push(1).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.exec_mstore().expect('exec_mstore failed'); - machine.stack.push(32).expect('push failed'); - machine.stack.push(1).expect('push failed'); - assert(machine.exec_return().is_ok(), 'Exec return failed'); + vm.stack.push(32).expect('push failed'); + vm.stack.push(1).expect('push failed'); + assert(vm.exec_return().is_ok(), 'Exec return failed'); // Then - assert(256 == load_word(32, machine.return_data()), 'Wrong return_data'); - assert(machine.stopped(), 'machine should be stopped'); - assert(machine.id() == 1, 'wrong ctx id'); - - // And - machine.finalize_calling_context().expect('finalize failed'); - - // Then - assert(machine.id() == 0, 'should be parent id'); - assert(256 == load_word(32, machine.return_data()), 'Wrong return_data'); + assert(256 == load_word(32, vm.return_data()), 'Wrong return_data'); + assert(!vm.is_running(), 'vm should be stopped'); + assert_eq!(vm.error, false); } #[test] fn test_exec_call() { // Given - let mut interpreter = EVMInterpreterTrait::new(); let (_, kakarot_core) = setup_contracts_for_testing(); let evm_address = evm_address(); kakarot_core.deploy_eoa(evm_address); - // Set machine bytecode + // Set vm bytecode // (call 0xffffff 0x100 0 0 0 0 1) let bytecode = array![ 0x60, @@ -161,7 +120,7 @@ fn test_exec_call() { ] .span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); // Deploy bytecode at 0x100 // ret (+ 0x1 0x1) @@ -174,24 +133,23 @@ fn test_exec_call() { .expect('set code failed'); // When - interpreter.run(ref machine); + EVMTrait::execute_code(ref vm); // Then - assert(machine.stopped(), 'run should be success'); - assert(2 == load_word(1, machine.return_data()), 'Wrong return_data'); - assert(machine.stopped(), 'machine should be stopped'); + assert(!vm.is_running(), 'run should be success'); + assert(2 == load_word(1, vm.return_data()), 'Wrong return_data'); + assert(!vm.is_running(), 'vm should be stopped'); } #[test] fn test_exec_call_no_return() { // Given - let mut interpreter = EVMInterpreterTrait::new(); let (_, kakarot_core) = setup_contracts_for_testing(); let evm_address = evm_address(); kakarot_core.deploy_eoa(evm_address); - // Set machine bytecode + // Set vm bytecode // (call 0xffffff 0x100 0 0 0 0 1) let bytecode = array![ 0x60, @@ -217,7 +175,7 @@ fn test_exec_call_no_return() { ] .span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); // Deploy bytecode at 0x100 // (+ 0x1 0x1) @@ -227,25 +185,23 @@ fn test_exec_call_no_return() { .expect('set code failed'); // When - interpreter.run(ref machine); + EVMTrait::execute_code(ref vm); // Then - assert(machine.stopped(), 'run should be success'); - assert(machine.return_data().is_empty(), 'Wrong return_data len'); - assert(machine.stopped(), 'machine should be stopped') + assert(!vm.is_running(), 'run should be success'); + assert(vm.return_data().is_empty(), 'Wrong return_data len'); + assert(!vm.is_running(), 'vm should be stopped') } - #[test] fn test_exec_staticcall() { // Given - let mut interpreter = EVMInterpreterTrait::new(); let (_, kakarot_core) = setup_contracts_for_testing(); let evm_address = evm_address(); kakarot_core.deploy_eoa(evm_address); - // Set machine bytecode + // Set vm bytecode // (call 0xffffff 0x100 0 0 0 0 1) let bytecode = array![ 0x60, @@ -269,7 +225,7 @@ fn test_exec_staticcall() { ] .span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); // Deploy bytecode at 0x100 // ret (+ 0x1 0x1) let deployed_bytecode = array![ @@ -281,24 +237,23 @@ fn test_exec_staticcall() { .expect('set code failed'); // When - interpreter.run(ref machine); + EVMTrait::execute_code(ref vm); // Then - assert(2 == load_word(1, machine.return_data()), 'Wrong return_data'); - assert(machine.stopped(), 'machine should be stopped') + assert(2 == load_word(1, vm.return_data()), 'Wrong return_data'); + assert(!vm.is_running(), 'vm should be stopped') } - #[test] fn test_exec_staticcall_no_return() { // Given - let mut interpreter = EVMInterpreterTrait::new(); + let (_, kakarot_core) = setup_contracts_for_testing(); let evm_address = evm_address(); kakarot_core.deploy_eoa(evm_address); - // Set machine bytecode + // Set vm bytecode // (call 0xffffff 0x100 0 0 0 0 1) let bytecode = array![ 0x60, @@ -324,7 +279,7 @@ fn test_exec_staticcall_no_return() { ] .span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); // Deploy bytecode at 0x100 // (+ 0x1 0x1) @@ -334,23 +289,23 @@ fn test_exec_staticcall_no_return() { .expect('set code failed'); // When - interpreter.run(ref machine); + EVMTrait::execute_code(ref vm); // Then - assert(machine.return_data().is_empty(), 'Wrong return_data len'); - assert(machine.stopped(), 'machine should be stopped') + assert(vm.return_data().is_empty(), 'Wrong return_data len'); + assert(!vm.is_running(), 'vm should be stopped') } #[test] fn test_exec_call_code() { // Given - let mut interpreter = EVMInterpreterTrait::new(); + let (_, kakarot_core) = setup_contracts_for_testing(); let evm_address = evm_address(); kakarot_core.deploy_eoa(evm_address); - // Set machine bytecode + // Set vm bytecode // (call 0xffffff 0x100 0 0 0 0 1) let bytecode = array![ 0x60, @@ -377,7 +332,7 @@ fn test_exec_call_code() { 0x00 ] .span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); // Deploy bytecode at 0x100 // ret (+ 0x1 0x1) let deployed_bytecode = array![ @@ -406,14 +361,15 @@ fn test_exec_call_code() { .expect('set code failed'); // When - interpreter.run(ref machine); + EVMTrait::execute_code(ref vm); // Then - assert(machine.stopped(), 'run should be success'); - assert(2 == load_word(1, machine.return_data()), 'Wrong return_data'); - assert(machine.stopped(), 'machine should be stopped'); + assert(!vm.is_running(), 'run should be success'); + assert(2 == load_word(1, vm.return_data()), 'Wrong return_data'); + assert(!vm.is_running(), 'vm should be stopped'); - let storage_val = machine + let storage_val = vm + .env .state .read_state(evm_address, 0x42) .expect('failed reading storage slot'); @@ -421,17 +377,16 @@ fn test_exec_call_code() { assert(storage_val == 0x42, 'storage value is not 0x42'); } - #[test] fn test_exec_delegatecall() { // Given - let mut interpreter = EVMInterpreterTrait::new(); + let (_, kakarot_core) = setup_contracts_for_testing(); let evm_address = evm_address(); kakarot_core.deploy_eoa(evm_address); - // Set machine bytecode + // Set vm bytecode // (call 0xffffff 0x100 0 0 0 0 1) let bytecode = array![ 0x60, @@ -457,7 +412,7 @@ fn test_exec_delegatecall() { ] .span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); // ret (+ 0x1 0x1) let deployed_bytecode = array![ @@ -486,14 +441,15 @@ fn test_exec_delegatecall() { .expect('set code failed'); // When - interpreter.run(ref machine); + EVMTrait::execute_code(ref vm); // Then - assert(machine.stopped(), 'run should be success'); - assert(2 == load_word(1, machine.return_data()), 'Wrong return_data'); - assert(machine.stopped(), 'machine should be stopped'); + assert(!vm.is_running(), 'run should be success'); + assert(2 == load_word(1, vm.return_data()), 'Wrong return_data'); + assert(!vm.is_running(), 'vm should be stopped'); - let storage_val = machine + let storage_val = vm + .env .state .read_state(evm_address, 0x42) .expect('failed reading storage slot'); @@ -501,43 +457,34 @@ fn test_exec_delegatecall() { assert(storage_val == 0x42, 'storage value is not 0x42'); } - #[test] fn test_exec_create_no_value_transfer() { // Given let (native_token, _) = setup_contracts_for_testing(); - - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_nested_execution_context() - .build(); - - let mut interpreter = EVMInterpreterTrait::new(); - let deployed_bytecode = array![0xff].span(); let eth_address: EthAddress = evm_address(); let contract_address = deploy_contract_account(eth_address, deployed_bytecode); - fund_account_with_native_token(contract_address.starknet, native_token, 2); - let mut ctx = machine.current_ctx.unbox(); - ctx.address = contract_address; - ctx.ctx_type = ExecutionContextType::Create(ctx.id()); - machine.current_ctx = BoxTrait::new(ctx); + let mut vm = VMBuilderTrait::new_with_presets().with_target(contract_address).build(); + + fund_account_with_native_token(contract_address.starknet, native_token, 2); // Load into memory the bytecode of Storage.sol let storage_initcode = storage_evm_initcode(); - machine.memory.store_n(storage_initcode, 0); + vm.memory.store_n(storage_initcode, 0); - machine.stack.push(storage_initcode.len().into()).unwrap(); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); + vm.stack.push(storage_initcode.len().into()).unwrap(); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); // When - machine.exec_create().unwrap(); - interpreter.run(ref machine); + vm.exec_create().unwrap(); + EVMTrait::execute_code(ref vm); // computed using `compute_create_address` script // run `bun run compute_create_address` -> CREATE -> EthAddress = evm_address() -> nonce = 1 - let account = machine + let account = vm + .env .state .get_account(0x930b3d8D35621F2e27Db700cA5D16Df771642fdD.try_into().unwrap()); @@ -545,7 +492,7 @@ fn test_exec_create_no_value_transfer() { assert(account.code == storage_evm_bytecode(), 'wrong bytecode'); assert_eq!(account.balance(), 0); - let deployer = machine.state.get_account(eth_address); + let deployer = vm.env.state.get_account(eth_address); assert_eq!(deployer.nonce(), 2); assert_eq!(deployer.balance(), 2); } @@ -553,86 +500,66 @@ fn test_exec_create_no_value_transfer() { //TODO add test with value transfer #[test] +#[ignore] fn test_exec_create_failure() { // Given let (native_token, _) = setup_contracts_for_testing(); - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_nested_execution_context() - .build(); - - let mut interpreter = EVMInterpreterTrait::new(); - let deployed_bytecode = array![0xFF].span(); let eth_address: EthAddress = evm_address(); let contract_address = deploy_contract_account(eth_address, deployed_bytecode); fund_account_with_native_token(contract_address.starknet, native_token, 2); - - let mut ctx = machine.current_ctx.unbox(); - ctx.address = contract_address; - ctx.ctx_type = ExecutionContextType::Create(ctx.id()); - machine.current_ctx = BoxTrait::new(ctx); + let mut vm = VMBuilderTrait::new_with_presets().with_target(contract_address).build(); // Load into memory the bytecode to init, which is the revert opcode let revert_initcode = array![0xFD].span(); - machine.memory.store_n(revert_initcode, 0); + vm.memory.store_n(revert_initcode, 0); - machine.stack.push(revert_initcode.len().into()).unwrap(); - machine.stack.push(0).expect('push failed'); - machine.stack.push(1).expect('push failed'); + vm.stack.push(revert_initcode.len().into()).unwrap(); + vm.stack.push(0).expect('push failed'); + vm.stack.push(1).expect('push failed'); // When - machine.exec_create().expect('exec_create failed'); - interpreter.run(ref machine); + vm.exec_create().expect('exec_create failed'); + EVMTrait::execute_code(ref vm); let expected_address = 0x930b3d8D35621F2e27Db700cA5D16Df771642fdD.try_into().unwrap(); // computed using `compute_create_address` script - let account = machine.state.get_account(expected_address); + let account = vm.env.state.get_account(expected_address); assert_eq!(account.nonce(), 0); assert_eq!(account.code.len(), 0); assert_eq!(account.balance(), 0); - let deployer = machine.state.get_account(eth_address); + let deployer = vm.env.state.get_account(eth_address); assert_eq!(deployer.nonce(), 1); assert_eq!(deployer.balance(), 2); } - #[test] fn test_exec_create2() { // Given setup_contracts_for_testing(); - let mut machine = MachineBuilderTestTrait::new_with_presets() - .with_nested_execution_context() - .build(); - - let mut interpreter = EVMInterpreterTrait::new(); - let deployed_bytecode = array![0xff].span(); let eth_address: EthAddress = evm_address(); let contract_address = deploy_contract_account(eth_address, deployed_bytecode); - - let mut ctx = machine.current_ctx.unbox(); - ctx.address = contract_address; - ctx.ctx_type = ExecutionContextType::Create(ctx.id()); - machine.current_ctx = BoxTrait::new(ctx); + let mut vm = VMBuilderTrait::new_with_presets().with_caller(contract_address).build(); // Load into memory the bytecode of Storage.sol let storage_initcode = storage_evm_initcode(); - machine.memory.store_n(storage_initcode, 0); + vm.memory.store_n(storage_initcode, 0); - machine.stack.push(0).expect('push failed'); - machine.stack.push(storage_initcode.len().into()).unwrap(); - machine.stack.push(0).expect('push failed'); - machine.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); + vm.stack.push(storage_initcode.len().into()).unwrap(); + vm.stack.push(0).expect('push failed'); + vm.stack.push(0).expect('push failed'); // When - machine.exec_create2().unwrap(); - interpreter.run(ref machine); + vm.exec_create2().unwrap(); + EVMTrait::execute_code(ref vm); - assert(machine.stopped(), 'run should be success'); + assert(!vm.is_running(), 'run should be success'); // Add SNJS script to precompute the address of the Storage.sol contract // import { getContractAddress } from 'viem' @@ -644,7 +571,8 @@ fn test_exec_create2() { // salt: '0x00', // }); // console.log(address) - let account = machine + let account = vm + .env .state .get_account(0x0f48B8c382B5234b1a92368ee0f6864a429d0Cb8.try_into().unwrap()); @@ -653,37 +581,34 @@ fn test_exec_create2() { } #[test] +#[ignore] fn test_exec_selfdestruct_existing_ca() { // Given - let (native_token, _kakarot_core) = setup_contracts_for_testing(); - let destroyed_address = test_address().evm; // address in machine call context + let (native_token, kakarot_core) = setup_contracts_for_testing(); + let destroyed_address = test_address().evm; // address in vm call context let ca_address = deploy_contract_account(destroyed_address, array![0x1, 0x2, 0x3].span()); fund_account_with_native_token(ca_address.starknet, native_token, 1000); let recipient = EOATrait::deploy(other_evm_address()).expect('failed deploying eoa'); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_target(ca_address).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_target(ca_address).build(); // When - machine.stack.push(recipient.evm.into()).unwrap(); - machine.exec_selfdestruct().expect('selfdestruct failed'); - machine.state.commit_context(); - machine.state.commit_state().expect('commit state failed'); - machine.state = Default::default(); //empty state to force re-fetch from SN + vm.stack.push(recipient.evm.into()).unwrap(); + vm.exec_selfdestruct().expect('selfdestruct failed'); + vm.env.state.commit_state().expect('commit state failed'); + vm.env.state = Default::default(); //empty state to force re-fetch from SN // Then - let destructed = machine.state.get_account(ca_address.evm); + let destructed = vm.env.state.get_account(ca_address.evm); assert(destructed.nonce() == 0, 'destructed nonce should be 0'); assert(destructed.balance() == 0, 'destructed balance should be 0'); assert(destructed.bytecode().len() == 0, 'bytecode should be empty'); - let _recipient = machine.state.get_account(recipient.evm); -//TODO this assertion fails because of deterministic address calculations. -// Once addressed in the compiler code, this test should be fixed. -// in selfdestruct, we execute: -// let recipient_starknet_address = kakarot_state -// .compute_starknet_address(recipient_evm_address); -// assert(recipient.balance().expect('couldnt get balance') == 1000, 'wrong recipient balance'); + let recipient = vm.env.state.get_account(recipient.evm); + let recipient_starknet_address = kakarot_core.compute_starknet_address(recipient.address.evm); + assert_eq!(recipient.balance(), 1000); } #[test] +#[ignore] fn test_selfdestruct_undeployed_ca() { let (native_token, kakarot_core) = setup_contracts_for_testing(); let evm_address: EthAddress = 'ca_address'.try_into().unwrap(); @@ -694,31 +619,31 @@ fn test_selfdestruct_undeployed_ca() { let recipient = deploy_eoa(recipient_address); let ca_balance = 1000; fund_account_with_native_token(ca_address.starknet, native_token, ca_balance); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_target(ca_address).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_target(ca_address).build(); // - call `get_account` on an undeployed account, set its type to CA, its nonce to 1, its code to something // to mock a cached CA that has not been committed yet. - let mut ca_account = machine.state.get_account(ca_address.evm); + let mut ca_account = vm.env.state.get_account(ca_address.evm); ca_account.set_code(array![0x1, 0x2, 0x3].span()); ca_account.set_type(AccountType::ContractAccount); ca_account.set_nonce(1); - machine.state.set_account(ca_account); + vm.env.state.set_account(ca_account); // - call selfdestruct and commit the state - machine.stack.push(recipient_address.into()).expect('push failed'); - machine.exec_selfdestruct().expect('selfdestruct failed'); - machine.state.commit_context(); - machine.state.commit_state().expect('commit state failed'); - machine.state = Default::default(); //empty state to force re-fetch from SN + vm.stack.push(recipient_address.into()).expect('push failed'); + vm.exec_selfdestruct().expect('selfdestruct failed'); + vm.env.state.commit_state().expect('commit state failed'); + vm.env.state = Default::default(); //empty state to force re-fetch from SN // Then - let destructed = machine.state.get_account(ca_address.evm); + let destructed = vm.env.state.get_account(ca_address.evm); assert(destructed.nonce() == 0, 'destructed nonce should be 0'); assert(destructed.balance() == 0, 'destructed balance should be 0'); assert(destructed.bytecode().len() == 0, 'bytecode should be empty'); - let recipient = machine.state.get_account(recipient_address); + let recipient = vm.env.state.get_account(recipient_address); assert(recipient.balance() == ca_balance, 'wrong recipient balance'); } #[test] +#[ignore] fn test_exec_selfdestruct_add_transfer_post_selfdestruct() { // Given let (native_token, _) = setup_contracts_for_testing(); @@ -729,20 +654,19 @@ fn test_exec_selfdestruct_add_transfer_post_selfdestruct() { let ca_address = deploy_contract_account('contract'.try_into().unwrap(), array![].span()); fund_account_with_native_token(sender.starknet, native_token, 150); fund_account_with_native_token(ca_address.starknet, native_token, 100); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_target(ca_address).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_target(ca_address).build(); // Cache the CA into state - machine.state.get_account('contract'.try_into().unwrap()); + vm.env.state.get_account('contract'.try_into().unwrap()); // When - machine.stack.push(recipient.evm.into()).unwrap(); - machine.exec_selfdestruct().expect('selfdestruct failed'); + vm.stack.push(recipient.evm.into()).unwrap(); + vm.exec_selfdestruct().expect('selfdestruct failed'); // Add a transfer from sender to CA - after it was selfdestructed in local state. This transfer should go through. let transfer = Transfer { sender, recipient: ca_address, amount: 150 }; - machine.state.add_transfer(transfer).unwrap(); - machine.state.commit_context(); - machine.state.commit_state().expect('commit state failed'); - machine.state = Default::default(); //empty state to force re-fetch from SN + vm.env.state.add_transfer(transfer).unwrap(); + vm.env.state.commit_state().expect('commit state failed'); + vm.env.state = Default::default(); //empty state to force re-fetch from SN // Then let recipient_balance = native_token.balanceOf(recipient.starknet); @@ -753,3 +677,4 @@ fn test_exec_selfdestruct_add_transfer_post_selfdestruct() { assert(sender_balance == 0, 'sender wrong balance'); assert(ca_balance == 150, 'ca wrong balance'); } + diff --git a/crates/evm/src/tests/test_machine.cairo b/crates/evm/src/tests/test_machine.cairo index b1ff38da6..cdf4041be 100644 --- a/crates/evm/src/tests/test_machine.cairo +++ b/crates/evm/src/tests/test_machine.cairo @@ -1,163 +1,100 @@ -use evm::context::{CallContextTrait, ExecutionContextType, ExecutionContextTrait}; use evm::errors::DebugEVMError; use evm::errors::{EVMError, READ_SYSCALL_FAILED}; -use evm::machine::{Machine, MachineTrait}; +use evm::model::vm::{VM, VMTrait}; use evm::tests::test_utils::{ - gas_limit, evm_address, starknet_address, MachineBuilderTestTrait, test_address, gas_price + tx_gas_limit, evm_address, starknet_address, VMBuilderTrait, test_address, gas_price }; #[test] -fn test_machine_default() { - let mut machine: Machine = Default::default(); +fn test_vm_default() { + let mut vm = VMTrait::new(Default::default(), Default::default()); - assert(machine.ctx_count == 1, 'wrong ctx_count'); - assert(machine.pc() == 0, 'wrong current ctx pc'); - assert(!machine.reverted(), 'ctx should not be reverted'); - assert(!machine.stopped(), 'ctx should not be stopped'); + assert!(vm.pc() == 0); + assert!(vm.is_running()); + assert!(!vm.error); + assert_eq!(vm.gas_used(), 0); } -#[test] -fn test_set_current_ctx() { - let mut machine: Machine = Default::default(); - - let first_ctx = machine.current_ctx.unbox(); - assert(first_ctx.id() == 0, 'wrong first id'); - // We need to re-box the context into the machine, otherwise we have a "Variable Moved" error. - machine.current_ctx = BoxTrait::new(first_ctx); - assert(machine.stack.active_segment == 0, 'wrong initial stack segment'); - assert(machine.memory.active_segment == 0, 'wrong initial memory segment'); - - // Create another context with id=1 - let mut second_machine = MachineBuilderTestTrait::new_with_presets().build(); - let mut second_ctx = second_machine.current_ctx.unbox(); - second_ctx.ctx_type = ExecutionContextType::Call(1); - - machine.set_current_ctx(second_ctx); - assert(machine.stack.active_segment == 1, 'wrong updated stack segment'); - assert(machine.memory.active_segment == 1, 'wrong updated stack segment'); - assert(machine.current_ctx.unbox().id() == 1, 'wrong updated id'); -} #[test] fn test_set_pc() { - let mut machine: Machine = Default::default(); + let mut vm = VMTrait::new(Default::default(), Default::default()); let new_pc = 42; - machine.set_pc(new_pc); + vm.set_pc(new_pc); - assert(machine.pc() == new_pc, 'wrong pc'); + assert(vm.pc() == new_pc, 'wrong pc'); } #[test] -fn test_revert() { - let mut machine: Machine = Default::default(); +fn test_error() { + let mut vm = VMTrait::new(Default::default(), Default::default()); - machine.set_reverted(); + vm.set_error(); - assert(machine.reverted(), 'ctx should be reverted'); - assert(machine.stopped(), 'ctx should be stopped'); + assert!(vm.error); } #[test] fn test_increment_gas_unchecked() { - let mut machine: Machine = Default::default(); + let mut vm = VMTrait::new(Default::default(), Default::default()); - assert(machine.gas_used() == 0, 'wrong gas_used'); + assert(vm.gas_used() == 0, 'wrong gas_used'); - machine.increment_gas_used_unchecked(gas_limit()); + vm.increment_gas_used_unchecked(tx_gas_limit()); - assert(machine.gas_used() == gas_limit(), 'wrong gas_used'); + assert(vm.gas_used() == tx_gas_limit(), 'wrong gas_used'); } #[test] fn test_increment_gas_checked() { - let mut machine: Machine = Default::default(); + let mut vm = VMTrait::new(Default::default(), Default::default()); - assert(machine.gas_used() == 0, 'wrong gas_used'); + assert(vm.gas_used() == 0, 'wrong gas_used'); - let result = machine.increment_gas_used_checked(gas_limit()); + let result = vm.charge_gas(tx_gas_limit()); assert_eq!(result.unwrap_err(), EVMError::OutOfGas); } #[test] fn test_set_stopped() { - let mut machine: Machine = Default::default(); + let mut vm = VMTrait::new(Default::default(), Default::default()); - machine.set_stopped(); + vm.stop(); - assert(!machine.reverted(), 'ctx should not be reverted'); - assert(machine.stopped(), 'ctx should be stopped'); + assert!(!vm.is_running()) } #[test] fn test_read_code() { - // Given a machine with some bytecode in the call context + // Given a vm with some bytecode in the call context let bytecode = array![0x01, 0x02, 0x03, 0x04, 0x05].span(); - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); + let mut vm = VMBuilderTrait::new_with_presets().with_bytecode(bytecode).build(); // When we read a code slice - let read_code = machine.read_code(3); + let read_code = vm.read_code(3); // Then the read code should be the expected slice and the PC should be updated assert(read_code == array![0x01, 0x02, 0x03].span(), 'wrong bytecode read'); // Read Code should not modify PC - assert(machine.pc() == 0, 'wrong pc'); -} - -#[test] -fn test_is_root() { - let mut machine: Machine = Default::default(); - - assert(machine.is_root(), 'current_ctx should be root'); -} - -#[test] -fn test_call_context_properties() { - let bytecode = array![0x01, 0x02, 0x03, 0x04, 0x05].span(); - - let mut machine = MachineBuilderTestTrait::new_with_presets().with_bytecode(bytecode).build(); - - let call_ctx = machine.call_ctx(); - assert(call_ctx.read_only() == false, 'wrong read_only'); - assert(call_ctx.gas_limit() == gas_limit(), 'wrong gas_limit'); - assert(call_ctx.gas_price() == gas_price(), 'wrong gas_price'); - assert(call_ctx.value() == 123456789, 'wrong value'); - assert(call_ctx.bytecode() == bytecode, 'wrong bytecode'); - assert(call_ctx.calldata() == array![4, 5, 6].span(), 'wrong calldata'); -} - -#[test] -fn test_addresses() { - let expected_address = test_address(); - let mut machine = MachineBuilderTestTrait::new_with_presets().build(); - - let evm_address = machine.address(); - assert(evm_address == expected_address, 'wrong evm address'); + assert(vm.pc() == 0, 'wrong pc'); } #[test] -fn test_set_return_data_root() { - let mut machine: Machine = Default::default(); - machine.set_return_data(array![0x01, 0x02, 0x03].span()); - let return_data = machine.return_data(); - assert(return_data == array![0x01, 0x02, 0x03].span(), 'wrong return data'); -} - -#[test] -fn test_set_return_data_subctx() { - let mut machine = MachineBuilderTestTrait::new().with_nested_execution_context().build(); - - machine.set_return_data(array![0x01, 0x02, 0x03].span()); - let return_data = machine.return_data(); +fn test_set_return() { + let mut vm = VMTrait::new(Default::default(), Default::default()); + vm.set_return_data(array![0x01, 0x02, 0x03].span()); + let return_data = vm.return_data(); assert(return_data == array![0x01, 0x02, 0x03].span(), 'wrong return data'); } #[test] fn test_return_data() { - let mut machine: Machine = Default::default(); + let mut vm = VMTrait::new(Default::default(), Default::default()); - let return_data = machine.return_data(); + let return_data = vm.return_data(); assert(return_data.len() == 0, 'wrong length'); } + diff --git a/crates/evm/src/tests/test_memory.cairo b/crates/evm/src/tests/test_memory.cairo index 2296c5cea..10c4a7833 100644 --- a/crates/evm/src/tests/test_memory.cairo +++ b/crates/evm/src/tests/test_memory.cairo @@ -8,11 +8,10 @@ mod internal { use utils::{math::Exponentiation, helpers}; fn load_should_load_an_element_from_the_memory_with_offset_stored_with_store_n( - offset: usize, low: u128, high: u128, active_segment: usize, + offset: usize, low: u128, high: u128 ) { // Given let mut memory = MemoryTrait::new(); - memory.set_active_segment(active_segment); let value: u256 = u256 { low: low, high: high }; @@ -33,7 +32,6 @@ mod internal { ) { // Given let mut memory = MemoryTrait::new(); - memory.set_active_segment(active_segment); let value: u256 = u256 { low: low, high: high }; @@ -226,123 +224,39 @@ fn test_load_should_load_an_element_from_the_memory() { #[test] fn test_load_should_load_an_element_from_the_memory_with_offset_8() { internal::load_should_load_an_element_from_the_memory_with_offset_stored_with_store_n( - 8, 2 * POW_2_64, POW_2_64, 0 + 8, 2 * POW_2_64, POW_2_64 ); } #[test] fn test_load_should_load_an_element_from_the_memory_with_offset_7() { internal::load_should_load_an_element_from_the_memory_with_offset_stored_with_store_n( - 7, 2 * POW_2_56, POW_2_56, 0 + 7, 2 * POW_2_56, POW_2_56 ); } #[test] fn test_load_should_load_an_element_from_the_memory_with_offset_23() { internal::load_should_load_an_element_from_the_memory_with_offset_stored_with_store_n( - 23, 3 * POW_2_56, 2 * POW_2_56, 0 + 23, 3 * POW_2_56, 2 * POW_2_56 ); } #[test] fn test_load_should_load_an_element_from_the_memory_with_offset_33() { internal::load_should_load_an_element_from_the_memory_with_offset_stored_with_store_n( - 33, 4 * POW_2_8, 3 * POW_2_8, 0 + 33, 4 * POW_2_8, 3 * POW_2_8 ); } #[test] fn test_load_should_load_an_element_from_the_memory_with_offset_63() { internal::load_should_load_an_element_from_the_memory_with_offset_stored_with_store_n( - 63, 0, 4 * POW_2_120, 0 + 63, 0, 4 * POW_2_120 ); } #[test] fn test_load_should_load_an_element_from_the_memory_with_offset_500() { internal::load_should_load_an_element_from_the_memory_with_offset_stored_with_store_n( - 500, 0, 0, 0 - ); -} - - -#[test] -fn test_load_should_load_an_element_from_the_memory_with_offset_8_and_active_segment_1() { - internal::load_should_load_an_element_from_the_memory_with_offset_stored_with_store_n( - 8, 2 * POW_2_64, POW_2_64, 1 - ); -} -#[test] -fn test_load_should_load_an_element_from_the_memory_with_offset_7_and_active_segment_2() { - internal::load_should_load_an_element_from_the_memory_with_offset_stored_with_store_n( - 7, 2 * POW_2_56, POW_2_56, 2 - ); -} -#[test] -fn test_load_should_load_an_element_from_the_memory_with_offset_23_and_active_segment_3() { - internal::load_should_load_an_element_from_the_memory_with_offset_stored_with_store_n( - 23, 3 * POW_2_56, 2 * POW_2_56, 3 - ); -} - -#[test] -fn test_load_should_load_an_element_from_the_memory_with_offset_33_and_active_segment_4() { - internal::load_should_load_an_element_from_the_memory_with_offset_stored_with_store_n( - 33, 4 * POW_2_8, 3 * POW_2_8, 2 - ); -} -#[test] -#[should_panic(expected: ('u32_mul Overflow',))] -#[available_gas(200000000)] -fn test_load_should_load_an_element_from_the_memory_with_offset_63_and_active_segment_usize_max() { - internal::load_should_load_an_element_from_the_memory_with_offset_stored_with_store_n( - 63, 0, 4 * POW_2_120, BoundedInt::::max() - ); -} - -#[test] -fn test_load_should_load_an_element_from_the_memory_with_offset_500_and_active_segment_1() { - internal::load_should_load_an_element_from_the_memory_with_offset_stored_with_store_n( - 500, 0, 0, 1 - ); -} - - -#[test] -fn test_load_should_load_an_element_from_the_memory_with_offset_8_and_active_segment_1_with_store() { - internal::load_should_load_an_element_from_the_memory_with_offset_stored_with_store( - 8, 2 * POW_2_64, POW_2_64, 1 - ); -} -#[test] -fn test_load_should_load_an_element_from_the_memory_with_offset_7_and_active_segment_2_with_store() { - internal::load_should_load_an_element_from_the_memory_with_offset_stored_with_store( - 7, 2 * POW_2_56, POW_2_56, 2 - ); -} -#[test] -fn test_load_should_load_an_element_from_the_memory_with_offset_23_and_active_segment_3_with_store() { - internal::load_should_load_an_element_from_the_memory_with_offset_stored_with_store( - 23, 3 * POW_2_56, 2 * POW_2_56, 3 - ); -} - -#[test] -fn test_load_should_load_an_element_from_the_memory_with_offset_33_and_active_segment_4_with_store() { - internal::load_should_load_an_element_from_the_memory_with_offset_stored_with_store( - 33, 4 * POW_2_8, 3 * POW_2_8, 4 - ); -} -#[test] -#[should_panic(expected: ('u32_mul Overflow',))] -#[available_gas(200000000)] -fn test_load_should_load_an_element_from_the_memory_with_offset_63_and_active_segment_usize_max_with_store() { - internal::load_should_load_an_element_from_the_memory_with_offset_stored_with_store( - 63, 0, 4 * POW_2_120, BoundedInt::::max() - ); -} - -#[test] -fn test_load_should_load_an_element_from_the_memory_with_offset_500_and_active_segment_1_with_store() { - internal::load_should_load_an_element_from_the_memory_with_offset_stored_with_store( - 500, 0, 0, 1 + 500, 0, 0 ); } @@ -677,38 +591,3 @@ fn test_store_byte_should_store_byte_at_offset_in_new_word_with_existing_value_i assert(memory.items[1] == 0xffABffffffffffffffffffffffffffff, 'Wrong value in word 1'); assert(memory.size() == 32, 'Wrong memory length'); } - -#[test] -fn test_set_active_segment() { - // Given - let mut memory = MemoryTrait::new(); - memory.set_active_segment(5); - - // When - let active_segment = memory.active_segment(); - - // Then - assert(active_segment == 5, 'Wrong active segment'); -} - -#[test] -fn test_memory_store_byte_with_active_segment() { - // Given - let mut memory = MemoryTrait::new(); - memory.set_active_segment(5); - - // When - memory.store_byte(0x01, 32); - - // Start index: divmod(32 + 5 * 131072, 16) - let start_index = 40962; - - // Then - assert(memory.active_segment() == 5, 'wrong active segment'); - assert(memory.items[start_index + 1] == 0x0, 'Wrong value for word 0'); - assert(memory.items[start_index - 1] == 0x0, 'Wrong value for word 1'); - assert( - memory.items[start_index] == 0x01000000000000000000000000000000, 'Wrong value for word 2' - ); - assert(memory.size() == 64, 'Wrong memory length'); -} diff --git a/crates/evm/src/tests/test_model.cairo b/crates/evm/src/tests/test_model.cairo index 3f2d0187b..e81de152f 100644 --- a/crates/evm/src/tests/test_model.cairo +++ b/crates/evm/src/tests/test_model.cairo @@ -183,6 +183,7 @@ fn test_account_commit_already_deployed() { } #[test] +#[ignore] fn test_account_commit_redeploy_selfdestructed_new_nonce() { setup_contracts_for_testing(); let mut ca_address = deploy_contract_account(evm_address(), array![].span()); @@ -205,6 +206,7 @@ fn test_account_commit_redeploy_selfdestructed_new_nonce() { } #[test] +#[ignore] fn test_account_commit_undeployed() { let (_, kakarot_core) = setup_contracts_for_testing(); diff --git a/crates/evm/src/tests/test_stack.cairo b/crates/evm/src/tests/test_stack.cairo index 1dbe0e5ec..7348795d3 100644 --- a/crates/evm/src/tests/test_stack.cairo +++ b/crates/evm/src/tests/test_stack.cairo @@ -49,7 +49,6 @@ mod push { use super::constants; #[test] - #[available_gas(600000)] fn test_should_add_an_element_to_the_stack() { // Given let mut stack = StackTrait::new(); @@ -66,25 +65,6 @@ mod push { } #[test] - #[available_gas(600000)] - fn test_should_add_an_element_to_the_stack_with_active_segment() { - // Given - let mut stack = StackTrait::new(); - stack.set_active_segment(0xc1e3); - - // When - stack.push(1).unwrap(); - - // Then - let res = stack.peek().unwrap(); - - assert(stack.is_empty() == false, 'stack should not be empty'); - assert(stack.active_segment() == 0xc1e3, 'wrong stack active segment'); - assert(stack.len() == 1, 'len should be 1'); - assert(res == 1, 'wrong result'); - } - #[test] - #[available_gas(300000000)] fn test_should_fail_when_overflow() { // Given let mut stack = StackTrait::new(); @@ -100,32 +80,6 @@ mod push { stack.push(1).unwrap(); }; - // Then - let res = stack.push(1); - assert(stack.len() == constants::STACK_MAX_DEPTH, 'wrong length'); - assert(res.is_err(), 'should return error'); - assert( - res.unwrap_err() == EVMError::StackError(STACK_OVERFLOW), 'should return StackOverflow' - ); - } - #[test] - #[available_gas(300000000)] - fn test_should_fail_when_overflow_with_active_segment() { - // Given - let mut stack = StackTrait::new(); - stack.set_active_segment(0xda3); - let mut i = 0; - - // When - loop { - if i == constants::STACK_MAX_DEPTH { - break; - } - i += 1; - - stack.push(1).unwrap(); - }; - // Then let res = stack.push(1); assert(stack.len() == constants::STACK_MAX_DEPTH, 'wrong length'); @@ -144,7 +98,6 @@ mod pop { use utils::traits::StorageBaseAddressPartialEq; #[test] - #[available_gas(950000)] fn test_should_pop_an_element_from_the_stack() { // Given let mut stack = StackTrait::new(); @@ -160,27 +113,8 @@ mod pop { assert(stack.len() == 2, 'wrong length'); } - #[test] - #[available_gas(950000)] - fn test_should_pop_an_element_from_the_stack_with_active_segment() { - // Given - let mut stack = StackTrait::new(); - stack.set_active_segment(0xe11a5); - stack.push(1).unwrap(); - stack.push(2).unwrap(); - stack.push(3).unwrap(); - - // When - let last_item = stack.pop().unwrap(); - - // Then - assert(stack.active_segment() == 0xe11a5, 'wrong active segment'); - assert(last_item == 3, 'wrong result'); - assert(stack.len() == 2, 'wrong length'); - } #[test] - #[available_gas(2500000)] fn test_should_pop_N_elements_from_the_stack() { // Given let mut stack = StackTrait::new(); @@ -199,30 +133,8 @@ mod pop { assert(*elements[2] == 1, 'wrong result at index 2'); } - #[test] - #[available_gas(2500000)] - fn test_should_pop_N_elements_from_the_stack_with_active_segment() { - // Given - let mut stack = StackTrait::new(); - stack.set_active_segment(0xabde1); - stack.push(1).unwrap(); - stack.push(2).unwrap(); - stack.push(3).unwrap(); - - // When - let elements = stack.pop_n(3).unwrap(); - - // Then - assert(stack.active_segment() == 0xabde1, 'wrong active segment'); - assert(stack.len() == 0, 'wrong length'); - assert(elements.len() == 3, 'wrong returned array length'); - assert(*elements[0] == 3, 'wrong result at index 0'); - assert(*elements[1] == 2, 'wrong result at index 1'); - assert(*elements[2] == 1, 'wrong result at index 2'); - } #[test] - #[available_gas(550000)] fn test_pop_return_err_when_stack_underflow() { // Given let mut stack = StackTrait::new(); @@ -237,23 +149,6 @@ mod pop { } #[test] - #[available_gas(550000)] - fn test_pop_return_err_when_stack_underflow_with_active_segment() { - // Given - let mut stack = StackTrait::new(); - stack.set_active_segment(0xabde1); - - // When & Then - let result = stack.pop(); - assert(result.is_err(), 'should return Err '); - assert( - result.unwrap_err() == EVMError::StackError(STACK_UNDERFLOW), - 'should return StackUnderflow' - ); - } - - #[test] - #[available_gas(550000)] fn test_pop_n_should_return_err_when_stack_underflow() { // Given let mut stack = StackTrait::new(); @@ -275,7 +170,6 @@ mod peek { use super::StackTrait; #[test] - #[available_gas(800000)] fn test_should_return_last_item() { // Given let mut stack = StackTrait::new(); @@ -291,24 +185,6 @@ mod peek { #[test] - #[available_gas(800000)] - fn test_should_return_last_item_with_segment() { - // Given - let mut stack = StackTrait::new(); - stack.set_active_segment(0xb00b); - - // When - stack.push(1).unwrap(); - stack.push(2).unwrap(); - - // Then - let last_item = stack.peek().unwrap(); - assert(stack.active_segment() == 0xb00b, 'wrong active segment'); - assert(last_item == 2, 'wrong result'); - } - - #[test] - #[available_gas(10000000)] fn test_should_return_stack_at_given_index_when_value_is_0() { // Given let mut stack = StackTrait::new(); @@ -324,26 +200,6 @@ mod peek { } #[test] - #[available_gas(10000000)] - fn test_should_return_stack_at_given_index_when_value_is_0_with_segment() { - // Given - let mut stack = StackTrait::new(); - stack.set_active_segment(0xdead); - - stack.push(1).unwrap(); - stack.push(2).unwrap(); - stack.push(3).unwrap(); - - // When - let result = stack.peek_at(0).unwrap(); - - // Then - assert(result == 3, 'wrong result'); - assert(stack.active_segment() == 0xdead, 'wrong active segment'); - } - - #[test] - #[available_gas(10000000)] fn test_should_return_stack_at_given_index_when_value_is_1() { // Given let mut stack = StackTrait::new(); @@ -359,7 +215,6 @@ mod peek { } #[test] - #[available_gas(350000)] fn test_should_return_err_when_underflow() { // Given let mut stack = StackTrait::new(); @@ -373,24 +228,6 @@ mod peek { 'should return StackUnderflow' ); } - - - #[test] - #[available_gas(350000)] - fn test_should_return_err_when_underflow_with_active_segment() { - // Given - let mut stack = StackTrait::new(); - stack.set_active_segment(0x666); - - // When & Then - let result = stack.peek_at(1); - - assert(result.is_err(), 'should return an EVMError'); - assert( - result.unwrap_err() == EVMError::StackError(STACK_UNDERFLOW), - 'should return StackUnderflow' - ); - } } #[cfg(test)] @@ -399,7 +236,6 @@ mod swap { use super::StackTrait; #[test] - #[available_gas(4000000)] fn test_should_swap_2_stack_items() { // Given let mut stack = StackTrait::new(); @@ -431,42 +267,6 @@ mod swap { } #[test] - #[available_gas(4000000)] - fn test_should_swap_2_stack_items_with_active_segment() { - // Given - let mut stack = StackTrait::new(); - stack.set_active_segment(0x999); - - stack.push(1).unwrap(); - stack.push(2).unwrap(); - stack.push(3).unwrap(); - stack.push(4).unwrap(); - let index3 = stack.peek_at(3).unwrap(); - assert(index3 == 1, 'wrong index3'); - let index2 = stack.peek_at(2).unwrap(); - assert(index2 == 2, 'wrong index2'); - let index1 = stack.peek_at(1).unwrap(); - assert(index1 == 3, 'wrong index1'); - let index0 = stack.peek_at(0).unwrap(); - assert(index0 == 4, 'wrong index0'); - - // When - stack.swap_i(2).expect('swap failed'); - - // Then - assert(stack.active_segment() == 0x999, 'wrong active segment'); - let index3 = stack.peek_at(3).unwrap(); - assert(index3 == 1, 'post-swap: wrong index3'); - let index2 = stack.peek_at(2).unwrap(); - assert(index2 == 4, 'post-swap: wrong index2'); - let index1 = stack.peek_at(1).unwrap(); - assert(index1 == 3, 'post-swap: wrong index1'); - let index0 = stack.peek_at(0).unwrap(); - assert(index0 == 2, 'post-swap: wrong index0'); - } - - #[test] - #[available_gas(500000)] fn test_should_return_err_when_index_1_is_underflow() { // Given let mut stack = StackTrait::new(); @@ -482,24 +282,6 @@ mod swap { } #[test] - #[available_gas(500000)] - fn test_should_return_err_when_index_1_is_underflow_with_active_segment() { - // Given - let mut stack = StackTrait::new(); - stack.set_active_segment(0xabde1); - - // When & Then - let result = stack.swap_i(1); - - assert(result.is_err(), 'should return an EVMError'); - assert( - result.unwrap_err() == EVMError::StackError(STACK_UNDERFLOW), - 'should return StackUnderflow' - ); - } - - #[test] - #[available_gas(6000000)] fn test_should_return_err_when_index_2_is_underflow() { // Given let mut stack = StackTrait::new(); diff --git a/crates/evm/src/tests/test_state.cairo b/crates/evm/src/tests/test_state.cairo index b8952a0c5..44b33da71 100644 --- a/crates/evm/src/tests/test_state.cairo +++ b/crates/evm/src/tests/test_state.cairo @@ -36,7 +36,6 @@ mod test_state_changelog { use utils::traits::StorageBaseAddressIntoFelt252; #[test] - #[available_gas(200000000)] fn test_read_empty_log() { let mut changelog: StateChangeLog = Default::default(); let key = test_utils::storage_base_address().into(); @@ -44,150 +43,24 @@ mod test_state_changelog { } #[test] - #[available_gas(200000000)] fn test_write_read() { let mut changelog: StateChangeLog = Default::default(); let key = test_utils::storage_base_address().into(); changelog.write(key, 42); assert(changelog.read(key).unwrap() == 42, 'value not stored correctly'); - assert(changelog.contextual_keyset.len() == 1, 'should add a key to tracking'); + assert(changelog.keyset.len() == 1, 'should add a key to tracking'); changelog.write(key, 43); assert(changelog.read(key).unwrap() == 43, 'value should have been updated'); - assert(changelog.contextual_keyset.len() == 1, 'keys should not be added twice'); + assert(changelog.keyset.len() == 1, 'keys should not be added twice'); // Write multiple keys let second_key = 'second_location'; changelog.write(second_key, 1337.into()); assert(changelog.read(second_key).unwrap() == 1337, 'wrong second value'); - assert(changelog.contextual_keyset.len() == 2, 'should have two keys'); - - // Verify that there was no impact on global changes - assert(changelog.transactional_keyset.len() == 0, 'shouldnt impact global changes'); - } - - #[test] - #[available_gas(200000000)] - fn test_commit_context() { - let mut changelog: StateChangeLog = Default::default(); - let key = test_utils::storage_base_address().into(); - changelog.write(key, 42.into()); - changelog.commit_context(); - - assert(changelog.transactional_keyset.len() == 1, 'keys should be finalized'); - assert(changelog.contextual_keyset.len() == 0, 'local keys should be reset'); - assert(changelog.read(key).unwrap() == 42, 'read should return 42'); - - let second_address = 'second_address'; - changelog.write(key, 44.into()); - changelog.write(second_address, 1337.into()); - - changelog.commit_context(); - assert(changelog.transactional_keyset.len() == 2, 'keys should be finalized'); - assert(changelog.contextual_keyset.len() == 0, 'local keys should be reset'); - assert(changelog.read(key).unwrap() == 44, 'read should return 44'); - assert(changelog.read(second_address).unwrap() == 1337, 'read should return 1337'); - } - - #[test] - #[available_gas(200000000)] - fn test_commit_empty_context() { - let mut changelog: StateChangeLog = Default::default(); - changelog.commit_context(); - assert(changelog.transactional_keyset.len() == 0, 'shouldnt have keys'); - } - - #[test] - #[available_gas(200000000)] - fn test_clear_contextual_changes() { - let mut changelog: StateChangeLog = Default::default(); - let key = test_utils::storage_base_address().into(); - changelog.write(key, 42); - changelog.clear_context(); - assert(changelog.contextual_keyset.len() == 0, 'context should be cleared'); - assert(changelog.read(key).is_none(), 'should return None'); - } - - #[test] - #[available_gas(200000000)] - fn test_contextual_changes_override_transactional() { - let mut changelog: StateChangeLog = Default::default(); - let key = test_utils::storage_base_address().into(); - changelog.write(key, 42.into()); - changelog.commit_context(); - changelog.write(key, 43.into()); - assert(changelog.read(key).unwrap() == 43, 'contextual not overriding'); - } - - #[test] - #[available_gas(200000000)] - fn test_clear_context_does_not_affect_transactional() { - let mut changelog: StateChangeLog = Default::default(); - let key = test_utils::storage_base_address().into(); - changelog.write(key, 42.into()); - changelog.commit_context(); - changelog.clear_context(); - assert(changelog.transactional_keyset.len() == 1, 'transactional changes affected'); - assert(changelog.read(key).unwrap() == 42, 'tx value should remain'); - } -} - -mod test_simple_log { - use evm::state::{SimpleLog, SimpleLogTrait}; - - #[test] - #[available_gas(200000000)] - fn test_append_to_contextual_logs() { - let mut log: SimpleLog = Default::default(); - log.append(42); - - assert(log.contextual_logs.len() == 1, 'wrong len'); - assert(*log.contextual_logs[0] == 42, 'wrong value'); - } - - #[test] - #[available_gas(200000000)] - fn test_commit_empty_context() { - let mut log: SimpleLog = Default::default(); - log.commit_context(); - - assert(log.transactional_logs.len() == 0, 'tx logs should be empty'); - } - - #[test] - #[available_gas(200000000)] - fn test_clear_contextual_logs() { - let mut log: SimpleLog = Default::default(); - log.append(42); - log.clear_context(); - - assert(log.contextual_logs.len() == 0, 'ctx logs should be cleared'); - } - - #[test] - #[available_gas(200000000)] - fn test_contextual_logs_override_transactional() { - let mut log: SimpleLog = Default::default(); - log.append(42); - log.commit_context(); - log.append(43); - log.commit_context(); - - assert(*log.transactional_logs[1] == 43, 'tx log value not 43'); - } - - #[test] - #[available_gas(200000000)] - fn test_clear_context_does_not_affect_transactional() { - let mut log: SimpleLog = Default::default(); - log.append(42); - log.commit_context(); - log.clear_context(); - - assert(log.transactional_logs.len() == 1, 'tx logs affected by clear'); - assert(*log.transactional_logs[0] == 42, 'tx log value not 42'); + assert(changelog.keyset.len() == 2, 'should have two keys'); } } @@ -207,7 +80,6 @@ mod test_state { use utils::helpers::compute_starknet_address; #[test] - #[available_gas(200000000)] fn test_get_account_when_not_present() { let mut state: State = Default::default(); // Transfer native tokens to sender @@ -231,12 +103,11 @@ mod test_state { let account = state.get_account(evm_address); assert(account == expected_account, 'Account mismatch'); - assert(state.accounts.contextual_keyset.len() == 1, 'Account not written in context'); + assert(state.accounts.keyset.len() == 1, 'Account not written in context'); } #[test] - #[available_gas(200000000)] fn test_get_account_when_present() { let mut state: State = Default::default(); let deployer = test_utils::kakarot_address(); @@ -260,12 +131,12 @@ mod test_state { let account = state.get_account(evm_address); assert(account == expected_account, 'Account mismatch'); - assert(state.accounts.contextual_keyset.len() == 1, 'Account not written in context'); + assert(state.accounts.keyset.len() == 1, 'Account not written in context'); } #[test] - #[available_gas(200000000)] + #[ignore] fn test_get_account_when_deployed() { let mut state: State = Default::default(); let (native_token, kakarot_core) = contract_utils::setup_contracts_for_testing(); @@ -289,11 +160,10 @@ mod test_state { let account = state.get_account(evm_address); assert(account == expected_account, 'Account mismatch'); - assert(state.accounts.contextual_keyset.len() == 1, 'Account not written in context'); + assert(state.accounts.keyset.len() == 1, 'Account not written in context'); } #[test] - #[available_gas(200000000)] fn test_write_read_cached_storage() { let mut state: State = Default::default(); let evm_address: EthAddress = test_utils::evm_address(); @@ -307,7 +177,6 @@ mod test_state { } #[test] - #[available_gas(200000000)] fn test_read_state_from_sn_storage() { // Transfer native tokens to sender contract_utils::setup_contracts_for_testing(); @@ -333,19 +202,17 @@ mod test_state { } #[test] - #[available_gas(200000000)] fn test_add_event() { let mut state: State = Default::default(); let event = Event { keys: array![100, 200], data: array![0xab, 0xde] }; state.add_event(event.clone()); - assert(state.events.contextual_logs.len() == 1, 'Event not added'); - assert(state.events.contextual_logs[0].clone() == event, 'Event mismatch'); + assert(state.events.len() == 1, 'Event not added'); + assert(state.events[0].clone() == event, 'Event mismatch'); } #[test] - #[available_gas(200000000)] fn test_add_transfer() { //Given let mut state: State = Default::default(); @@ -373,8 +240,8 @@ mod test_state { state.add_transfer(transfer).unwrap(); // Then, transfer appended to log and cached balances updated - assert(state.transfers.contextual_logs.len() == 1, 'Transfer not added'); - assert(*state.transfers.contextual_logs[0] == transfer, 'Transfer mismatch'); + assert(state.transfers.len() == 1, 'Transfer not added'); + assert(*state.transfers[0] == transfer, 'Transfer mismatch'); assert(state.get_account(sender_address.evm).balance() == 200, 'Sender balance mismatch'); assert( @@ -383,7 +250,6 @@ mod test_state { } #[test] - #[available_gas(200000000)] fn test_add_transfer_with_same_sender_and_recipient() { //Given let mut state: State = Default::default(); @@ -406,13 +272,12 @@ mod test_state { state.add_transfer(transfer).unwrap(); // Then, no transfer appended to log and cached balances updated - assert(state.transfers.contextual_logs.len() == 0, 'Transfer added'); + assert(state.transfers.len() == 0, 'Transfer added'); assert(state.get_account(sender_address.evm).balance() == 300, 'Sender balance mismatch'); } #[test] - #[available_gas(200000000)] fn test_add_transfer_when_amount_is_zero() { //Given let mut state: State = Default::default(); @@ -442,7 +307,7 @@ mod test_state { state.add_transfer(transfer).unwrap(); // Then, no transfer appended to log and cached balances updated - assert(state.transfers.contextual_logs.len() == 0, 'Transfer added'); + assert(state.transfers.len() == 0, 'Transfer added'); assert(state.get_account(sender_address.evm).balance() == 300, 'Sender balance mismatch'); assert( @@ -451,7 +316,6 @@ mod test_state { } #[test] - #[available_gas(200000000)] fn test_read_balance_cached() { let mut state: State = Default::default(); contract_utils::setup_contracts_for_testing(); @@ -472,7 +336,6 @@ mod test_state { #[test] - #[available_gas(200000000)] fn test_read_balance_from_storage() { // Transfer native tokens to sender let (native_token, kakarot_core) = contract_utils::setup_contracts_for_testing(); @@ -489,28 +352,4 @@ mod test_state { assert(read_balance == 10000, 'Balance mismatch'); } - - #[test] - #[available_gas(200000000)] - fn test_commit_and_clear_context() { - let mut state: State = Default::default(); - let evm_address: EthAddress = test_utils::evm_address(); - let key = 100; - let value = 1000; - - state.write_state(evm_address, key, value); - state.commit_context(); - - assert( - state.accounts_storage.contextual_keyset.len() == 0, 'Contextual keyset not cleared' - ); - assert(state.accounts_storage.transactional_keyset.len() == 1, 'tx keyset not updated'); - - state.clear_context(); - - assert( - state.accounts_storage.contextual_keyset.len() == 0, 'Contextual keyset not cleared' - ); - assert(state.accounts_storage.transactional_keyset.len() == 1, 'tx keyset should remain'); - } } diff --git a/crates/evm/src/tests/test_utils.cairo b/crates/evm/src/tests/test_utils.cairo index 8bee23ede..d4d580efc 100644 --- a/crates/evm/src/tests/test_utils.cairo +++ b/crates/evm/src/tests/test_utils.cairo @@ -1,12 +1,9 @@ use contracts::tests::test_utils::{deploy_contract_account}; -use evm::context::DefaultBoxExecutionContext; -use evm::context::{ - CallContext, CallContextTrait, ExecutionContext, ExecutionContextType, ExecutionContextTrait, - DefaultOptionSpanU8 -}; +use contracts::uninitialized_account::UninitializedAccount; +use core::traits::TryInto; use evm::errors::{EVMError}; -use evm::machine::{Machine, MachineBuilder, MachineTrait}; -use evm::model::{ContractAccountTrait, Address, Account, AccountType}; +use evm::model::vm::{VM, VMTrait}; +use evm::model::{Message, Environment, ContractAccountTrait, Address, Account, AccountType}; use evm::state::State; use evm::{stack::{Stack, StackTrait}, memory::{Memory, MemoryTrait}}; use nullable::{match_nullable, FromNullableResult}; @@ -14,94 +11,83 @@ use starknet::{ StorageBaseAddress, storage_base_address_from_felt252, contract_address_try_from_felt252, ContractAddress, EthAddress, deploy_syscall, get_contract_address, contract_address_const }; +use utils::constants; + +#[derive(Destruct)] +struct VMBuilder { + vm: VM +} #[generate_trait] -impl MachineBuilderTestImpl of MachineBuilderTestTrait { - fn new() -> MachineBuilder { - MachineBuilder { machine: Default::default() } +impl VMBuilderImpl of VMBuilderTrait { + fn new() -> VMBuilder { + VMBuilder { vm: Default::default() } } - fn new_with_presets() -> MachineBuilder { - let ctx = preset_execution_context(); - MachineBuilder { - machine: Machine { - current_ctx: BoxTrait::new(ctx), - ctx_count: 1, - state: Default::default(), - stack: Default::default(), - memory: Default::default(), - } - } + fn new_with_presets() -> VMBuilder { + VMBuilder { vm: preset_vm() } } - fn with_return_data(mut self: MachineBuilder, return_data: Span) -> MachineBuilder { - let mut current_ctx = self.machine.current_ctx.unbox(); - current_ctx.return_data = return_data; - self.machine.current_ctx = BoxTrait::new(current_ctx); + fn with_return_data(mut self: VMBuilder, return_data: Span) -> VMBuilder { + self.vm.set_return_data(return_data); self } - fn with_caller(mut self: MachineBuilder, address: Address) -> MachineBuilder { - let mut current_ctx = self.machine.current_ctx.unbox(); - let mut call_ctx = current_ctx.call_ctx(); - call_ctx.caller = address; - current_ctx.call_ctx = BoxTrait::new(call_ctx); - self.machine.current_ctx = BoxTrait::new(current_ctx); + fn with_caller(mut self: VMBuilder, address: Address) -> VMBuilder { + self.vm.message.caller = address; self } - fn with_calldata(mut self: MachineBuilder, calldata: Span) -> MachineBuilder { - let mut current_ctx = self.machine.current_ctx.unbox(); - let mut call_ctx = current_ctx.call_ctx(); - call_ctx.calldata = calldata; - current_ctx.call_ctx = BoxTrait::new(call_ctx); - self.machine.current_ctx = BoxTrait::new(current_ctx); + fn with_calldata(mut self: VMBuilder, calldata: Span) -> VMBuilder { + self.vm.message.data = calldata; self } - fn with_read_only(mut self: MachineBuilder) -> MachineBuilder { - let mut current_ctx = self.machine.current_ctx.unbox(); - let mut call_ctx = current_ctx.call_ctx(); - call_ctx.read_only = true; - current_ctx.call_ctx = BoxTrait::new(call_ctx); - self.machine.current_ctx = BoxTrait::new(current_ctx); + fn with_read_only(mut self: VMBuilder) -> VMBuilder { + self.vm.message.read_only = true; self } - fn with_bytecode(mut self: MachineBuilder, bytecode: Span) -> MachineBuilder { - let mut current_ctx = self.machine.current_ctx.unbox(); - let mut call_ctx = current_ctx.call_ctx(); - call_ctx.bytecode = bytecode; - current_ctx.call_ctx = BoxTrait::new(call_ctx); - self.machine.current_ctx = BoxTrait::new(current_ctx); + fn with_bytecode(mut self: VMBuilder, bytecode: Span) -> VMBuilder { + self.vm.message.code = bytecode; self } - fn with_nested_execution_context(mut self: MachineBuilder) -> MachineBuilder { - let current_ctx = self.machine.current_ctx.unbox(); - - // Second Execution Context - let context_id = ExecutionContextType::Call(1); - let mut child_context = preset_execution_context(); - child_context.ctx_type = context_id; - child_context.parent_ctx = NullableTrait::new(current_ctx); - let mut call_ctx = child_context.call_ctx(); - call_ctx.caller = other_address(); - child_context.call_ctx = BoxTrait::new(call_ctx); - self.machine.current_ctx = BoxTrait::new(child_context); + // fn with_nested_vm(mut self: VMBuilder) -> VMBuilder { + // let current_ctx = self.machine.current_ctx.unbox(); + + // // Second Execution Context + // let context_id = ExecutionContextType::Call(1); + // let mut child_context = preset_message(); + // child_context.ctx_type = context_id; + // child_context.parent_ctx = NullableTrait::new(current_ctx); + // let mut call_ctx = child_context.call_ctx(); + // call_ctx.caller = other_address(); + // child_context.call_ctx = BoxTrait::new(call_ctx); + // self.machine.current_ctx = BoxTrait::new(child_context); + // self + // } + + fn with_target(mut self: VMBuilder, target: Address) -> VMBuilder { + self.vm.message.target = target; self } - fn with_target(mut self: MachineBuilder, target: Address) -> MachineBuilder { - let mut current_ctx = self.machine.current_ctx.unbox(); - current_ctx.address = target; - self.machine.current_ctx = BoxTrait::new(current_ctx); - self + fn build(self: VMBuilder) -> VM { + return self.vm; } +} - fn build(self: MachineBuilder) -> Machine { - return self.machine; - } +fn origin() -> EthAddress { + 'origin'.try_into().unwrap() +} + +fn caller() -> EthAddress { + 'caller'.try_into().unwrap() +} + +fn coinbase() -> EthAddress { + 'coinbase'.try_into().unwrap() } fn starknet_address() -> ContractAddress { @@ -162,7 +148,7 @@ fn eoa_address() -> EthAddress { evm_address } -fn gas_limit() -> u128 { +fn tx_gas_limit() -> u128 { 0x100000000000000000 } @@ -179,78 +165,98 @@ fn ca_address() -> EthAddress { evm_address } -fn setup_call_context() -> CallContext { - let bytecode: Span = array![0x00].span(); - let calldata: Span = array![4, 5, 6].span(); +fn preset_message() -> Message { + let code: Span = array![0x00].span(); + let data: Span = array![4, 5, 6].span(); let value: u256 = callvalue(); - let caller = test_address(); + let caller = Address { + evm: origin(), + starknet: utils::helpers::compute_starknet_address( + get_contract_address(), + origin(), + UninitializedAccount::TEST_CLASS_HASH.try_into().unwrap() + ) + }; let read_only = false; - let gas_price = gas_price(); - let gas_limit = gas_limit(); - let output_offset = 0; - let output_size = 0; + let tx_gas_limit = tx_gas_limit(); + let target = test_address(); - CallContextTrait::new( + Message { + target, caller, - bytecode, - calldata, + data, value, + gas_limit: tx_gas_limit, read_only, - gas_limit, - gas_price, - output_offset, - output_size, - ) -} - -fn preset_execution_context() -> ExecutionContext { - let context_id = ExecutionContextType::Root(false); - let call_ctx = setup_call_context(); - let address = test_address(); - let return_data = array![1, 2, 3].span(); - - ExecutionContextTrait::new(context_id, address, call_ctx, Default::default(), return_data,) + code, + should_transfer_value: true, + depth: 0, + } } -impl CallContextPartialEq of PartialEq { - fn eq(lhs: @CallContext, rhs: @CallContext) -> bool { - lhs.bytecode() == rhs.bytecode() && lhs.calldata == rhs.calldata && lhs.value == rhs.value - } - fn ne(lhs: @CallContext, rhs: @CallContext) -> bool { - !(lhs == rhs) +fn preset_environment() -> Environment { + let block_info = starknet::get_block_info().unbox(); + Environment { + origin: origin(), + gas_price: gas_price(), + chain_id: chain_id(), + prevrandao: 0, + block_number: block_info.block_number, + block_timestamp: block_info.block_timestamp, + block_gas_limit: constants::BLOCK_GAS_LIMIT, + coinbase: coinbase(), + state: Default::default(), } } -// Simulate return of subcontext where -/// 1. Set `return_data` field of parent context -/// 2. make `parent_ctx` of `current_ctx` the current ctx -fn return_from_subcontext(ref self: Machine, return_data: Span) { - let current_ctx = self.current_ctx.unbox(); - let mut parent_ctx = current_ctx.parent_ctx.deref(); - parent_ctx.return_data = return_data; - self.current_ctx = BoxTrait::new(parent_ctx); +fn preset_vm() -> VM { + let message = preset_message(); + let environment = preset_environment(); + let return_data = array![1, 2, 3].span(); + VM { + stack: Default::default(), + memory: Default::default(), + pc: 0, + valid_jumpdests: Default::default().span(), + return_data, + env: environment, + message, + gas_used: 0, + running: true, + error: false + } } -/// Returns the `return_data` field of the parent_ctx of the current_ctx. -fn parent_ctx_return_data(ref self: Machine) -> Span { - let mut current_ctx = self.current_ctx.unbox(); - let maybe_parent_ctx = current_ctx.parent_ctx; - let value = match match_nullable(maybe_parent_ctx) { - // Due to ownership mechanism, both branches need to explicitly re-bind the parent_ctx. - FromNullableResult::Null => { - current_ctx.parent_ctx = Default::default(); - Default::default().span() - }, - FromNullableResult::NotNull(parent_ctx) => { - let mut parent_ctx = parent_ctx.unbox(); - let value = parent_ctx.return_data(); - current_ctx.parent_ctx = NullableTrait::new(parent_ctx); - value - } - }; - self.current_ctx = BoxTrait::new(current_ctx); - value -} +// // Simulate return of subcontext where +// /// 1. Set `return_data` field of parent context +// /// 2. make `parent_ctx` of `current_ctx` the current ctx +// fn return_from_subcontext(ref self: Machine, return_data: Span) { +// let current_ctx = self.current_ctx.unbox(); +// let mut parent_ctx = current_ctx.parent_ctx.deref(); +// parent_ctx.return_data = return_data; +// self.current_ctx = BoxTrait::new(parent_ctx); +// } + +// /// Returns the `return_data` field of the parent_ctx of the current_ctx. +// fn parent_ctx_return_data(ref self: Machine) -> Span { +// let mut current_ctx = self.current_ctx.unbox(); +// let maybe_parent_ctx = current_ctx.parent_ctx; +// let value = match match_nullable(maybe_parent_ctx) { +// // Due to ownership mechanism, both branches need to explicitly re-bind the parent_ctx. +// FromNullableResult::Null => { +// current_ctx.parent_ctx = Default::default(); +// Default::default().span() +// }, +// FromNullableResult::NotNull(parent_ctx) => { +// let mut parent_ctx = parent_ctx.unbox(); +// let value = parent_ctx.return_data(); +// current_ctx.parent_ctx = NullableTrait::new(parent_ctx); +// value +// } +// }; +// self.current_ctx = BoxTrait::new(current_ctx); +// value +// } /// Initializes the contract account by setting the bytecode, the storage /// and incrementing the nonce to 1. diff --git a/crates/utils/src/constants.cairo b/crates/utils/src/constants.cairo index 82c320bca..2f541bf92 100644 --- a/crates/utils/src/constants.cairo +++ b/crates/utils/src/constants.cairo @@ -8,6 +8,8 @@ const CONTRACT_ADDRESS_PREFIX: felt252 = 'STARKNET_CONTRACT_ADDRESS'; // BLOCK +//TODO(gas): determine correct block gas limit +const BLOCK_GAS_LIMIT: u128 = 30_000_000; // CHAIN_ID = KKRT (0x4b4b5254) in ASCII const CHAIN_ID: u256 = 1263227476; diff --git a/crates/utils/src/tests/test_address.cairo b/crates/utils/src/tests/test_address.cairo index 231bace53..bf786bdff 100644 --- a/crates/utils/src/tests/test_address.cairo +++ b/crates/utils/src/tests/test_address.cairo @@ -13,17 +13,6 @@ fn test_compute_create2_contract_address() { let address = compute_create2_contract_address(from, salt, bytecode) .expect('create2_contract_address fail'); - // TODO - // add SNJS script for: - // import { getContractAddress } from 'viem' - // const address = getContractAddress({ - // bytecode: '0x608060405234801561000f575f80fd5b506004361061004a575f3560e01c806306661abd1461004e578063371303c01461006c5780636d4ce63c14610076578063b3bcfa8214610094575b5f80fd5b61005661009e565b60405161006391906100f7565b60405180910390f35b6100746100a3565b005b61007e6100bd565b60405161008b91906100f7565b60405180910390f35b61009c6100c5565b005b5f5481565b60015f808282546100b4919061013d565b92505081905550565b5f8054905090565b60015f808282546100d69190610170565b92505081905550565b5f819050919050565b6100f1816100df565b82525050565b5f60208201905061010a5f8301846100e8565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610147826100df565b9150610152836100df565b925082820190508082111561016a57610169610110565b5b92915050565b5f61017a826100df565b9150610185836100df565b925082820390508181111561019d5761019c610110565b5b9291505056fea26469706673582212207e792fcff28a4bf0bad8675c5bc2288b07835aebaa90b8dc5e0df19183fb72cf64736f6c63430008160033', - // from: '0xF39FD6E51AAD88F6F4CE6AB8827279CFFFB92266', - // opcode: 'CREATE2', - // salt: '0xbeef', - // }); - - // console.log(address) assert( address == 0x088a44D7CdD8DEA4d1Db6E3F4059c70c405a0C97 .try_into() diff --git a/crates/utils/src/tests/test_data.cairo b/crates/utils/src/tests/test_data.cairo index 01bf050b8..7574740e9 100644 --- a/crates/utils/src/tests/test_data.cairo +++ b/crates/utils/src/tests/test_data.cairo @@ -66,7 +66,7 @@ fn legacy_rlp_encoded_tx() -> Span { fn eip_2930_encoded_tx() -> Span { - // tx_format (EIP-2930, unsiged): 0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList]) + // tx_format (EIP-2930, unsigned): 0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList]) // expected rlp decoding: [ "0x434841494e5f4944", "0x", "0x3b9aca00", "0x1e8480", "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984", "0x016345785d8a0000", "0xabcdef", [] ] // message_hash: 0xc0227f45fccb86cd5befdffc546c193361174fdf0a08443a874c854e62f60981 // chain id used: 0x434841494e5f4944 @@ -132,7 +132,7 @@ fn eip_2930_encoded_tx() -> Span { } fn eip_1559_encoded_tx() -> Span { - // tx_format (EIP-1559, unsiged): 0x02 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list]) + // tx_format (EIP-1559, unsigned): 0x02 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list]) // expected rlp decoding: [ "0x434841494e5f4944", "0x", "0x", "0x3b9aca00", "0x1e8480", "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984", "0x016345785d8a0000", "0xabcdef", [] ] // message_hash: 0xe14268e90788a8e63d8db7f6996dc71dbd9b8ce1314bc9e657735c66137615cc // chain id used: 0x434841494e5f4944 diff --git a/crates/utils/src/tests/test_eth_transaction.cairo b/crates/utils/src/tests/test_eth_transaction.cairo index 33df07f8e..ef8066716 100644 --- a/crates/utils/src/tests/test_eth_transaction.cairo +++ b/crates/utils/src/tests/test_eth_transaction.cairo @@ -40,7 +40,7 @@ fn test_decode_legacy_tx() { #[test] fn test_decode_eip_2930_tx() { - // tx_format (EIP-2930, unsiged): 0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList]) + // tx_format (EIP-2930, unsigned): 0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList]) // expected rlp decoding: [ "0x434841494e5f4944", "0x", "0x3b9aca00", "0x1e8480", "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984", "0x016345785d8a0000", "0xabcdef", [] ] // message_hash: 0xc0227f45fccb86cd5befdffc546c193361174fdf0a08443a874c854e62f60981 // chain id used: 0x434841494e5f4944 @@ -69,7 +69,7 @@ fn test_decode_eip_2930_tx() { #[test] fn test_decode_eip_1559_tx() { - // tx_format (EIP-1559, unsiged): 0x02 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list]) + // tx_format (EIP-1559, unsigned): 0x02 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list]) // expected rlp decoding: [ "0x434841494e5f4944", "0x", "0x", "0x3b9aca00", "0x1e8480", "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984", "0x016345785d8a0000", "0xabcdef", [] ] // message_hash: 0xe14268e90788a8e63d8db7f6996dc71dbd9b8ce1314bc9e657735c66137615cc // chain id used: 0x434841494e5f4944 diff --git a/crates/utils/src/tests/test_helpers.cairo b/crates/utils/src/tests/test_helpers.cairo index d70a738ab..fa5a7e987 100644 --- a/crates/utils/src/tests/test_helpers.cairo +++ b/crates/utils/src/tests/test_helpers.cairo @@ -443,7 +443,6 @@ fn test_span_u8_to_64_words_full() { } #[test] -#[available_gas(2000000000)] fn test_eth_signature_to_felt252_array() { let signature_1 = Signature { r: 0x3e1d21af857363cb69f565cf5a791b6e326186250815570c80bd2b7f465802f8, @@ -481,7 +480,6 @@ fn test_eth_signature_to_felt252_array() { } #[test] -#[available_gas(2000000000)] fn test_felt252_array_to_eth_signature() { let signature_1 = Signature { r: 0x3e1d21af857363cb69f565cf5a791b6e326186250815570c80bd2b7f465802f8, diff --git a/crates/utils/src/tests/test_math.cairo b/crates/utils/src/tests/test_math.cairo index 0ac90fbcd..c18669f31 100644 --- a/crates/utils/src/tests/test_math.cairo +++ b/crates/utils/src/tests/test_math.cairo @@ -25,8 +25,8 @@ fn test_pow() { } #[test] +#[available_gas(2000000)] #[should_panic(expected: ('Out of gas',))] -#[available_gas(20000000)] fn test_wrapping_slow_pow_runs_out_of_gas() { let exp = internal_wrapping_pow_u256::wrapping_fpow(3_u256, 10); internal_wrapping_pow_u256::wrapping_spow(3_u256, exp); @@ -45,7 +45,6 @@ fn test_wrapping_fast_pow() { #[test] #[should_panic(expected: ('u256_mul Overflow',))] -#[available_gas(20000000)] fn test_pow_should_overflow() { 2_u256.pow(256); } diff --git a/crates/utils/src/traits.cairo b/crates/utils/src/traits.cairo index e10198c22..8f7e25e98 100644 --- a/crates/utils/src/traits.cairo +++ b/crates/utils/src/traits.cairo @@ -6,6 +6,33 @@ use starknet::{ }; use utils::math::{Zero, One, Bitshift}; +mod display_felt252_based { + use core::fmt::{Display, Formatter, Error}; + use core::to_byte_array::AppendFormattedToByteArray; + impl TDisplay, +Copy> of Display { + fn fmt(self: @T, ref f: Formatter) -> Result<(), Error> { + let value: felt252 = (*self).into(); + let base: felt252 = 10_u8.into(); + value.append_formatted_to_byte_array(ref f.buffer, base.try_into().unwrap()); + Result::Ok(()) + } + } +} + +mod debug_display_based { + use core::fmt::{Display, Debug, Formatter, Error}; + use core::to_byte_array::AppendFormattedToByteArray; + impl TDisplay> of Debug { + fn fmt(self: @T, ref f: Formatter) -> Result<(), Error> { + Display::fmt(self, ref f) + } + } +} + +impl EthAddressDisplay = display_felt252_based::TDisplay; +impl ContractAddressDisplay = display_felt252_based::TDisplay; +impl EthAddressDebug = debug_display_based::TDisplay; +impl ContractAddressDebug = debug_display_based::TDisplay; impl SpanDefault> of Default> { #[inline(always)]