diff --git a/cmd/ef_tests/levm/deserialize.rs b/cmd/ef_tests/levm/deserialize.rs index b81f4208b..a733797ff 100644 --- a/cmd/ef_tests/levm/deserialize.rs +++ b/cmd/ef_tests/levm/deserialize.rs @@ -1,11 +1,77 @@ -use crate::types::EFTest; +use crate::types::{EFTest, TransactionExpectedException}; use bytes::Bytes; -use ethrex_core::U256; -use serde::Deserialize; +use ethrex_core::{H256, U256}; +use serde::{Deserialize, Deserializer}; use std::{collections::HashMap, str::FromStr}; use crate::types::{EFTestRawTransaction, EFTestTransaction}; +pub fn deserialize_transaction_expected_exception<'de, D>( + deserializer: D, +) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + let option: Option = Option::deserialize(deserializer)?; + + if let Some(value) = option { + let exceptions = value + .split('|') + .map(|s| match s.trim() { + "TransactionException.INITCODE_SIZE_EXCEEDED" => { + TransactionExpectedException::InitcodeSizeExceeded + } + "TransactionException.NONCE_IS_MAX" => TransactionExpectedException::NonceIsMax, + "TransactionException.TYPE_3_TX_BLOB_COUNT_EXCEEDED" => { + TransactionExpectedException::Type3TxBlobCountExceeded + } + "TransactionException.TYPE_3_TX_ZERO_BLOBS" => { + TransactionExpectedException::Type3TxZeroBlobs + } + "TransactionException.TYPE_3_TX_CONTRACT_CREATION" => { + TransactionExpectedException::Type3TxContractCreation + } + "TransactionException.TYPE_3_TX_INVALID_BLOB_VERSIONED_HASH" => { + TransactionExpectedException::Type3TxInvalidBlobVersionedHash + } + "TransactionException.INTRINSIC_GAS_TOO_LOW" => { + TransactionExpectedException::IntrinsicGasTooLow + } + "TransactionException.INSUFFICIENT_ACCOUNT_FUNDS" => { + TransactionExpectedException::InsufficientAccountFunds + } + "TransactionException.SENDER_NOT_EOA" => TransactionExpectedException::SenderNotEoa, + "TransactionException.PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS" => { + TransactionExpectedException::PriorityGreaterThanMaxFeePerGas + } + "TransactionException.GAS_ALLOWANCE_EXCEEDED" => { + TransactionExpectedException::GasAllowanceExceeded + } + "TransactionException.INSUFFICIENT_MAX_FEE_PER_GAS" => { + TransactionExpectedException::InsufficientMaxFeePerGas + } + "TransactionException.RLP_INVALID_VALUE" => { + TransactionExpectedException::RlpInvalidValue + } + "TransactionException.GASLIMIT_PRICE_PRODUCT_OVERFLOW" => { + TransactionExpectedException::GasLimitPriceProductOverflow + } + "TransactionException.TYPE_3_TX_PRE_FORK" => { + TransactionExpectedException::Type3TxPreFork + } + "TransactionException.INSUFFICIENT_MAX_FEE_PER_BLOB_GAS" => { + TransactionExpectedException::InsufficientMaxFeePerBlobGas + } + other => panic!("Unexpected error type: {}", other), // Should not fail, TODO is to return an error + }) + .collect(); + + Ok(Some(exceptions)) + } else { + Ok(None) + } +} + pub fn deserialize_ef_post_value_indexes<'de, D>( deserializer: D, ) -> Result, D::Error> @@ -52,6 +118,29 @@ where Ok(ret) } +pub fn deserialize_h256_vec_optional_safe<'de, D>( + deserializer: D, +) -> Result>, D::Error> +where + D: serde::Deserializer<'de>, +{ + let s = Option::>::deserialize(deserializer)?; + match s { + Some(s) => { + let mut ret = Vec::new(); + for s in s { + ret.push(H256::from_str(s.trim_start_matches("0x")).map_err(|err| { + serde::de::Error::custom(format!( + "error parsing H256 when deserializing H256 vec optional: {err}" + )) + })?); + } + Ok(Some(ret)) + } + None => Ok(None), + } +} + pub fn deserialize_u256_safe<'de, D>(deserializer: D) -> Result where D: serde::Deserializer<'de>, @@ -165,6 +254,10 @@ impl<'de> Deserialize<'de> for EFTest { sender: raw_tx.sender, to: raw_tx.to.clone(), value: *value, + max_fee_per_gas: raw_tx.max_fee_per_gas, + max_priority_fee_per_gas: raw_tx.max_priority_fee_per_gas, + max_fee_per_blob_gas: raw_tx.max_fee_per_blob_gas, + blob_versioned_hashes: raw_tx.blob_versioned_hashes.clone(), }; transactions.push(((data_id, gas_limit_id, value_id), tx)); } diff --git a/cmd/ef_tests/levm/runner.rs b/cmd/ef_tests/levm/runner.rs index d3b4eaa95..260a606b7 100644 --- a/cmd/ef_tests/levm/runner.rs +++ b/cmd/ef_tests/levm/runner.rs @@ -1,4 +1,8 @@ -use crate::{report::EFTestsReport, types::EFTest, utils}; +use crate::{ + report::EFTestsReport, + types::{EFTest, EFTestPostValue, TransactionExpectedException}, + utils, +}; use ethrex_core::{ types::{code_hash, AccountInfo}, H256, U256, @@ -32,14 +36,21 @@ pub fn run_ef_tests() -> Result> { }) { // TODO: Figure out what to do with overflowed value: 0x10000000000000000000000000000000000000000000000000000000000000001. - // Deserialization fails because the value is too big for U256. + // Deserialization of ValueOverflowParis fails because the value is too big for U256. + // Intrinsic is skipped because execution fails as access lists are not yet implemented. if test .path() .file_name() - .is_some_and(|name| name == "ValueOverflowParis.json") + .is_some_and(|name| name == "ValueOverflowParis.json" || name == "intrinsic.json") { continue; } + // 'If' for running a specific test when necessary. + // if test + // .path() + // .file_name() + // .is_some_and(|name| name == "valCausesOOF.json") + // { let test_result = run_ef_test( serde_json::from_reader(std::fs::File::open(test.path())?)?, &mut report, @@ -47,6 +58,7 @@ pub fn run_ef_tests() -> Result> { if test_result.is_err() { continue; } + // } } spinner.update_text(report.progress()); } @@ -64,13 +76,18 @@ pub fn run_ef_test_tx( let mut evm = prepare_vm_for_tx(tx_id, test)?; ensure_pre_state(&evm, test)?; let execution_result = evm.transact(); - ensure_post_state(execution_result, test, report)?; + ensure_post_state(execution_result, test, report, tx_id)?; Ok(()) } pub fn run_ef_test(test: EFTest, report: &mut EFTestsReport) -> Result<(), Box> { + println!("Running test: {}", &test.name); let mut failed = false; for (tx_id, (tx_indexes, _tx)) in test.transactions.iter().enumerate() { + // Code for debugging a specific case. + // if *tx_indexes != (346, 0, 0) { + // continue; + // } match run_ef_test_tx(tx_id, &test, report) { Ok(_) => {} Err(e) => { @@ -100,7 +117,7 @@ pub fn prepare_vm_for_tx(tx_id: usize, test: &EFTest) -> Result Result Result<( Ok(()) } +fn get_indexes_tuple(post_value: &EFTestPostValue) -> Option<(usize, usize, usize)> { + let data_index: usize = post_value.indexes.get("data")?.as_usize(); + let gas_index: usize = post_value.indexes.get("gas")?.as_usize(); + let value_index: usize = post_value.indexes.get("value")?.as_usize(); + Some((data_index, gas_index, value_index)) +} + +fn get_post_value(test: &EFTest, tx_id: usize) -> Option { + if let Some(transaction) = test.transactions.get(tx_id) { + let indexes = transaction.0; + test.post + .clone() + .iter() + .find(|post_value| { + if let Some(post_indexes) = get_indexes_tuple(post_value) { + indexes == post_indexes + } else { + false + } + }) + .cloned() + } else { + None + } +} + +// Exceptions not covered: RlpInvalidValue and Type3TxPreFork +fn exception_is_expected( + expected_exceptions: Vec, + returned_error: VMError, +) -> bool { + expected_exceptions.iter().any(|exception| { + matches!( + (exception, &returned_error), + ( + TransactionExpectedException::IntrinsicGasTooLow, + VMError::IntrinsicGasTooLow + ) | ( + TransactionExpectedException::InsufficientAccountFunds, + VMError::InsufficientAccountFunds + ) | ( + TransactionExpectedException::PriorityGreaterThanMaxFeePerGas, + VMError::PriorityGreaterThanMaxFeePerGas + ) | ( + TransactionExpectedException::GasLimitPriceProductOverflow, + VMError::GasLimitPriceProductOverflow + ) | ( + TransactionExpectedException::SenderNotEoa, + VMError::SenderNotEOA + ) | ( + TransactionExpectedException::InsufficientMaxFeePerGas, + VMError::InsufficientMaxFeePerGas + ) | ( + TransactionExpectedException::NonceIsMax, + VMError::NonceIsMax + ) | ( + TransactionExpectedException::GasAllowanceExceeded, + VMError::GasAllowanceExceeded + ) | ( + TransactionExpectedException::Type3TxBlobCountExceeded, + VMError::Type3TxBlobCountExceeded + ) | ( + TransactionExpectedException::Type3TxZeroBlobs, + VMError::Type3TxZeroBlobs + ) | ( + TransactionExpectedException::Type3TxContractCreation, + VMError::Type3TxContractCreation + ) | ( + TransactionExpectedException::Type3TxInvalidBlobVersionedHash, + VMError::Type3TxInvalidBlobVersionedHash + ) | ( + TransactionExpectedException::InsufficientMaxFeePerBlobGas, + VMError::InsufficientMaxFeePerBlobGas + ) | ( + TransactionExpectedException::InitcodeSizeExceeded, + VMError::InitcodeSizeExceeded + ) + ) + }) +} + pub fn ensure_post_state( execution_result: Result, test: &EFTest, report: &mut EFTestsReport, + tx_id: usize, ) -> Result<(), Box> { + let post_value = get_post_value(test, tx_id); match execution_result { Ok(execution_report) => { - match test - .post - .clone() - .values() - .first() - .map(|v| v.clone().expect_exception) - { + match post_value.clone().map(|v| v.clone().expect_exception) { // Execution result was successful but an exception was expected. - Some(Some(expected_exception)) => { - let error_reason = format!("Expected exception: {expected_exception}"); + Some(Some(expected_exceptions)) => { + let error_reason = match expected_exceptions.get(1) { + Some(second_exception) => { + format!( + "Expected exception: {:?} or {:?}", + expected_exceptions.first().unwrap(), + second_exception + ) + } + None => { + format!( + "Expected exception: {:?}", + expected_exceptions.first().unwrap() + ) + } + }; + return Err(format!("Post-state condition failed: {error_reason}").into()); } // Execution result was successful and no exception was expected. - // TODO: Check that the post-state matches the expected post-state. None | Some(None) => { let pos_state_root = post_state_root(execution_report, test); - let expected_post_state_value = test.post.iter().next().cloned(); - if let Some(expected_post_state_root_hash) = expected_post_state_value { + if let Some(expected_post_state_root_hash) = post_value { let expected_post_state_root_hash = expected_post_state_root_hash.hash; if expected_post_state_root_hash != pos_state_root { let error_reason = format!( @@ -226,16 +348,31 @@ pub fn ensure_post_state( } } Err(err) => { - match test - .post - .clone() - .values() - .first() - .map(|v| v.clone().expect_exception) - { + match post_value.map(|v| v.clone().expect_exception) { // Execution result was unsuccessful and an exception was expected. - // TODO: Check that the exception matches the expected exception. - Some(Some(_expected_exception)) => {} + Some(Some(expected_exceptions)) => { + // Instead of cloning could use references + if !exception_is_expected(expected_exceptions.clone(), err.clone()) { + let error_reason = match expected_exceptions.get(1) { + Some(second_exception) => { + format!( + "Returned exception is not the expected: Returned {:?} but expected {:?} or {:?}", + err, + expected_exceptions.first().unwrap(), + second_exception + ) + } + None => { + format!( + "Returned exception is not the expected: Returned {:?} but expected {:?}", + err, + expected_exceptions.first().unwrap() + ) + } + }; + return Err(format!("Post-state condition failed: {error_reason}").into()); + } + } // Execution result was unsuccessful but no exception was expected. None | Some(None) => { let error_reason = format!("Unexpected exception: {err:?}"); diff --git a/cmd/ef_tests/levm/tests/test.rs b/cmd/ef_tests/levm/tests/test.rs index e726edb91..533272a32 100644 --- a/cmd/ef_tests/levm/tests/test.rs +++ b/cmd/ef_tests/levm/tests/test.rs @@ -1,6 +1,5 @@ use ef_tests_levm::runner; fn main() { - let report = runner::run_ef_tests().unwrap(); - println!("{report}"); + runner::run_ef_tests().unwrap(); } diff --git a/cmd/ef_tests/levm/types.rs b/cmd/ef_tests/levm/types.rs index 9721b1e60..378a870d4 100644 --- a/cmd/ef_tests/levm/types.rs +++ b/cmd/ef_tests/levm/types.rs @@ -1,5 +1,6 @@ use crate::deserialize::{ - deserialize_ef_post_value_indexes, deserialize_hex_bytes, deserialize_hex_bytes_vec, + deserialize_ef_post_value_indexes, deserialize_h256_vec_optional_safe, deserialize_hex_bytes, + deserialize_hex_bytes_vec, deserialize_transaction_expected_exception, deserialize_u256_optional_safe, deserialize_u256_safe, deserialize_u256_valued_hashmap_safe, deserialize_u256_vec_safe, }; @@ -99,10 +100,34 @@ impl EFTestPost { } } +#[derive(Debug, Deserialize, Clone)] +pub enum TransactionExpectedException { + InitcodeSizeExceeded, + NonceIsMax, + Type3TxBlobCountExceeded, + Type3TxZeroBlobs, + Type3TxContractCreation, + Type3TxInvalidBlobVersionedHash, + IntrinsicGasTooLow, + InsufficientAccountFunds, + SenderNotEoa, + PriorityGreaterThanMaxFeePerGas, + GasAllowanceExceeded, + InsufficientMaxFeePerGas, + RlpInvalidValue, + GasLimitPriceProductOverflow, + Type3TxPreFork, + InsufficientMaxFeePerBlobGas, +} + #[derive(Debug, Deserialize, Clone)] pub struct EFTestPostValue { - #[serde(rename = "expectException")] - pub expect_exception: Option, + #[serde( + rename = "expectException", + default, + deserialize_with = "deserialize_transaction_expected_exception" + )] + pub expect_exception: Option>, pub hash: H256, #[serde(deserialize_with = "deserialize_ef_post_value_indexes")] pub indexes: HashMap, @@ -161,6 +186,14 @@ pub struct EFTestRawTransaction { pub to: TxKind, #[serde(deserialize_with = "deserialize_u256_vec_safe")] pub value: Vec, + #[serde(default, deserialize_with = "deserialize_u256_optional_safe")] + pub max_fee_per_gas: Option, + #[serde(default, deserialize_with = "deserialize_u256_optional_safe")] + pub max_priority_fee_per_gas: Option, + #[serde(default, deserialize_with = "deserialize_u256_optional_safe")] + pub max_fee_per_blob_gas: Option, + #[serde(default, deserialize_with = "deserialize_h256_vec_optional_safe")] + pub blob_versioned_hashes: Option>, } #[derive(Debug, Deserialize)] @@ -176,4 +209,12 @@ pub struct EFTestTransaction { pub sender: Address, pub to: TxKind, pub value: U256, + #[serde(default, deserialize_with = "deserialize_u256_optional_safe")] + pub max_fee_per_gas: Option, + #[serde(default, deserialize_with = "deserialize_u256_optional_safe")] + pub max_priority_fee_per_gas: Option, + #[serde(default, deserialize_with = "deserialize_u256_optional_safe")] + pub max_fee_per_blob_gas: Option, + #[serde(default, deserialize_with = "deserialize_h256_vec_optional_safe")] + pub blob_versioned_hashes: Option>, } diff --git a/crates/vm/levm/bench/revm_comparison/src/lib.rs b/crates/vm/levm/bench/revm_comparison/src/lib.rs index 1a224d4bd..495e3c93d 100644 --- a/crates/vm/levm/bench/revm_comparison/src/lib.rs +++ b/crates/vm/levm/bench/revm_comparison/src/lib.rs @@ -24,15 +24,15 @@ pub fn run_with_levm(program: &str, runs: usize, number_of_iterations: u32) { *vm.current_call_frame_mut().unwrap() = call_frame.clone(); let mut current_call_frame = vm.call_frames.pop().unwrap(); let tx_report = black_box(vm.execute(&mut current_call_frame)); - assert!(tx_report.result == TxResult::Success); + assert!(tx_report.unwrap().result == TxResult::Success); } let mut vm = new_vm_with_bytecode(Bytes::new()).unwrap(); *vm.current_call_frame_mut().unwrap() = call_frame.clone(); let mut current_call_frame = vm.call_frames.pop().unwrap(); let tx_report = black_box(vm.execute(&mut current_call_frame)); - assert!(tx_report.result == TxResult::Success); + assert!(tx_report.clone().unwrap().result == TxResult::Success); - match tx_report.result { + match tx_report.unwrap().result { TxResult::Success => { println!("\t\t0x{}", hex::encode(current_call_frame.returndata)); } diff --git a/crates/vm/levm/docs/validations.md b/crates/vm/levm/docs/validations.md new file mode 100644 index 000000000..95c1ca44f --- /dev/null +++ b/crates/vm/levm/docs/validations.md @@ -0,0 +1,17 @@ +## Transaction Validation + +1. **GASLIMIT_PRICE_PRODUCT_OVERFLOW** -> The product of gas limit and gas price is too high. +2. **INSUFFICIENT_ACCOUNT_FUNDS** -> Sender does not have enough funds to pay for the gas. +3. **INSUFFICIENT_MAX_FEE_PER_GAS** -> The max fee per gas is lower than the base fee per gas. +4. **INITCODE_SIZE_EXCEEDED** -> The size of the initcode is too big. +5. **INTRINSIC_GAS_TOO_LOW** -> The gas limit is lower than the intrinsic gas. +6. **NONCE_IS_MAX** -> The nonce of the sender is at its maximum value. +7. **PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS** -> The priority fee is greater than the max fee per gas. +8. **SENDER_NOT_EOA** -> The sender is not an EOA (it has code). +9. **GAS_ALLOWANCE_EXCEEDED** -> The gas limit is higher than the block gas limit. +10. **INSUFFICIENT_MAX_FEE_PER_BLOB_GAS** -> The max fee per blob gas is lower than the base fee per gas. +11. **TYPE_3_TX_ZERO_BLOBS** -> The transaction has zero blobs. +12. **TYPE_3_TX_INVALID_BLOB_VERSIONED_HASH** -> The blob versioned hash is invalid. +13. **TYPE_3_TX_PRE_FORK** -> The transaction is a pre-cancun transaction. +14. **TYPE_3_TX_BLOB_COUNT_EXCEEDED** -> The blob count is higher than the max allowed. +15. **TYPE_3_TX_CONTRACT_CREATION** -> The type 3 transaction is a contract creation. diff --git a/crates/vm/levm/src/account.rs b/crates/vm/levm/src/account.rs index da8872a92..d29d2c627 100644 --- a/crates/vm/levm/src/account.rs +++ b/crates/vm/levm/src/account.rs @@ -58,8 +58,8 @@ impl Account { } } - pub fn has_code(&self) -> Result { - Ok(!(self.info.bytecode.is_empty() || self.bytecode_hash() == EMPTY_CODE_HASH)) + pub fn has_code(&self) -> bool { + !(self.info.bytecode.is_empty() || self.bytecode_hash() == EMPTY_CODE_HASH) } pub fn bytecode_hash(&self) -> H256 { diff --git a/crates/vm/levm/src/constants.rs b/crates/vm/levm/src/constants.rs index 6b07e6e87..0d83303a2 100644 --- a/crates/vm/levm/src/constants.rs +++ b/crates/vm/levm/src/constants.rs @@ -22,6 +22,7 @@ pub const MEMORY_EXPANSION_QUOTIENT: usize = 512; pub const TX_BASE_COST: U256 = U256([21000, 0, 0, 0]); pub const MAX_CODE_SIZE: usize = 0x6000; +pub const INIT_CODE_MAX_SIZE: usize = 49152; pub const MAX_CREATE_CODE_SIZE: usize = 2 * MAX_CODE_SIZE; pub const INVALID_CONTRACT_PREFIX: u8 = 0xef; @@ -41,7 +42,8 @@ pub const MAX_BLOB_NUMBER_PER_BLOCK: usize = 6; pub const TARGET_BLOB_GAS_PER_BLOCK: U256 = U256([393216, 0, 0, 0]); // TARGET_BLOB_NUMBER_PER_BLOCK * GAS_PER_BLOB pub const MIN_BASE_FEE_PER_BLOB_GAS: U256 = U256([1, 0, 0, 0]); pub const BLOB_BASE_FEE_UPDATE_FRACTION: U256 = U256([3338477, 0, 0, 0]); - +pub const MAX_BLOB_COUNT: usize = 6; +pub const VALID_BLOB_PREFIXES: [u8; 2] = [0x01, 0x02]; // Storage constants pub const COLD_STORAGE_ACCESS_COST: U256 = U256([2100, 0, 0, 0]); pub const WARM_ADDRESS_ACCESS_COST: U256 = U256([100, 0, 0, 0]); diff --git a/crates/vm/levm/src/db.rs b/crates/vm/levm/src/db.rs index d9abe7681..b544b378e 100644 --- a/crates/vm/levm/src/db.rs +++ b/crates/vm/levm/src/db.rs @@ -96,6 +96,10 @@ impl Cache { self.accounts.insert(*address, account.clone()); } + pub fn remove_account(&mut self, address: &Address) { + self.accounts.remove(address); + } + pub fn write_account_storage( &mut self, address: &Address, diff --git a/crates/vm/levm/src/environment.rs b/crates/vm/levm/src/environment.rs index 3e57703f2..1617f3121 100644 --- a/crates/vm/levm/src/environment.rs +++ b/crates/vm/levm/src/environment.rs @@ -1,4 +1,3 @@ -use crate::constants::TX_BASE_COST; use ethrex_core::{Address, H256, U256}; #[derive(Debug, Default, Clone)] @@ -15,17 +14,22 @@ pub struct Environment { pub prev_randao: Option, pub chain_id: U256, pub base_fee_per_gas: U256, + // It should store effective gas price, in type 2 transactions it is not defined but we calculate if with max fee per gas and max priority fee per gas. pub gas_price: U256, pub block_excess_blob_gas: Option, pub block_blob_gas_used: Option, pub tx_blob_hashes: Option>, + pub block_gas_limit: U256, + pub tx_max_priority_fee_per_gas: Option, + pub tx_max_fee_per_gas: Option, + pub tx_max_fee_per_blob_gas: Option, } impl Environment { pub fn default_from_address(origin: Address) -> Self { Self { origin, - consumed_gas: TX_BASE_COST, + consumed_gas: U256::zero(), refunded_gas: U256::default(), gas_limit: U256::MAX, block_number: Default::default(), @@ -38,6 +42,10 @@ impl Environment { block_excess_blob_gas: Default::default(), block_blob_gas_used: Default::default(), tx_blob_hashes: Default::default(), + block_gas_limit: Default::default(), + tx_max_priority_fee_per_gas: Default::default(), + tx_max_fee_per_gas: Default::default(), + tx_max_fee_per_blob_gas: Default::default(), } } } diff --git a/crates/vm/levm/src/errors.rs b/crates/vm/levm/src/errors.rs index b6bad188c..ea30f1f43 100644 --- a/crates/vm/levm/src/errors.rs +++ b/crates/vm/levm/src/errors.rs @@ -37,11 +37,11 @@ pub enum VMError { SenderAccountDoesNotExist, #[error("Address Does Not Match An Account")] AddressDoesNotMatchAnAccount, - #[error("Sender Account Should Not Have Bytecode")] - SenderAccountShouldNotHaveBytecode, - #[error("Sender Balance Should Contain Transfer Value")] - SenderBalanceShouldContainTransferValue, - #[error("Gas Price Is Lower Than Base Fee")] + #[error("Sender account should not have bytecode")] + SenderNotEOA, + #[error("Insufficient account founds")] + InsufficientAccountFunds, + #[error("Gas price is lower than base fee")] GasPriceIsLowerThanBaseFee, #[error("Address Already Occupied")] AddressAlreadyOccupied, @@ -49,7 +49,9 @@ pub enum VMError { ContractOutputTooBig, #[error("Invalid Initial Byte")] InvalidInitialByte, - #[error("Memory Load Out Of Bounds")] + #[error("Nonce is max (overflow)")] + NonceIsMax, + #[error("Memory load out of bounds")] MemoryLoadOutOfBounds, #[error("Memory Store Out Of Bounds")] MemoryStoreOutOfBounds, @@ -63,8 +65,30 @@ pub enum VMError { GasRefundsUnderflow, #[error("Gas refunds overflow")] GasRefundsOverflow, + #[error("Initcode size exceeded")] + InitcodeSizeExceeded, + #[error("Priority fee greater than max fee per gas")] + PriorityGreaterThanMaxFeePerGas, + #[error("Intrinsic gas too low")] + IntrinsicGasTooLow, + #[error("Gas allowance exceeded")] + GasAllowanceExceeded, + #[error("Insufficient max fee per gas")] + InsufficientMaxFeePerGas, + #[error("Insufficient max fee per blob gas")] + InsufficientMaxFeePerBlobGas, #[error("Memory size overflows")] MemorySizeOverflow, + #[error("Type3TxZeroBlobs")] + Type3TxZeroBlobs, + #[error("Type3TxInvalidBlobVersionedHash")] + Type3TxInvalidBlobVersionedHash, + #[error("Type3TxBlobCountExceeded")] + Type3TxBlobCountExceeded, + #[error("Type3TxContractCreation")] + Type3TxContractCreation, + #[error("Revert Create")] + RevertCreate, // OutOfGas #[error("Out Of Gas")] OutOfGas(#[from] OutOfGasError), @@ -129,6 +153,16 @@ pub enum InternalError { ExcessBlobGasShouldNotBeNone, #[error("Error in utils file")] UtilsError, + #[error("Overflow error")] + OperationOverflow, + #[error("Undefined state")] + UndefinedState(i32), // This error is temporarily for things that cause an undefined state. +} + +impl VMError { + pub fn is_internal(&self) -> bool { + matches!(self, VMError::Internal(_)) + } } #[derive(Debug, Clone)] @@ -165,9 +199,14 @@ pub struct TransactionReport { } impl TransactionReport { - /// Function to add gas to report without exceeding the maximum gas limit - pub fn add_gas_with_max(&mut self, gas: u64, max: u64) { - self.gas_used = self.gas_used.saturating_add(gas).min(max); + /// Function to add gas to report, if it exceeds max gas limit it should return OutOfGas error. Only used for adding gas after execution. + pub fn add_gas_with_max(&mut self, gas: u64, max: u64) -> Result<(), VMError> { + self.gas_used = self + .gas_used + .checked_add(gas) + .filter(|&total| total <= max) + .ok_or(VMError::OutOfGas(OutOfGasError::MaxGasLimitExceeded))?; + Ok(()) } pub fn is_success(&self) -> bool { diff --git a/crates/vm/levm/src/opcode_handlers/environment.rs b/crates/vm/levm/src/opcode_handlers/environment.rs index f0d7e02c8..1d53e4fcd 100644 --- a/crates/vm/levm/src/opcode_handlers/environment.rs +++ b/crates/vm/levm/src/opcode_handlers/environment.rs @@ -1,7 +1,7 @@ use crate::{ call_frame::CallFrame, constants::{BALANCE_COLD_ADDRESS_ACCESS_COST, WARM_ADDRESS_ACCESS_COST}, - errors::{InternalError, OpcodeSuccess, OutOfGasError, VMError}, + errors::{OpcodeSuccess, OutOfGasError, VMError}, gas_cost, vm::{word_to_address, VM}, }; @@ -239,10 +239,7 @@ impl VM { let code = if offset < bytecode_len { current_call_frame.bytecode.slice( offset - ..(offset.checked_add(size).ok_or(VMError::Internal( - InternalError::ArithmeticOperationOverflow, - ))?) - .min(bytecode_len), + ..(offset.checked_add(size).ok_or(VMError::VeryLargeNumber)?).min(bytecode_len), ) } else { vec![0u8; size].into() @@ -320,28 +317,26 @@ impl VM { let bytecode = self.get_account(&address).info.bytecode; - let new_memory_size = dest_offset.checked_add(size).ok_or(VMError::Internal( - InternalError::ArithmeticOperationOverflow, - ))?; + // If offset + size overflows usize we should return VeryLargeNumber. + let new_memory_size = dest_offset + .checked_add(size) + .ok_or(VMError::VeryLargeNumber)?; let current_memory_size = current_call_frame.memory.data.len(); if current_memory_size < new_memory_size { current_call_frame.memory.data.resize(new_memory_size, 0); } for i in 0..size { - if let Some(memory_byte) = - current_call_frame - .memory - .data - .get_mut(dest_offset.checked_add(i).ok_or(VMError::Internal( - InternalError::ArithmeticOperationOverflow, - ))?) + if let Some(memory_byte) = current_call_frame + .memory + .data + .get_mut(dest_offset.checked_add(i).ok_or(VMError::VeryLargeNumber)?) { - *memory_byte = *bytecode - .get(offset.checked_add(i).ok_or(VMError::Internal( - InternalError::ArithmeticOperationOverflow, - ))?) - .unwrap_or(&0u8); + *memory_byte = if let Some(new_offset) = offset.checked_add(i) { + *bytecode.get(new_offset).unwrap_or(&0u8) + } else { + 0u8 + }; } } @@ -398,9 +393,7 @@ impl VM { returndata_offset ..(returndata_offset .checked_add(size) - .ok_or(VMError::Internal( - InternalError::ArithmeticOperationOverflow, - ))?) + .ok_or(VMError::VeryLargeNumber)?) .min(sub_return_data_len), ) } else { diff --git a/crates/vm/levm/src/opcode_handlers/system.rs b/crates/vm/levm/src/opcode_handlers/system.rs index 1012a2e95..651d452e6 100644 --- a/crates/vm/levm/src/opcode_handlers/system.rs +++ b/crates/vm/levm/src/opcode_handlers/system.rs @@ -1,7 +1,7 @@ use crate::{ call_frame::CallFrame, constants::SUCCESS_FOR_RETURN, - errors::{InternalError, OpcodeSuccess, ResultReason, VMError}, + errors::{OpcodeSuccess, ResultReason, VMError}, gas_cost, vm::{word_to_address, VM}, }; @@ -173,12 +173,9 @@ impl VM { .try_into() .map_err(|_| VMError::VeryLargeNumber)?; - let gas_cost = - current_call_frame - .memory - .expansion_cost(offset.checked_add(size).ok_or(VMError::Internal( - InternalError::ArithmeticOperationOverflow, - ))?)?; + let gas_cost = current_call_frame + .memory + .expansion_cost(offset.checked_add(size).ok_or(VMError::VeryLargeNumber)?)?; self.increase_consumed_gas(current_call_frame, gas_cost)?; @@ -408,12 +405,9 @@ impl VM { .try_into() .map_err(|_err| VMError::VeryLargeNumber)?; - let gas_cost = - current_call_frame - .memory - .expansion_cost(offset.checked_add(size).ok_or(VMError::Internal( - InternalError::ArithmeticOperationOverflow, - ))?)?; + let gas_cost = current_call_frame + .memory + .expansion_cost(offset.checked_add(size).ok_or(VMError::VeryLargeNumber)?)?; self.increase_consumed_gas(current_call_frame, gas_cost)?; diff --git a/crates/vm/levm/src/vm.rs b/crates/vm/levm/src/vm.rs index f3041fbbf..e4a27f0ae 100644 --- a/crates/vm/levm/src/vm.rs +++ b/crates/vm/levm/src/vm.rs @@ -8,7 +8,7 @@ use crate::{ InternalError, OpcodeSuccess, OutOfGasError, ResultReason, TransactionReport, TxResult, VMError, }, - gas_cost, + gas_cost::CREATE_BASE_COST, opcodes::Opcode, }; use bytes::Bytes; @@ -99,7 +99,7 @@ impl VM { calldata.clone(), false, env.gas_limit.min(MAX_BLOCK_GAS_LIMIT), - TX_BASE_COST, + U256::zero(), 0, ); @@ -137,7 +137,7 @@ impl VM { calldata.clone(), false, env.gas_limit.min(MAX_BLOCK_GAS_LIMIT), - TX_BASE_COST, + U256::zero(), 0, ); @@ -154,7 +154,14 @@ impl VM { // TODO: https://github.com/lambdaclass/lambda_ethrex/issues/1088 } - pub fn execute(&mut self, current_call_frame: &mut CallFrame) -> TransactionReport { + /// Executes opcodes in callframe + /// Returns a TransactionReport with the result of the transaction + /// and the new state of the accounts. + /// It only returns an error if the error was internal, otherwise it will be a TransactionReport with revert status. + pub fn execute( + &mut self, + current_call_frame: &mut CallFrame, + ) -> Result { // Backup of Database, Substate and Gas Refunds if sub-context is reverted let (backup_db, backup_substate, backup_refunded_gas) = ( self.cache.clone(), @@ -163,20 +170,7 @@ impl VM { ); loop { - let opcode = match current_call_frame.next_opcode() { - Ok(opt) => opt.unwrap_or(Opcode::STOP), - Err(e) => { - return TransactionReport { - result: TxResult::Revert(e), - new_state: self.cache.accounts.clone(), - gas_used: current_call_frame.gas_used.low_u64(), - gas_refunded: self.env.refunded_gas.low_u64(), - output: current_call_frame.returndata.clone(), // Bytes::new() if error is not RevertOpcode - logs: current_call_frame.logs.clone(), - created_address: None, - }; - } - }; + let opcode = current_call_frame.next_opcode()?.unwrap_or(Opcode::STOP); // This will execute opcode stop if there are no more opcodes, there are other ways of solving this but this is the simplest and doesn't change VM behavior. // Note: This is commented because it's used for debugging purposes in development. // dbg!(¤t_call_frame.gas_used); @@ -287,7 +281,7 @@ impl VM { Ok(OpcodeSuccess::Continue) => {} Ok(OpcodeSuccess::Result(_)) => { self.call_frames.push(current_call_frame.clone()); - return TransactionReport { + return Ok(TransactionReport { result: TxResult::Success, new_state: self.cache.accounts.clone(), gas_used: current_call_frame.gas_used.low_u64(), @@ -295,11 +289,16 @@ impl VM { output: current_call_frame.returndata.clone(), logs: current_call_frame.logs.clone(), created_address: None, - }; + }); } Err(error) => { self.call_frames.push(current_call_frame.clone()); + // If error is internal then propagate it to the upper layer + if error.is_internal() { + return Err(error); + } + // Unless error is from Revert opcode, all gas is consumed if error != VMError::RevertOpcode { let left_gas = current_call_frame @@ -312,7 +311,7 @@ impl VM { self.restore_state(backup_db, backup_substate, backup_refunded_gas); - return TransactionReport { + return Ok(TransactionReport { result: TxResult::Revert(error), new_state: self.cache.accounts.clone(), gas_used: current_call_frame.gas_used.low_u64(), @@ -320,7 +319,7 @@ impl VM { output: current_call_frame.returndata.clone(), // Bytes::new() if error is not RevertOpcode logs: current_call_frame.logs.clone(), created_address: None, - }; + }); } } } @@ -337,258 +336,429 @@ impl VM { self.env.refunded_gas = backup_refunded_gas; } - // let account = self.db.accounts.get(&self.env.origin).ok_or(VMError::FatalUnwrap)?; - /// Based on Ethereum yellow paper's initial tests of intrinsic validity (Section 6). The last version is - /// Shanghai, so there are probably missing Cancun validations. The intrinsic validations are: - /// - /// (1) The transaction is well-formed RLP, with no additional trailing bytes; - /// (2) The transaction signature is valid; - /// (3) The transaction nonce is valid (equivalent to the sender account's - /// current nonce); - /// (4) The sender account has no contract code deployed (see EIP-3607). - /// (5) The gas limit is no smaller than the intrinsic gas, used by the - /// transaction; - /// (6) The sender account balance contains at least the cost, required in - /// up-front payment; - /// (7) The max fee per gas, in the case of type 2 transactions, or gasPrice, - /// in the case of type 0 and type 1 transactions, is greater than or equal to - /// the block’s base fee; - /// (8) For type 2 transactions, max priority fee per fas, must be no larger - /// than max fee per fas. - fn validate_transaction(&mut self) -> Result<(), VMError> { - // Validations (1), (2), (3), (5), and (8) are assumed done in upper layers. - - let call_frame = self - .call_frames - .last() - .ok_or(VMError::Internal( - InternalError::CouldNotAccessLastCallframe, - ))? - .clone(); + /// ## Description + /// This method performs validations and returns an error if any of the validations fail. + /// It also makes initial changes alongside the validations: + /// - It increases sender nonce + /// - It substracts up-front-cost from sender balance. + /// - It calculates and adds intrinsic gas to the 'gas used' of callframe and environment. + /// See 'docs' for more information about validations. + fn validate_transaction(&mut self, initial_call_frame: &mut CallFrame) -> Result<(), VMError> { + //TODO: This should revert the transaction, not throw an error. And I don't know if it should be done here... + // if self.is_create() { + // // If address is already in db, there's an error + // let new_address_acc = self.db.get_account_info(call_frame.to); + // if !new_address_acc.is_empty() { + // return Err(VMError::AddressAlreadyOccupied); + // } + // } + let sender_address = self.env.origin; + let mut sender_account = self.get_account(&sender_address); + + // (1) GASLIMIT_PRICE_PRODUCT_OVERFLOW + let gaslimit_price_product = self + .gas_price_or_max_fee_per_gas() + .checked_mul(self.env.gas_limit) + .ok_or(VMError::GasLimitPriceProductOverflow)?; + + // Up front cost is the maximum amount of wei that a user is willing to pay for. + let up_front_cost = gaslimit_price_product + .checked_add(initial_call_frame.msg_value) + .ok_or(VMError::InsufficientAccountFunds)?; + + // (2) INSUFFICIENT_ACCOUNT_FUNDS + sender_account.info.balance = sender_account + .info + .balance + .checked_sub(up_front_cost) + .ok_or(VMError::InsufficientAccountFunds)?; + // (3) INSUFFICIENT_MAX_FEE_PER_GAS + if self.gas_price_or_max_fee_per_gas() < self.env.base_fee_per_gas { + return Err(VMError::InsufficientMaxFeePerGas); + } + + // (4) INITCODE_SIZE_EXCEEDED if self.is_create() { - // If address is already in db, there's an error - let new_address_acc = self.db.get_account_info(call_frame.to); - if !new_address_acc.is_empty() { - return Err(VMError::AddressAlreadyOccupied); + // INITCODE_SIZE_EXCEEDED + if initial_call_frame.calldata.len() > INIT_CODE_MAX_SIZE { + return Err(VMError::InitcodeSizeExceeded); } } - let origin = self.env.origin; - - let mut sender_account = self.get_account(&origin); + // (5) INTRINSIC_GAS_TOO_LOW + self.add_intrinsic_gas(initial_call_frame)?; - // See if it's raised in upper layers + // (6) NONCE_IS_MAX sender_account.info.nonce = sender_account .info .nonce .checked_add(1) - .ok_or(VMError::Internal(InternalError::NonceOverflowed))?; - - // (4) - if sender_account.has_code()? { - return Err(VMError::SenderAccountShouldNotHaveBytecode); + .ok_or(VMError::NonceIsMax)?; + + // Update cache with account with incremented nonce + self.cache.add_account(&sender_address, &sender_account); + + // (7) PRIORITY_GREATER_THAN_MAX_FEE_PER_GAS + if let (Some(tx_max_priority_fee), Some(tx_max_fee_per_gas)) = ( + self.env.tx_max_priority_fee_per_gas, + self.env.tx_max_fee_per_gas, + ) { + if tx_max_priority_fee > tx_max_fee_per_gas { + return Err(VMError::PriorityGreaterThanMaxFeePerGas); + } } - // (6) - if sender_account.info.balance < call_frame.msg_value { - return Err(VMError::SenderBalanceShouldContainTransferValue); + // (8) SENDER_NOT_EOA + if sender_account.has_code() { + return Err(VMError::SenderNotEOA); } - self.cache.add_account(&origin, &sender_account); - - // (7) - if self.env.gas_price < self.env.base_fee_per_gas { - return Err(VMError::GasPriceIsLowerThanBaseFee); + // (9) GAS_ALLOWANCE_EXCEEDED + if self.env.gas_limit > self.env.block_gas_limit { + return Err(VMError::GasAllowanceExceeded); } - Ok(()) - } - fn is_create(&self) -> bool { - matches!(self.tx_kind, TxKind::Create) - } + // (10) INSUFFICIENT_MAX_FEE_PER_BLOB_GAS + if let Some(tx_max_fee_per_blob_gas) = self.env.tx_max_fee_per_blob_gas { + if tx_max_fee_per_blob_gas < self.env.base_fee_per_gas { + return Err(VMError::InsufficientMaxFeePerGas); + } + } - fn revert_create(&mut self) -> Result<(), VMError> { - // Note: currently working with copies - let call_frame = self - .call_frames - .last() - .ok_or(VMError::Internal( - InternalError::CouldNotAccessLastCallframe, - ))? - .clone(); + //TODO: Implement the rest of the validations (TYPE_3) - let sender = call_frame.msg_sender; - let mut sender_account = self.get_account(&sender); + // (11) TYPE_3_TX_ZERO_BLOBS + if let Some(tx_blob_hashes) = &self.env.tx_blob_hashes { + if tx_blob_hashes.is_empty() { + return Err(VMError::Type3TxZeroBlobs); + } + } - sender_account.info.nonce = sender_account - .info - .nonce - .checked_sub(1) - .ok_or(VMError::Internal(InternalError::NonceUnderflowed))?; + // (12) TYPE_3_TX_INVALID_BLOB_VERSIONED_HASH + if let Some(tx_blob_hashes) = &self.env.tx_blob_hashes { + for blob_hash in tx_blob_hashes { + let blob_hash = blob_hash.as_bytes(); + if let Some(first_byte) = blob_hash.first() { + if !VALID_BLOB_PREFIXES.contains(first_byte) { + return Err(VMError::Type3TxInvalidBlobVersionedHash); + } + } + } + } - let new_contract_address = call_frame.to; + // (13) TYPE_3_TX_PRE_FORK -> This is not necessary for now because we are not supporting pre-cancun transactions yet. But we should somehow be able to tell the current context. - if self.cache.accounts.remove(&new_contract_address).is_none() { - return Err(VMError::AddressDoesNotMatchAnAccount); // Should not be this error + // (14) TYPE_3_TX_BLOB_COUNT_EXCEEDED + if let Some(tx_blob_hashes) = &self.env.tx_blob_hashes { + if tx_blob_hashes.len() > MAX_BLOB_COUNT { + return Err(VMError::Type3TxBlobCountExceeded); + } } - // Should revert this? - // sender_account.info.balance -= self.call_frames.first().ok_or(VMError::FatalUnwrap)?.msg_value; + // (15) TYPE_3_TX_CONTRACT_CREATION + // The current way of checking if the transaction is a Type 3 Tx is by checking if the tx_blob_hashes is Some. + if self.env.tx_blob_hashes.is_some() && self.is_create() { + return Err(VMError::Type3TxContractCreation); + } Ok(()) } - pub fn transact(&mut self) -> Result { - self.validate_transaction()?; - - let initial_gas = Default::default(); - - self.env.consumed_gas = initial_gas; - - let mut current_call_frame = self - .call_frames - .pop() - .ok_or(VMError::Internal(InternalError::CouldNotPopCallframe))?; - - let mut report = self.execute(&mut current_call_frame); - - let initial_call_frame = self - .call_frames - .last() - .ok_or(VMError::Internal( - InternalError::CouldNotAccessLastCallframe, - ))? - .clone(); - - let sender = initial_call_frame.msg_sender; - - let initial_call_frame = self - .call_frames - .last() - .ok_or(VMError::Internal( - InternalError::CouldNotAccessLastCallframe, - ))? - .clone(); - - let calldata_cost = - gas_cost::tx_calldata(&initial_call_frame.calldata).map_err(VMError::OutOfGas)?; + fn is_create(&self) -> bool { + matches!(self.tx_kind, TxKind::Create) + } - report.gas_used = report - .gas_used - .checked_add(calldata_cost) - .ok_or(VMError::OutOfGas(OutOfGasError::GasUsedOverflow))?; + // Maybe this function is not necessary. + // fn revert_create(&mut self) -> Result<(), VMError> { + // // Note: currently working with copies + // let call_frame = self + // .call_frames + // .last() + // .ok_or(VMError::Internal( + // InternalError::CouldNotAccessLastCallframe, + // ))? + // .clone(); + + // let sender = call_frame.msg_sender; + // let mut sender_account = self.get_account(&sender); + + // sender_account.info.nonce = sender_account + // .info + // .nonce + // .checked_sub(1) + // .ok_or(VMError::Internal(InternalError::NonceUnderflowed))?; + + // let new_contract_address = call_frame.to; + + // if self.cache.accounts.remove(&new_contract_address).is_none() { + // return Err(VMError::AddressDoesNotMatchAnAccount); // Should not be this error + // } + + // // Should revert this? + // // sender_account.info.balance -= self.call_frames.first().ok_or(VMError::FatalUnwrap)?.msg_value; + + // Ok(()) + // } + + /// Calculates effective gas price and updates variable gas_price in env. + pub fn update_effective_gas_price(&mut self) -> Result<(), VMError> { + if let (Some(max_priority_fee_per_gas), Some(max_fee_per_gas)) = ( + self.env.tx_max_priority_fee_per_gas, + self.env.tx_max_fee_per_gas, + ) { + // Effective Gas Price = Base Fee + min(maxPriorityFeePerGas, maxFeePerGas - Base Fee) + self.env.gas_price = self + .env + .base_fee_per_gas + .checked_add( + max_priority_fee_per_gas.min( + max_fee_per_gas + .checked_sub(self.env.base_fee_per_gas) + .ok_or(VMError::InsufficientMaxFeePerGas)?, + ), + ) + .ok_or(VMError::Internal( + InternalError::ArithmeticOperationOverflow, + ))?; + // TODO: See what to return if base fee + priority fee causes overflow. + }; + Ok(()) + } + pub fn create_post_execution( + &mut self, + initial_call_frame: &mut CallFrame, + report: &mut TransactionReport, + ) -> Result<(), VMError> { if self.is_create() { - // If create should check if transaction failed. If failed should revert (delete created contract, ) - if let TxResult::Revert(error) = report.result { - self.revert_create()?; - return Err(error); + if let TxResult::Revert(error) = &report.result { + return Err(error.clone()); } + let contract_code = report.clone().output; - // TODO: Is this the expected behavior? - if !contract_code.is_empty() { - // (6) - if contract_code.len() > MAX_CODE_SIZE { - return Err(VMError::ContractOutputTooBig); - } - // Supposing contract code has contents - if *contract_code - .first() - .ok_or(VMError::Internal(InternalError::TriedToIndexEmptyCode))? - == INVALID_CONTRACT_PREFIX - { - return Err(VMError::InvalidInitialByte); - } + // (6) + if contract_code.len() > MAX_CODE_SIZE { + return Err(VMError::ContractOutputTooBig); } - // If the initialization code completes successfully, a final contract-creation cost is paid, - // the code-deposit cost, c, proportional to the size of the created contract’s code - let number_of_words: u64 = initial_call_frame - .calldata - .chunks(WORD_SIZE) - .len() - .try_into() - .map_err(|_| VMError::Internal(InternalError::ConversionError))?; + // If contract code is not empty then the first byte should not be 0xef + if *contract_code.first().unwrap_or(&0) == INVALID_CONTRACT_PREFIX { + return Err(VMError::InvalidInitialByte); + } + + let max_gas = self.env.gas_limit.low_u64(); + // If initialization code is successful, code-deposit cost is paid. let code_length: u64 = contract_code .len() .try_into() .map_err(|_| VMError::Internal(InternalError::ConversionError))?; + let code_deposit_cost = code_length + .checked_mul(200) + .ok_or(VMError::Internal(InternalError::OperationOverflow))?; - let creation_cost = - gas_cost::tx_creation(code_length, number_of_words).map_err(VMError::OutOfGas)?; - report.gas_used = report - .gas_used - .checked_add(creation_cost) - .ok_or(VMError::OutOfGas(OutOfGasError::GasUsedOverflow))?; - // Charge 22100 gas for each storage variable set + report.add_gas_with_max(code_deposit_cost, max_gas)?; + // Charge 22100 gas for each storage variable set (???) + // Assign bytecode to the new contract let contract_address = initial_call_frame.to; - let mut created_contract = self.get_account(&contract_address); created_contract.info.bytecode = contract_code; self.cache.add_account(&contract_address, &created_contract); } + Ok(()) + } - let mut sender_account = self.get_account(&sender); - let coinbase_address = self.env.coinbase; + /// ## Description + /// Changes to the state post-execution, if this fails we won't be able to determine a final state. + /// Errors here are mostly related to balance overflows. + /// TODO: Determine the right behavior when a balance overflow occurs. + /// 1. Refund unused gas to sender + /// 2. Transfer value to recipient or return value to sender depending on execution result. + /// 3. Pay priority fee to coinbase + pub fn post_execution_changes( + &mut self, + initial_call_frame: &CallFrame, + report: &TransactionReport, + ) -> Result<(), VMError> { + // 1. Refund unused gas to sender + let sender_address = self.env.origin; + let mut sender_account = self.get_account(&sender_address); + + let max_gas = self.env.gas_limit.low_u64(); + let consumed_gas = report.gas_used; + let refunded_gas = report.gas_refunded.min( + consumed_gas + .checked_div(5) + .ok_or(VMError::Internal(InternalError::UndefinedState(-1)))?, + ); + // "The max refundable proportion of gas was reduced from one half to one fifth by EIP-3529 by Buterin and Swende [2021] in the London release" + + let gas_to_return = max_gas + .checked_sub(consumed_gas) + .and_then(|gas| gas.checked_add(refunded_gas)) + .ok_or(VMError::Internal(InternalError::UndefinedState(0)))?; + + let gas_return_amount = self + .env + .gas_price + .checked_mul(U256::from(gas_to_return)) + .ok_or(VMError::Internal(InternalError::UndefinedState(1)))?; sender_account.info.balance = sender_account .info .balance - .checked_sub( - U256::from(report.gas_used) - .checked_mul(self.env.gas_price) - .ok_or(VMError::GasLimitPriceProductOverflow)?, - ) - .ok_or(VMError::BalanceUnderflow)?; + .checked_add(gas_return_amount) + .ok_or(VMError::Internal(InternalError::UndefinedState(2)))?; + + // 2. Transfer value to recipient or return value to sender depending on execution result. + let recipient_address = initial_call_frame.to; + let mut recipient_account = self.get_account(&recipient_address); - let receiver_address = initial_call_frame.to; - let mut receiver_account = self.get_account(&receiver_address); - // If execution was successful we want to transfer value from sender to receiver if report.is_success() { - // Subtract to the caller the gas sent - sender_account.info.balance = sender_account + // transfer value to recipient + recipient_account.info.balance = recipient_account .info .balance - .checked_sub(initial_call_frame.msg_value) - .ok_or(VMError::BalanceUnderflow)?; - receiver_account.info.balance = receiver_account + .checked_add(initial_call_frame.msg_value) + .ok_or(VMError::Internal(InternalError::UndefinedState(3)))?; + } else { + // return value to sender + sender_account.info.balance = sender_account .info .balance .checked_add(initial_call_frame.msg_value) - .ok_or(VMError::BalanceUnderflow)?; + .ok_or(VMError::Internal(InternalError::UndefinedState(4)))?; } - // Note: This is commented because it's used for debugging purposes in development. - // dbg!(&report.gas_refunded); - - self.cache.add_account(&sender, &sender_account); - self.cache.add_account(&receiver_address, &receiver_account); + self.cache.add_account(&sender_address, &sender_account); + self.cache + .add_account(&recipient_address, &recipient_account); - // Send coinbase fee + // 3. Pay priority fee to coinbase + let coinbase_address = self.env.coinbase; let priority_fee_per_gas = self .env .gas_price .checked_sub(self.env.base_fee_per_gas) - .ok_or(VMError::GasPriceIsLowerThanBaseFee)?; - let coinbase_fee = (U256::from(report.gas_used)) + .ok_or(VMError::Internal(InternalError::UndefinedState(5)))?; + let coinbase_fee = (U256::from(consumed_gas)) .checked_mul(priority_fee_per_gas) - .ok_or(VMError::BalanceOverflow)?; + .ok_or(VMError::Internal(InternalError::UndefinedState(6)))?; let mut coinbase_account = self.get_account(&coinbase_address); + coinbase_account.info.balance = coinbase_account .info .balance .checked_add(coinbase_fee) - .ok_or(VMError::BalanceOverflow)?; + .ok_or(VMError::Internal(InternalError::UndefinedState(7)))?; self.cache.add_account(&coinbase_address, &coinbase_account); + Ok(()) + } + + pub fn add_intrinsic_gas(&mut self, initial_call_frame: &mut CallFrame) -> Result<(), VMError> { + // Intrinsic gas is the gas consumed by the transaction before the execution of the opcodes. Section 6.2 in the Yellow Paper. + + // Intrinsic Gas = Calldata cost + Create cost + Base cost + Access list cost + let mut intrinsic_gas: U256 = U256::zero(); + + // Calldata Cost + // 4 gas for each zero byte in the transaction data 16 gas for each non-zero byte in the transaction. + let mut calldata_cost: U256 = U256::zero(); + for byte in &initial_call_frame.calldata { + if *byte != 0 { + calldata_cost = calldata_cost + .checked_add(U256::from(16)) + .ok_or(VMError::OutOfGas(OutOfGasError::ConsumedGasOverflow))?; + } else { + calldata_cost = calldata_cost + .checked_add(U256::from(4)) + .ok_or(VMError::OutOfGas(OutOfGasError::ConsumedGasOverflow))?; + } + } + + intrinsic_gas = intrinsic_gas + .checked_add(calldata_cost) + .ok_or(VMError::OutOfGas(OutOfGasError::ConsumedGasOverflow))?; + + // Base Cost + intrinsic_gas = intrinsic_gas + .checked_add(TX_BASE_COST) + .ok_or(VMError::OutOfGas(OutOfGasError::ConsumedGasOverflow))?; + + // Create Cost + if self.is_create() { + intrinsic_gas = intrinsic_gas + .checked_add(CREATE_BASE_COST) + .ok_or(VMError::OutOfGas(OutOfGasError::ConsumedGasOverflow))?; + + let number_of_words: u64 = initial_call_frame + .calldata + .chunks(WORD_SIZE) + .len() + .try_into() + .map_err(|_| VMError::Internal(InternalError::ConversionError))?; + + intrinsic_gas = intrinsic_gas + .checked_add( + U256::from(number_of_words) + .checked_mul(U256::from(2)) + .ok_or(VMError::OutOfGas(OutOfGasError::ConsumedGasOverflow))?, + ) + .ok_or(VMError::OutOfGas(OutOfGasError::ConsumedGasOverflow))?; + } + + // Access List Cost + // TODO: Implement access list cost. + + self.increase_consumed_gas(initial_call_frame, intrinsic_gas) + .map_err(|_| VMError::IntrinsicGasTooLow)?; + + Ok(()) + } + + pub fn transact(&mut self) -> Result { + let mut initial_call_frame = self + .call_frames + .pop() + .ok_or(VMError::Internal(InternalError::CouldNotPopCallframe))?; + + // Validates transaction and performs pre-exeuction changes. + // Errors don't revert execution, they are propagated because transaction is invalid. + self.validate_transaction(&mut initial_call_frame)?; + + self.update_effective_gas_price()?; // This is for gas_price to be a reasonable value + + // We need cache before execution because if a create transaction reverts in post-execution then we need to revert whatever the init-code did. + let cache_before_execution = self.cache.clone(); + let mut report = self.execute(&mut initial_call_frame)?; + + // Validation of create transaction post execution + // If it fails, it reverts contract creation. + match self.create_post_execution(&mut initial_call_frame, &mut report) { + Ok(_) => {} + Err(error) => { + if error.is_internal() { + return Err(error); + } else { + report.result = TxResult::Revert(error); + report.gas_refunded = 0; + report.gas_used = self.env.gas_limit.low_u64(); + self.cache = cache_before_execution; + self.cache.accounts.remove(&initial_call_frame.to); + } + } + }; + + self.post_execution_changes(&initial_call_frame, &report)?; + report.new_state.clone_from(&self.cache.accounts); Ok(report) @@ -600,7 +770,11 @@ impl VM { )) } - // TODO: Improve and test REVERT behavior for XCALL opcodes. Issue: https://github.com/lambdaclass/lambda_ethrex/issues/1061 + pub fn gas_price_or_max_fee_per_gas(&self) -> U256 { + self.env.tx_max_fee_per_gas.unwrap_or(self.env.gas_price) + } + + // TODO: Improve and test REVERT behavior for XCALL opcodes. Issue: https://github.com/lambdaclass/lambda_ethereum_rust/issues/1061 #[allow(clippy::too_many_arguments)] pub fn generic_call( &mut self, @@ -700,7 +874,7 @@ impl VM { self.cache.add_account(&to, &recipient_account); // self.call_frames.push(new_call_frame.clone()); - let tx_report = self.execute(&mut new_call_frame); + let tx_report = self.execute(&mut new_call_frame)?; // Add gas used by the sub-context to the current one after it's execution. current_call_frame.gas_used = current_call_frame diff --git a/crates/vm/levm/tests/edge_case_tests.rs b/crates/vm/levm/tests/edge_case_tests.rs index 99b198d05..90ec32dd6 100644 --- a/crates/vm/levm/tests/edge_case_tests.rs +++ b/crates/vm/levm/tests/edge_case_tests.rs @@ -14,14 +14,14 @@ fn test_extcodecopy_memory_allocation() { let mut current_call_frame = vm.call_frames.pop().unwrap(); current_call_frame.gas_limit = U256::from(100_000_000); vm.env.gas_price = U256::from(10_000); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); } #[test] fn test_overflow_mcopy() { let mut vm = new_vm_with_bytecode(Bytes::copy_from_slice(&[90, 90, 90, 94])).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); } #[test] @@ -29,56 +29,56 @@ fn test_overflow_call() { let mut vm = new_vm_with_bytecode(Bytes::copy_from_slice(&[61, 48, 56, 54, 51, 51, 51, 241])).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); } #[test] fn test_usize_overflow_revert() { let mut vm = new_vm_with_bytecode(Bytes::copy_from_slice(&[61, 63, 61, 253])).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); } #[test] fn test_overflow_returndatacopy() { let mut vm = new_vm_with_bytecode(Bytes::copy_from_slice(&[50, 49, 48, 51, 62])).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); } #[test] fn test_overflow_keccak256() { let mut vm = new_vm_with_bytecode(Bytes::copy_from_slice(&[51, 63, 61, 32])).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); } #[test] fn test_arithmetic_operation_overflow_selfdestruct() { let mut vm = new_vm_with_bytecode(Bytes::copy_from_slice(&[50, 255])).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); } #[test] fn test_overflow_swap() { let mut vm = new_vm_with_bytecode(Bytes::copy_from_slice(&[48, 144])).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); } #[test] fn test_end_of_range_swap() { let mut vm = new_vm_with_bytecode(Bytes::copy_from_slice(&[58, 50, 50, 51, 57])).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); } #[test] fn test_usize_overflow_blobhash() { let mut vm = new_vm_with_bytecode(Bytes::copy_from_slice(&[71, 73])).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); } #[test] @@ -90,7 +90,7 @@ fn add_op() { ]) .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!(vm.current_call_frame_mut().unwrap().pc(), 34); } @@ -99,5 +99,5 @@ fn add_op() { fn test_is_negative() { let mut vm = new_vm_with_bytecode(Bytes::copy_from_slice(&[58, 63, 58, 5])).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); } diff --git a/crates/vm/levm/tests/tests.rs b/crates/vm/levm/tests/tests.rs index 06fef1b97..a8b876823 100644 --- a/crates/vm/levm/tests/tests.rs +++ b/crates/vm/levm/tests/tests.rs @@ -58,7 +58,7 @@ fn add_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::one()); assert!(vm.current_call_frame_mut().unwrap().pc() == 68); @@ -75,7 +75,7 @@ fn mul_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::from(8)); } @@ -91,7 +91,7 @@ fn sub_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::from(2)); } @@ -108,7 +108,7 @@ fn div_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::from(5)); @@ -122,7 +122,7 @@ fn div_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::zero()); } @@ -139,7 +139,7 @@ fn sdiv_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::from(2)); } @@ -156,7 +156,7 @@ fn mod_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::from(1)); } @@ -174,7 +174,7 @@ fn smod_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::from(1)); @@ -201,7 +201,7 @@ fn smod_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let c = U256::from_str_radix( "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", @@ -225,7 +225,7 @@ fn addmod_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::from(4)); } @@ -243,7 +243,7 @@ fn mulmod_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::from(4)); } @@ -260,7 +260,7 @@ fn exp_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::from(100)); } @@ -277,7 +277,7 @@ fn sign_extend_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::from(0x7F)); // Case 2: Input: 0, 0xFF. Output: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF @@ -290,7 +290,7 @@ fn sign_extend_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::MAX); } @@ -306,7 +306,7 @@ fn lt_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::one()); } @@ -323,7 +323,7 @@ fn gt_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::one()); } @@ -340,7 +340,7 @@ fn slt_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::one()); } @@ -357,7 +357,7 @@ fn sgt_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::one()); } @@ -374,7 +374,7 @@ fn eq_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::one()); // Case 2: Input: 10, 20. Output: 0 (false) @@ -387,7 +387,7 @@ fn eq_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::zero()); } @@ -402,7 +402,7 @@ fn is_zero_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::one()); // Case 2: Input is non-zero (e.g., 10), Output should be 0 (since 10 != 0 is false) @@ -414,7 +414,7 @@ fn is_zero_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!(vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::zero()); } @@ -429,11 +429,11 @@ fn and_basic() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0b1000)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); } #[test] @@ -445,11 +445,10 @@ fn and_binary_with_zero() { Operation::Stop, ]) .unwrap(); - let expected_consumed_gas = - TX_BASE_COST + gas_cost::AND + gas_cost::PUSHN.checked_mul(U256::from(2)).unwrap(); + let expected_consumed_gas = gas_cost::AND + gas_cost::PUSHN.checked_mul(U256::from(2)).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::zero()); @@ -467,11 +466,11 @@ fn and_with_hex_numbers() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0xF0F0)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0xF000))), @@ -482,11 +481,11 @@ fn and_with_hex_numbers() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0xF000)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0xB020))), @@ -497,11 +496,11 @@ fn and_with_hex_numbers() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0b1000000000000)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); } #[test] @@ -515,11 +514,11 @@ fn or_basic() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0b1110)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0b1010))), @@ -530,11 +529,11 @@ fn or_basic() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0b1010)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(u64::MAX))), @@ -545,11 +544,11 @@ fn or_basic() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0xFFFFFFFFFFFFFFFF_u64)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); } #[test] @@ -563,11 +562,11 @@ fn or_with_hex_numbers() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0xFFFF)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0xF000))), @@ -578,11 +577,11 @@ fn or_with_hex_numbers() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0xF0F0)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0xB020))), @@ -593,11 +592,11 @@ fn or_with_hex_numbers() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0b1011111100101111)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); } #[test] @@ -611,11 +610,11 @@ fn xor_basic() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0b110)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0b1010))), @@ -626,11 +625,11 @@ fn xor_basic() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0b1010)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(u64::MAX))), @@ -641,11 +640,11 @@ fn xor_basic() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(u64::MAX)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(u64::MAX))), @@ -656,11 +655,11 @@ fn xor_basic() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::zero()); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); } #[test] @@ -674,11 +673,11 @@ fn xor_with_hex_numbers() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0xFF)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0xFF))), @@ -689,11 +688,11 @@ fn xor_with_hex_numbers() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::zero()); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0xFFFF))), @@ -704,11 +703,11 @@ fn xor_with_hex_numbers() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0xF0F)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0xF000))), @@ -719,11 +718,11 @@ fn xor_with_hex_numbers() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0xF0)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0x4C0F))), @@ -734,11 +733,11 @@ fn xor_with_hex_numbers() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0b111011001000100)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); } #[test] @@ -751,12 +750,12 @@ fn not() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); let expected = !U256::from(0b1010); assert_eq!(result, expected); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 6); + assert_eq!(vm.env.consumed_gas, U256::from(6)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::MAX)), @@ -766,11 +765,11 @@ fn not() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::zero()); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 6); + assert_eq!(vm.env.consumed_gas, U256::from(6)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::zero())), @@ -780,11 +779,11 @@ fn not() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::MAX); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 6); + assert_eq!(vm.env.consumed_gas, U256::from(6)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(1))), @@ -794,11 +793,11 @@ fn not() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::MAX - 1); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 6); + assert_eq!(vm.env.consumed_gas, U256::from(6)); } #[test] @@ -812,11 +811,11 @@ fn byte_basic() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0xF1)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0x33ED))), @@ -827,11 +826,11 @@ fn byte_basic() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0x33)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); } #[test] @@ -845,11 +844,11 @@ fn byte_edge_cases() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0xFF)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::MAX)), @@ -860,11 +859,11 @@ fn byte_edge_cases() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0xFF)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0x00E0D0000))), @@ -875,11 +874,11 @@ fn byte_edge_cases() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0x0D)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0xFDEA179))), @@ -890,11 +889,11 @@ fn byte_edge_cases() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::zero()); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0xFDEA179))), @@ -905,11 +904,11 @@ fn byte_edge_cases() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::zero()); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::zero())), @@ -920,11 +919,11 @@ fn byte_edge_cases() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::zero()); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let word = U256::from_big_endian(&[ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x57, 0x08, 0x09, 0x90, 0x0B, 0x0C, 0x0D, 0x0E, @@ -941,11 +940,11 @@ fn byte_edge_cases() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0x90)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, word)), @@ -956,11 +955,11 @@ fn byte_edge_cases() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0x57)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, word)), @@ -971,11 +970,11 @@ fn byte_edge_cases() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0xDD)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, word)), @@ -986,11 +985,11 @@ fn byte_edge_cases() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0x40)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); } #[test] @@ -1004,11 +1003,11 @@ fn shl_basic() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0xDDDD)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0x12345678))), @@ -1019,11 +1018,11 @@ fn shl_basic() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0x2468acf0)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0x12345678))), @@ -1034,11 +1033,11 @@ fn shl_basic() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(4886718336_u64)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0xFF))), @@ -1049,11 +1048,11 @@ fn shl_basic() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0xFF << 4)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); } #[test] @@ -1067,11 +1066,11 @@ fn shl_edge_cases() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::zero()); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::zero())), @@ -1082,11 +1081,11 @@ fn shl_edge_cases() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::zero()); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::MAX)), @@ -1097,11 +1096,11 @@ fn shl_edge_cases() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::MAX - 1); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); } #[test] @@ -1115,11 +1114,11 @@ fn shr_basic() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0xDDDD)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0x12345678))), @@ -1130,11 +1129,11 @@ fn shr_basic() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0x91a2b3c)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0x12345678))), @@ -1145,11 +1144,11 @@ fn shr_basic() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0x1234567)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::from(0xFF))), @@ -1160,11 +1159,11 @@ fn shr_basic() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0xF)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); } #[test] @@ -1178,11 +1177,11 @@ fn shr_edge_cases() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::zero()); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::zero())), @@ -1193,11 +1192,11 @@ fn shr_edge_cases() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::zero()); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); let mut vm = new_vm_with_ops(&[ Operation::Push((32, U256::MAX)), @@ -1208,11 +1207,11 @@ fn shr_edge_cases() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::MAX >> 1); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); } #[test] @@ -1226,11 +1225,11 @@ fn sar_shift_by_0() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0x12345678)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); } #[test] @@ -1250,7 +1249,7 @@ fn sar_shifting_large_value_with_all_bits_set() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); let expected = U256::from_big_endian(&[ @@ -1259,7 +1258,7 @@ fn sar_shifting_large_value_with_all_bits_set() { 0xff, 0xff, ]); assert_eq!(result, expected); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); } #[test] @@ -1279,7 +1278,7 @@ fn sar_shifting_negative_value_and_small_shift() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); let expected = U256::from_big_endian(&[ @@ -1288,7 +1287,7 @@ fn sar_shifting_negative_value_and_small_shift() { 0x00, 0x00, ]); assert_eq!(result, expected); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); } #[test] @@ -1302,11 +1301,11 @@ fn sar_shift_positive_value() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(result, U256::from(0x07FFFF)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); } #[test] @@ -1326,7 +1325,7 @@ fn sar_shift_negative_value() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let result = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); let expected = U256::from_big_endian(&[ @@ -1336,7 +1335,7 @@ fn sar_shift_negative_value() { ]); // change 0x8f to 0xf8 assert_eq!(result, expected); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 9); + assert_eq!(vm.env.consumed_gas, U256::from(9)); } #[test] @@ -1359,14 +1358,14 @@ fn keccak256_zero_offset_size_four() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::from("0x29045a592007d0c246ef02c2223570da9522d0cf0f73282c79a1bc8f0bb2c238") ); assert_eq!(vm.current_call_frame_mut().unwrap().pc(), 40); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 52); + assert_eq!(vm.env.consumed_gas, U256::from(52)); } #[test] @@ -1389,14 +1388,14 @@ fn keccak256_zero_offset_size_bigger_than_actual_memory() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap() == U256::from("0xae75624a7d0413029c1e0facdd38cc8e177d9225892e2490a69c2f1f89512061") ); assert_eq!(vm.current_call_frame_mut().unwrap().pc(), 40); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 61); + assert_eq!(vm.env.consumed_gas, U256::from(61)); } #[test] @@ -1411,14 +1410,14 @@ fn keccak256_zero_offset_zero_size() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::from("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470") ); assert_eq!(vm.current_call_frame_mut().unwrap().pc(), 4); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 34); + assert_eq!(vm.env.consumed_gas, U256::from(34)); } #[test] @@ -1441,14 +1440,14 @@ fn keccak256_offset_four_size_four() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::from("0xe8e77626586f73b955364c7b4bbf0bb7f7685ebd40e852b164633a4acbd3244c") ); assert_eq!(vm.current_call_frame_mut().unwrap().pc(), 41); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 53); + assert_eq!(vm.env.consumed_gas, U256::from(53)); } #[test] @@ -1463,14 +1462,14 @@ fn mstore() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::from(32) ); assert_eq!(vm.current_call_frame_mut().unwrap().pc(), 69); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 14); + assert_eq!(vm.env.consumed_gas, U256::from(14)); } #[test] @@ -1485,7 +1484,7 @@ fn mstore_saves_correct_value() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let stored_value = vm.current_call_frame_mut().unwrap().memory.load(0).unwrap(); @@ -1493,7 +1492,7 @@ fn mstore_saves_correct_value() { let memory_size = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(memory_size, U256::from(32)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 14); + assert_eq!(vm.env.consumed_gas, U256::from(14)); } #[test] @@ -1508,7 +1507,7 @@ fn mstore8() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let stored_value = vm.current_call_frame_mut().unwrap().memory.load(0).unwrap(); @@ -1516,7 +1515,7 @@ fn mstore8() { stored_value.to_big_endian(&mut value_bytes); assert_eq!(value_bytes[0..1], [0xAB]); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 12); + assert_eq!(vm.env.consumed_gas, U256::from(12)); } #[test] @@ -1536,7 +1535,7 @@ fn mcopy() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let copied_value = vm .current_call_frame_mut() @@ -1548,7 +1547,7 @@ fn mcopy() { let memory_size = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(memory_size, U256::from(96)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 35); + assert_eq!(vm.env.consumed_gas, U256::from(35)); } #[test] @@ -1565,11 +1564,11 @@ fn mload() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let loaded_value = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(loaded_value, U256::from(0x33333)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 18); + assert_eq!(vm.env.consumed_gas, U256::from(18)); } #[test] @@ -1579,11 +1578,11 @@ fn msize() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let initial_size = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(initial_size, U256::from(0)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 2); + assert_eq!(vm.env.consumed_gas, U256::from(2)); let operations = [ Operation::Push((32, U256::from(0x33333))), // value @@ -1596,11 +1595,11 @@ fn msize() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let after_store_size = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(after_store_size, U256::from(32)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 14); + assert_eq!(vm.env.consumed_gas, U256::from(14)); let operations = [ Operation::Push((32, U256::from(0x55555))), // value @@ -1613,11 +1612,11 @@ fn msize() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let final_size = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(final_size, U256::from(96)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 20); + assert_eq!(vm.env.consumed_gas, U256::from(20)); } #[test] @@ -1635,14 +1634,14 @@ fn mstore_mload_offset_not_multiple_of_32() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let memory_size = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); let loaded_value = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(loaded_value, U256::from(0xabcdef)); assert_eq!(memory_size, U256::from(64)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 23); + assert_eq!(vm.env.consumed_gas, U256::from(23)); // check with big offset @@ -1659,14 +1658,14 @@ fn mstore_mload_offset_not_multiple_of_32() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let memory_size = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); let loaded_value = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(loaded_value, U256::from(0x123456)); assert_eq!(memory_size, U256::from(2048)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 217); + assert_eq!(vm.env.consumed_gas, U256::from(217)); } #[test] @@ -1681,14 +1680,14 @@ fn mload_uninitialized_memory() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let memory_size = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); let loaded_value = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(loaded_value, U256::zero()); assert_eq!(memory_size, U256::from(96)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 17); + assert_eq!(vm.env.consumed_gas, U256::from(17)); } #[test] @@ -1730,7 +1729,7 @@ fn call_returns_if_bytecode_empty() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let success = vm.current_call_frame_mut().unwrap().stack.pop().unwrap(); assert_eq!(success, U256::one()); @@ -1774,7 +1773,7 @@ fn call_changes_callframe_and_stores() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let current_call_frame = vm.current_call_frame_mut().unwrap(); @@ -1876,7 +1875,7 @@ fn nested_calls() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let current_call_frame = vm.current_call_frame_mut().unwrap(); @@ -1948,7 +1947,7 @@ fn staticcall_changes_callframe_is_static() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let mut current_call_frame = vm.call_frames[0].clone(); @@ -1970,7 +1969,7 @@ fn pop_on_empty_stack() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - let tx_report = vm.execute(&mut current_call_frame); + let tx_report = vm.execute(&mut current_call_frame).unwrap(); // result should be a Halt with error VMError::StackUnderflow @@ -1987,13 +1986,13 @@ fn pc_op() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::from(0) ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 2); + assert_eq!(vm.env.consumed_gas, U256::from(2)); } #[test] @@ -2007,13 +2006,13 @@ fn pc_op_with_push_offset() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::from(33) ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 5); + assert_eq!(vm.env.consumed_gas, U256::from(5)); } // #[test] @@ -2067,7 +2066,7 @@ fn pc_op_with_push_offset() { // current_call_frame.to = Address::from_low_u64_be(U256::from(5).low_u64()); // let mut current_call_frame = vm.call_frames.pop().unwrap(); -// vm.execute(&mut current_call_frame); +// vm.execute(&mut current_call_frame).unwrap(); // let storage_slot = vm.cache.get_storage_slot( // Address::from_low_u64_be(U256::from(1).low_u64()), @@ -2131,7 +2130,7 @@ fn pc_op_with_push_offset() { // current_call_frame.to = Address::from_low_u64_be(U256::from(5).low_u64()); // let mut current_call_frame = vm.call_frames.pop().unwrap(); -// vm.execute(&mut current_call_frame); +// vm.execute(&mut current_call_frame).unwrap(); // let storage_slot = vm.cache.get_storage_slot(callee_address, U256::zero()); // let slot = StorageSlot { @@ -2193,7 +2192,7 @@ fn pc_op_with_push_offset() { // current_call_frame.to = Address::from_low_u64_be(U256::from(5).low_u64()); // let mut current_call_frame = vm.call_frames.pop().unwrap(); -// vm.execute(&mut current_call_frame); +// vm.execute(&mut current_call_frame).unwrap(); // let current_call_frame = vm.current_call_frame_mut().unwrap(); @@ -2250,7 +2249,7 @@ fn pc_op_with_push_offset() { // ); // let mut current_call_frame = vm.call_frames.pop().unwrap(); -// vm.execute(&mut current_call_frame); +// vm.execute(&mut current_call_frame).unwrap(); // let current_call_frame = vm.call_frames[0].clone(); @@ -2283,7 +2282,7 @@ fn jump_position_bigger_than_program_bytecode_size() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - let tx_report = vm.execute(&mut current_call_frame); + let tx_report = vm.execute(&mut current_call_frame).unwrap(); assert!(matches!( tx_report.result, TxResult::Revert(VMError::InvalidJump) @@ -2305,13 +2304,13 @@ fn jumpi_not_zero() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::from(10) ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 20); + assert_eq!(vm.env.consumed_gas, U256::from(20)); } #[test] @@ -2330,13 +2329,13 @@ fn jumpi_for_zero() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::from(100) ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 19); + assert_eq!(vm.env.consumed_gas, U256::from(19)); } // This test is just for trying things out, not a real test. But it is useful to have this as an example for conversions between bytes and u256. @@ -2401,7 +2400,7 @@ fn calldataload() { vm.current_call_frame_mut().unwrap().calldata = calldata; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let current_call_frame = vm.current_call_frame_mut().unwrap(); @@ -2414,7 +2413,7 @@ fn calldataload() { 0x00, 0x00, 0x00, 0x00 ]) ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 6); + assert_eq!(vm.env.consumed_gas, U256::from(6)); } #[test] @@ -2474,7 +2473,7 @@ fn calldataload_being_set_by_parent() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let current_call_frame = vm.current_call_frame_mut().unwrap(); @@ -2499,12 +2498,12 @@ fn calldatasize() { vm.current_call_frame_mut().unwrap().calldata = calldata; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let current_call_frame = vm.current_call_frame_mut().unwrap(); let top_of_stack = current_call_frame.stack.pop().unwrap(); assert_eq!(top_of_stack, U256::from(3)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 2); + assert_eq!(vm.env.consumed_gas, U256::from(2)); } #[test] @@ -2522,12 +2521,12 @@ fn calldatacopy() { vm.current_call_frame_mut().unwrap().calldata = calldata; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let current_call_frame = vm.current_call_frame_mut().unwrap(); let memory = current_call_frame.memory.load_range(0, 2).unwrap(); assert_eq!(memory, vec![0x22, 0x33]); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 18); + assert_eq!(vm.env.consumed_gas, U256::from(18)); } #[test] @@ -2539,12 +2538,12 @@ fn returndatasize() { vm.current_call_frame_mut().unwrap().sub_return_data = returndata; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let current_call_frame = vm.current_call_frame_mut().unwrap(); let top_of_stack = current_call_frame.stack.pop().unwrap(); assert_eq!(top_of_stack, U256::from(3)); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 2); + assert_eq!(vm.env.consumed_gas, U256::from(2)); } #[test] @@ -2562,12 +2561,12 @@ fn returndatacopy() { vm.current_call_frame_mut().unwrap().sub_return_data = returndata; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let current_call_frame = vm.current_call_frame_mut().unwrap(); let memory = current_call_frame.memory.load_range(0, 2).unwrap(); assert_eq!(memory, vec![0xBB, 0xCC]); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 18); + assert_eq!(vm.env.consumed_gas, U256::from(18)); } #[test] @@ -2611,7 +2610,7 @@ fn returndatacopy_being_set_by_parent() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let current_call_frame = vm.current_call_frame_mut().unwrap(); @@ -2648,13 +2647,13 @@ fn blockhash_op() { vm.env.block_number = current_block_number; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), expected_block_hash ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 23); + assert_eq!(vm.env.consumed_gas, U256::from(23)); } #[test] @@ -2680,13 +2679,13 @@ fn blockhash_same_block_number() { vm.env.block_number = current_block_number; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), expected_block_hash ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 23); + assert_eq!(vm.env.consumed_gas, U256::from(23)); } #[test] @@ -2716,13 +2715,13 @@ fn blockhash_block_number_not_from_recent_256() { vm.env.block_number = current_block_number; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), expected_block_hash ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 23); + assert_eq!(vm.env.consumed_gas, U256::from(23)); } #[test] @@ -2735,13 +2734,13 @@ fn coinbase_op() { vm.env.coinbase = Address::from_low_u64_be(coinbase_address); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::from(coinbase_address) ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 2); + assert_eq!(vm.env.consumed_gas, U256::from(2)); } #[test] @@ -2754,13 +2753,13 @@ fn timestamp_op() { vm.env.timestamp = timestamp; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), timestamp ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 2); + assert_eq!(vm.env.consumed_gas, U256::from(2)); } #[test] @@ -2773,13 +2772,13 @@ fn number_op() { vm.env.block_number = block_number; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), block_number ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 2); + assert_eq!(vm.env.consumed_gas, U256::from(2)); } #[test] @@ -2792,13 +2791,13 @@ fn prevrandao_op() { vm.env.prev_randao = Some(prevrandao); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::from_big_endian(&prevrandao.0) ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 2); + assert_eq!(vm.env.consumed_gas, U256::from(2)); } #[test] @@ -2811,13 +2810,13 @@ fn gaslimit_op() { vm.env.gas_limit = gas_limit; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), gas_limit ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 2); + assert_eq!(vm.env.consumed_gas, U256::from(2)); } #[test] @@ -2830,13 +2829,13 @@ fn chain_id_op() { vm.env.chain_id = chain_id; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), chain_id ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 2); + assert_eq!(vm.env.consumed_gas, U256::from(2)); } #[test] @@ -2849,13 +2848,13 @@ fn basefee_op() { vm.env.base_fee_per_gas = base_fee_per_gas; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), base_fee_per_gas ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 2); + assert_eq!(vm.env.consumed_gas, U256::from(2)); } // TODO: Add excess_blob_gas and blob_gas_used to env @@ -2868,13 +2867,13 @@ fn blobbasefee_op() { vm.env.block_blob_gas_used = Some(U256::zero()); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::from(2) ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 2); + assert_eq!(vm.env.consumed_gas, U256::from(2)); } // TODO: Add excess_blob_gas and blob_gas_used to env @@ -2887,13 +2886,13 @@ fn blobbasefee_minimum_cost() { vm.env.block_blob_gas_used = Some(U256::zero()); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::one() ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 2); + assert_eq!(vm.env.consumed_gas, U256::from(2)); } #[test] @@ -2908,13 +2907,13 @@ fn pop_op() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::one() ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 8); + assert_eq!(vm.env.consumed_gas, U256::from(8)); } #[test] @@ -2931,14 +2930,14 @@ fn jump_op() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::from(10) ); assert_eq!(vm.current_call_frame_mut().unwrap().pc(), 70); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 15); + assert_eq!(vm.env.consumed_gas, U256::from(15)); } #[test] @@ -2954,7 +2953,7 @@ fn jump_not_jumpdest_position() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - let tx_report = vm.execute(&mut current_call_frame); + let tx_report = vm.execute(&mut current_call_frame).unwrap(); assert!(matches!( tx_report.result, TxResult::Revert(VMError::InvalidJump) @@ -2981,7 +2980,7 @@ fn sstore_op() { vm.current_call_frame_mut().unwrap().code_address = sender_address; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); // Convert key in U256 to H256 let mut bytes = [0u8; 32]; @@ -3007,7 +3006,7 @@ fn sstore_reverts_when_called_in_static() { let mut vm = new_vm_with_ops(&operations).unwrap(); vm.current_call_frame_mut().unwrap().is_static = true; let mut current_call_frame = vm.call_frames.pop().unwrap(); - let tx_report = vm.execute(&mut current_call_frame); + let tx_report = vm.execute(&mut current_call_frame).unwrap(); assert!(matches!( tx_report.result, @@ -3036,7 +3035,7 @@ fn sload_op() { vm.current_call_frame_mut().unwrap().msg_sender = sender_address; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( value, @@ -3057,7 +3056,7 @@ fn sload_untouched_key_of_storage() { vm.current_call_frame_mut().unwrap().msg_sender = sender_address; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( U256::zero(), @@ -3075,7 +3074,7 @@ fn sload_on_not_existing_account() { vm.current_call_frame_mut().unwrap().msg_sender = sender_address; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( U256::zero(), @@ -3099,14 +3098,14 @@ fn log0() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let logs = &vm.current_call_frame_mut().unwrap().logs; let data = [0xff_u8; 32].as_slice(); assert_eq!(logs.len(), 1); assert_eq!(logs[0].data, data.to_vec()); assert_eq!(logs[0].topics.len(), 0); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 649); + assert_eq!(vm.env.consumed_gas, U256::from(649)); } #[test] @@ -3129,14 +3128,14 @@ fn log1() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let logs = &vm.current_call_frame_mut().unwrap().logs; let data = [0xff_u8; 32].as_slice(); assert_eq!(logs.len(), 1); assert_eq!(logs[0].data, data.to_vec()); assert_eq!(logs[0].topics, vec![H256::from_slice(&topic1)]); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 1027); + assert_eq!(vm.env.consumed_gas, U256::from(1027)); } #[test] @@ -3162,7 +3161,7 @@ fn log2() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let logs = &vm.current_call_frame_mut().unwrap().logs; let data = [0xff_u8; 32].as_slice(); @@ -3172,7 +3171,7 @@ fn log2() { logs[0].topics, vec![H256::from_slice(&topic1), H256::from_slice(&topic2)] ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 1405); + assert_eq!(vm.env.consumed_gas, U256::from(1405)); } #[test] @@ -3201,7 +3200,7 @@ fn log3() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let logs = &vm.current_call_frame_mut().unwrap().logs; let data = [0xff_u8; 32].as_slice(); @@ -3215,7 +3214,7 @@ fn log3() { H256::from_slice(&topic3) ] ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 1783); + assert_eq!(vm.env.consumed_gas, U256::from(1783)); } #[test] @@ -3247,7 +3246,7 @@ fn log4() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let logs = &vm.current_call_frame_mut().unwrap().logs; let data = [0xff_u8; 32].as_slice(); @@ -3262,7 +3261,7 @@ fn log4() { H256::from_slice(&topic4) ] ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 2161); + assert_eq!(vm.env.consumed_gas, U256::from(2161)); } #[test] @@ -3281,13 +3280,13 @@ fn log_with_0_data_size() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let logs = &vm.current_call_frame_mut().unwrap().logs; assert_eq!(logs.len(), 1); assert_eq!(logs[0].data, Vec::new()); assert_eq!(logs[0].topics.len(), 0); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 393); + assert_eq!(vm.env.consumed_gas, U256::from(393)); } #[test] @@ -3307,7 +3306,7 @@ fn cant_create_log_in_static_context() { let mut vm: VM = new_vm_with_ops(&operations).unwrap(); vm.current_call_frame_mut().unwrap().is_static = true; let mut current_call_frame = vm.call_frames.pop().unwrap(); - let tx_report = vm.execute(&mut current_call_frame); + let tx_report = vm.execute(&mut current_call_frame).unwrap(); assert!(matches!( tx_report.result, @@ -3331,7 +3330,7 @@ fn log_with_data_in_memory_smaller_than_size() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let logs = &vm.current_call_frame_mut().unwrap().logs; let mut data = vec![0_u8; 16]; @@ -3340,7 +3339,7 @@ fn log_with_data_in_memory_smaller_than_size() { assert_eq!(logs.len(), 1); assert_eq!(logs[0].data, data); assert_eq!(logs[0].topics.len(), 0); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + 649); + assert_eq!(vm.env.consumed_gas, U256::from(649)); } #[test] @@ -3366,7 +3365,7 @@ fn multiple_logs_of_different_types() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let logs = &vm.current_call_frame_mut().unwrap().logs; let data = [0xff_u8; 32].as_slice(); @@ -3425,7 +3424,7 @@ fn logs_from_multiple_callers() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!(current_call_frame.logs.len(), 2) } @@ -3470,7 +3469,7 @@ fn logs_from_multiple_callers() { // vm.db.add_account(callee_address, callee_account); // let mut current_call_frame = vm.call_frames.pop().unwrap(); -// vm.execute(&mut current_call_frame); +// vm.execute(&mut current_call_frame).unwrap(); // assert_eq!( // vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), @@ -3483,7 +3482,7 @@ fn push0_ok() { let mut vm = new_vm_with_ops(&[Operation::Push0, Operation::Stop]).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.stack[0], @@ -3499,7 +3498,7 @@ fn push1_ok() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!(vm.current_call_frame_mut().unwrap().stack.stack[0], to_push); assert_eq!(vm.current_call_frame_mut().unwrap().pc(), 3); @@ -3512,7 +3511,7 @@ fn push5_ok() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!(vm.current_call_frame_mut().unwrap().stack.stack[0], to_push); assert_eq!(vm.current_call_frame_mut().unwrap().pc(), 7); @@ -3525,7 +3524,7 @@ fn push31_ok() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!(vm.current_call_frame_mut().unwrap().stack.stack[0], to_push); assert_eq!(vm.current_call_frame_mut().unwrap().pc(), 33); @@ -3538,7 +3537,7 @@ fn push32_ok() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!(vm.current_call_frame_mut().unwrap().stack.stack[0], to_push); assert_eq!(vm.current_call_frame_mut().unwrap().pc(), 34); @@ -3555,7 +3554,7 @@ fn dup1_ok() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let stack_len = vm.current_call_frame_mut().unwrap().stack.len(); @@ -3581,7 +3580,7 @@ fn dup16_ok() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let stack_len = vm.current_call_frame_mut().unwrap().stack.len(); @@ -3603,7 +3602,7 @@ fn dup_halts_if_stack_underflow() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - let tx_report = vm.execute(&mut current_call_frame); + let tx_report = vm.execute(&mut current_call_frame).unwrap(); assert!(matches!( tx_report.result, @@ -3623,7 +3622,7 @@ fn swap1_ok() { ]; let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!(vm.current_call_frame_mut().unwrap().stack.len(), 2); assert_eq!(vm.current_call_frame_mut().unwrap().pc(), 6); @@ -3643,7 +3642,7 @@ fn swap16_ok() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let stack_len = vm.current_call_frame_mut().unwrap().stack.len(); assert_eq!(stack_len, 17); @@ -3664,7 +3663,7 @@ fn swap_halts_if_stack_underflow() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - let tx_report = vm.execute(&mut current_call_frame); + let tx_report = vm.execute(&mut current_call_frame).unwrap(); assert!(matches!( tx_report.result, @@ -3691,7 +3690,7 @@ fn transient_store() { assert!(current_call_frame.transient_storage.is_empty()); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let current_call_frame = vm.current_call_frame_mut().unwrap(); @@ -3716,7 +3715,7 @@ fn transient_store_stack_underflow() { .is_empty()); let mut current_call_frame = vm.call_frames.pop().unwrap(); - let tx_report = vm.execute(&mut current_call_frame); + let tx_report = vm.execute(&mut current_call_frame).unwrap(); assert!(matches!( tx_report.result, @@ -3745,7 +3744,7 @@ fn transient_load() { .insert((caller, key), value); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( *vm.current_call_frame_mut() @@ -3791,7 +3790,7 @@ fn create_happy_path() { vm.current_call_frame_mut().unwrap().msg_sender = sender_addr; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let call_frame = vm.current_call_frame_mut().unwrap(); let returned_address = call_frame.stack.pop().unwrap(); @@ -3838,7 +3837,7 @@ fn cant_create_with_size_longer_than_max_code_size() { vm.current_call_frame_mut().unwrap().msg_sender = sender_addr; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let call_frame = vm.current_call_frame_mut().unwrap(); let create_return_value = call_frame.stack.pop().unwrap(); @@ -3873,7 +3872,7 @@ fn cant_create_on_static_contexts() { vm.current_call_frame_mut().unwrap().is_static = true; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let call_frame = vm.current_call_frame_mut().unwrap(); let create_return_value = call_frame.stack.pop().unwrap(); @@ -3907,7 +3906,7 @@ fn cant_create_if_transfer_value_bigger_than_balance() { vm.current_call_frame_mut().unwrap().msg_sender = sender_addr; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let call_frame = vm.current_call_frame_mut().unwrap(); let create_return_value = call_frame.stack.pop().unwrap(); @@ -3941,7 +3940,7 @@ fn cant_create_if_sender_nonce_would_overflow() { vm.current_call_frame_mut().unwrap().msg_sender = sender_addr; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let call_frame = vm.current_call_frame_mut().unwrap(); let create_return_value = call_frame.stack.pop().unwrap(); @@ -3985,7 +3984,7 @@ fn cant_create_if_sender_nonce_would_overflow() { // vm.current_call_frame_mut().unwrap().msg_sender = sender_addr; // let mut current_call_frame = vm.call_frames.pop().unwrap(); -// vm.execute(&mut current_call_frame); +// vm.execute(&mut current_call_frame).unwrap(); // let call_frame = vm.current_call_frame_mut().unwrap(); @@ -4013,7 +4012,7 @@ fn cant_create_if_sender_nonce_would_overflow() { // new_vm.current_call_frame_mut().unwrap().msg_sender = sender_addr; // let mut current_call_frame = new_vm.call_frames.pop().unwrap(); -// new_vm.execute(&mut current_call_frame); +// new_vm.execute(&mut current_call_frame).unwrap(); // let call_frame = new_vm.current_call_frame_mut().unwrap(); // let return_of_created_callframe = call_frame.stack.pop().unwrap(); // assert_eq!(return_of_created_callframe, U256::from(REVERT_FOR_CREATE)); @@ -4063,7 +4062,7 @@ fn create2_happy_path() { vm.current_call_frame_mut().unwrap().msg_sender = sender_addr; let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); let call_frame = vm.current_call_frame_mut().unwrap(); let returned_address = call_frame.stack.pop().unwrap(); @@ -4108,7 +4107,7 @@ fn create2_happy_path() { // vm.current_call_frame_mut().unwrap().msg_sender = sender_addr; // let mut current_call_frame = vm.call_frames.pop().unwrap(); -// vm.execute(&mut current_call_frame); +// vm.execute(&mut current_call_frame).unwrap(); // assert_eq!(vm.db.accounts.len(), 4); // } @@ -4144,13 +4143,13 @@ fn caller_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::from(caller.as_bytes()) ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + gas_cost::CALLER); + assert_eq!(vm.env.consumed_gas, gas_cost::CALLER); } #[test] @@ -4185,13 +4184,13 @@ fn origin_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::from(msg_sender.as_bytes()) ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + gas_cost::ORIGIN); + assert_eq!(vm.env.consumed_gas, gas_cost::ORIGIN); } #[test] @@ -4214,7 +4213,7 @@ fn balance_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), @@ -4253,13 +4252,13 @@ fn address_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::from(address_that_has_the_code.as_bytes()) ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + gas_cost::ADDRESS); + assert_eq!(vm.env.consumed_gas, gas_cost::ADDRESS); } #[test] @@ -4298,13 +4297,13 @@ fn selfbalance_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), balance ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + gas_cost::SELFBALANCE); + assert_eq!(vm.env.consumed_gas, gas_cost::SELFBALANCE); } #[test] @@ -4340,13 +4339,13 @@ fn callvalue_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), value ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + gas_cost::CALLVALUE); + assert_eq!(vm.env.consumed_gas, gas_cost::CALLVALUE); } #[test] @@ -4381,12 +4380,12 @@ fn codesize_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::from(2) ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + gas_cost::CODESIZE); + assert_eq!(vm.env.consumed_gas, gas_cost::CODESIZE); } #[test] @@ -4421,12 +4420,12 @@ fn gasprice_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), U256::from(0x9876) ); - assert_eq!(vm.env.consumed_gas, TX_BASE_COST + gas_cost::GASPRICE); + assert_eq!(vm.env.consumed_gas, gas_cost::GASPRICE); } #[test] @@ -4477,7 +4476,7 @@ fn codecopy_op() { .unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().memory.load(0).unwrap(), @@ -4485,7 +4484,7 @@ fn codecopy_op() { ); assert_eq!( vm.env.consumed_gas, - TX_BASE_COST + U256::from(9) + U256::from(3) * gas_cost::PUSHN + U256::from(9) + U256::from(3) * gas_cost::PUSHN ); } @@ -4507,12 +4506,12 @@ fn extcodesize_existing_account() { let mut vm = new_vm_with_ops_db(&operations, db).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), 23.into() ); - assert_eq!(vm.env.consumed_gas, 23603.into()); + assert_eq!(vm.env.consumed_gas, 2603.into()); } #[test] @@ -4527,12 +4526,12 @@ fn extcodesize_non_existing_account() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), 0.into() ); - assert_eq!(vm.env.consumed_gas, 23603.into()); + assert_eq!(vm.env.consumed_gas, 2603.into()); } #[test] @@ -4558,7 +4557,7 @@ fn extcodecopy_existing_account() { let mut vm = new_vm_with_ops_db(&operations, db).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut() .unwrap() @@ -4567,7 +4566,7 @@ fn extcodecopy_existing_account() { .unwrap(), vec![0x60] ); - assert_eq!(vm.env.consumed_gas, 23616.into()); + assert_eq!(vm.env.consumed_gas, 2616.into()); } #[test] @@ -4587,7 +4586,7 @@ fn extcodecopy_non_existing_account() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut() .unwrap() @@ -4596,7 +4595,7 @@ fn extcodecopy_non_existing_account() { .unwrap(), vec![0; size] ); - assert_eq!(vm.env.consumed_gas, 23616.into()); + assert_eq!(vm.env.consumed_gas, 2616.into()); } #[test] @@ -4614,12 +4613,12 @@ fn extcodehash_account_with_empty_code() { let mut vm = new_vm_with_ops_db(&operations, db).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470".into() ); - assert_eq!(vm.env.consumed_gas, 23603.into()); + assert_eq!(vm.env.consumed_gas, 2603.into()); } #[test] @@ -4634,12 +4633,12 @@ fn extcodehash_non_existing_account() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!( vm.current_call_frame_mut().unwrap().stack.pop().unwrap(), "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470".into() ); - assert_eq!(vm.env.consumed_gas, 23603.into()); + assert_eq!(vm.env.consumed_gas, 2603.into()); } #[test] @@ -4649,7 +4648,7 @@ fn invalid_opcode() { let mut vm = new_vm_with_ops(&operations).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - let tx_report = vm.execute(&mut current_call_frame); + let tx_report = vm.execute(&mut current_call_frame).unwrap(); assert!(matches!( tx_report.result, @@ -4672,7 +4671,7 @@ fn revert_opcode() { let mut vm = new_vm_with_ops(&ops).unwrap(); let mut current_call_frame = vm.call_frames.pop().unwrap(); - let tx_report = vm.execute(&mut current_call_frame); + let tx_report = vm.execute(&mut current_call_frame).unwrap(); assert_eq!(U256::from_big_endian(&tx_report.output), U256::from(0xA)); assert!(matches!( @@ -4703,7 +4702,7 @@ fn revert_sstore() { // Cache state before the SSTORE let cache_backup = vm.cache.clone(); - vm.execute(&mut current_call_frame); + vm.execute(&mut current_call_frame).unwrap(); assert_eq!(vm.cache, cache_backup); } diff --git a/crates/vm/vm.rs b/crates/vm/vm.rs index 89d9e24fe..429eec61d 100644 --- a/crates/vm/vm.rs +++ b/crates/vm/vm.rs @@ -166,7 +166,7 @@ cfg_if::cfg_if! { let env = Environment { origin: tx.sender(), - consumed_gas: U256::from(21000), // Base gas cost for a transaction + consumed_gas: U256::zero(), refunded_gas: U256::zero(), gas_limit: tx.gas_limit().into(), block_number: block_header.number.into(), @@ -179,6 +179,10 @@ cfg_if::cfg_if! { block_excess_blob_gas: block_header.excess_blob_gas.map(U256::from), block_blob_gas_used: block_header.blob_gas_used.map(U256::from), tx_blob_hashes: None, + block_gas_limit: block_header.gas_limit.into(), + tx_max_priority_fee_per_gas: tx.max_priority_fee().map(U256::from), + tx_max_fee_per_gas: tx.max_fee_per_gas().map(U256::from), + tx_max_fee_per_blob_gas: tx.max_fee_per_blob_gas().map(U256::from), }; let mut vm = VM::new(