From a19b652a0ec1571dfe247f849bdf14bd97b854ca Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Wed, 26 Jun 2024 16:58:21 +0200 Subject: [PATCH 1/7] tests: evm-gas-cost-optimizations --- Cargo.lock | 16 ++-- Cargo.toml | 9 ++- engine-precompiles/src/xcc.rs | 4 +- engine-sdk/src/caching.rs | 4 + engine-tests/src/tests/one_inch.rs | 6 +- .../src/tests/promise_results_precompile.rs | 4 +- engine-tests/src/utils/mod.rs | 19 +++-- engine/src/engine.rs | 78 +++++++++++++------ 8 files changed, 86 insertions(+), 54 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c07d36eb0..399a7bf6a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1757,8 +1757,8 @@ dependencies = [ [[package]] name = "evm" -version = "0.42.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.42.0-aurora#58f7b84e8c7e5decacb1a85baa8bbf0042c56666" +version = "0.43.0" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.44.0-alpha.0#bee8e90ce9bb23edbfc731e4840018df5d1691b9" dependencies = [ "auto_impl", "environmental", @@ -1777,8 +1777,8 @@ dependencies = [ [[package]] name = "evm-core" -version = "0.42.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.42.0-aurora#58f7b84e8c7e5decacb1a85baa8bbf0042c56666" +version = "0.43.0" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.44.0-alpha.0#bee8e90ce9bb23edbfc731e4840018df5d1691b9" dependencies = [ "parity-scale-codec", "primitive-types 0.12.2", @@ -1788,8 +1788,8 @@ dependencies = [ [[package]] name = "evm-gasometer" -version = "0.42.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.42.0-aurora#58f7b84e8c7e5decacb1a85baa8bbf0042c56666" +version = "0.43.0" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.44.0-alpha.0#bee8e90ce9bb23edbfc731e4840018df5d1691b9" dependencies = [ "environmental", "evm-core", @@ -1799,8 +1799,8 @@ dependencies = [ [[package]] name = "evm-runtime" -version = "0.42.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.42.0-aurora#58f7b84e8c7e5decacb1a85baa8bbf0042c56666" +version = "0.43.0" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.44.0-alpha.0#bee8e90ce9bb23edbfc731e4840018df5d1691b9" dependencies = [ "auto_impl", "environmental", diff --git a/Cargo.toml b/Cargo.toml index e133ad055..cd67ca2a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,10 +31,11 @@ byte-slice-cast = { version = "1", default-features = false } criterion = "0.5" digest = "0.10" ethabi = { version = "18", default-features = false } -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.42.0-aurora", default-features = false } -evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.42.0-aurora", default-features = false, features = ["std"] } -evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.42.0-aurora", default-features = false, features = ["std", "tracing"] } -evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.42.0-aurora", default-features = false, features = ["std", "tracing"] } +# ref = "000196f608568f6ea558adbcdc0c6cb5819f82b4" +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.0-alpha.0", default-features = false } +evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.0-alpha.0", default-features = false, features = ["std"] } +evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.0-alpha.0", default-features = false, features = ["std", "tracing"] } +evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.0-alpha.0", default-features = false, features = ["std", "tracing"] } fixed-hash = { version = "0.8", default-features = false } function_name = "0.3" git2 = "0.18" diff --git a/engine-precompiles/src/xcc.rs b/engine-precompiles/src/xcc.rs index 6bcead2d6..540274588 100644 --- a/engine-precompiles/src/xcc.rs +++ b/engine-precompiles/src/xcc.rs @@ -33,7 +33,7 @@ pub mod costs { pub const CROSS_CONTRACT_CALL_BASE: EthGas = EthGas::new(343_650); /// Additional EVM gas cost per bytes of input given. /// See `CROSS_CONTRACT_CALL_BASE` for estimation methodology. - pub const CROSS_CONTRACT_CALL_BYTE: EthGas = EthGas::new(3); + pub const CROSS_CONTRACT_CALL_BYTE: EthGas = EthGas::new(4); /// EVM gas cost per NEAR gas attached to the created promise. /// This value is derived from the gas report `https://hackmd.io/@birchmd/Sy4piXQ29` /// The units on this quantity are `NEAR Gas / EVM Gas`. @@ -338,7 +338,7 @@ mod tests { let amount = U256::from_big_endian(&amount); #[allow(deprecated)] - let transfer_from_function = ethabi::Function { + let transfer_from_function = ethabi::Function { name: "transferFrom".into(), inputs: vec![ ethabi::Param { diff --git a/engine-sdk/src/caching.rs b/engine-sdk/src/caching.rs index d2baa6c6a..f28a3ebc7 100644 --- a/engine-sdk/src/caching.rs +++ b/engine-sdk/src/caching.rs @@ -10,4 +10,8 @@ impl FullCache { pub fn get_or_insert_with V>(&mut self, k: K, f: F) -> &mut V { self.inner.entry(k).or_insert_with(f) } + + pub fn contains_key(&self, k: K) -> bool { + self.inner.contains_key(&k) + } } diff --git a/engine-tests/src/tests/one_inch.rs b/engine-tests/src/tests/one_inch.rs index e1ce72a66..75b03b552 100644 --- a/engine-tests/src/tests/one_inch.rs +++ b/engine-tests/src/tests/one_inch.rs @@ -26,7 +26,7 @@ fn test_1inch_liquidity_protocol() { let (result, profile, pool_factory) = helper.create_pool_factory(&deployer_address); assert!(result.gas_used >= 2_800_000); // more than 2.8M EVM gas used - assert_gas_bound(profile.all_gas(), 9); // less than 9 NEAR Tgas used + assert_gas_bound(profile.all_gas(), 10); // less than 9 NEAR Tgas used // create some ERC-20 tokens to have a liquidity pool for let signer_address = utils::address_from_secret_key(&helper.signer.secret_key); @@ -38,7 +38,7 @@ fn test_1inch_liquidity_protocol() { let (result, profile, pool) = helper.create_pool(&pool_factory, token_a.0.address, token_b.0.address); assert!(result.gas_used >= 4_500_000); // more than 4.5M EVM gas used - assert_gas_bound(profile.all_gas(), 18); + assert_gas_bound(profile.all_gas(), 20); // Approve giving ERC-20 tokens to the pool helper.approve_erc20_tokens(&token_a, pool.address()); @@ -100,7 +100,7 @@ fn test_1_inch_limit_order_deploy() { // more than 3.5 million Ethereum gas used assert!(result.gas_used > 3_500_000); // less than 11 NEAR TGas used - assert_gas_bound(profile.all_gas(), 11); + assert_gas_bound(profile.all_gas(), 12); // at least 45% of which is from wasm execution let wasm_fraction = 100 * profile.wasm_gas() / profile.all_gas(); assert!( diff --git a/engine-tests/src/tests/promise_results_precompile.rs b/engine-tests/src/tests/promise_results_precompile.rs index 7b6351c0f..536c3f795 100644 --- a/engine-tests/src/tests/promise_results_precompile.rs +++ b/engine-tests/src/tests/promise_results_precompile.rs @@ -121,13 +121,13 @@ fn test_promise_result_gas_cost() { let total_gas2 = y2 + baseline.all_gas(); assert!( - utils::within_x_percent(17, evm1, total_gas1 / NEAR_GAS_PER_EVM), + utils::within_x_percent(21, evm1, total_gas1 / NEAR_GAS_PER_EVM), "Incorrect EVM gas used. Expected: {} Actual: {}", evm1, total_gas1 / NEAR_GAS_PER_EVM ); assert!( - utils::within_x_percent(17, evm2, total_gas2 / NEAR_GAS_PER_EVM), + utils::within_x_percent(21, evm2, total_gas2 / NEAR_GAS_PER_EVM), "Incorrect EVM gas used. Expected: {} Actual: {}", evm2, total_gas2 / NEAR_GAS_PER_EVM diff --git a/engine-tests/src/utils/mod.rs b/engine-tests/src/utils/mod.rs index 45d3c1e55..267cae0a5 100644 --- a/engine-tests/src/utils/mod.rs +++ b/engine-tests/src/utils/mod.rs @@ -150,7 +150,7 @@ impl<'a> OneShotAuroraRunner<'a> { &[], Some(&self.base.cache), ) - .unwrap(); + .unwrap(); if let Some(aborted) = outcome.aborted.as_ref() { Err(into_engine_error(outcome.used_gas, aborted)) @@ -226,7 +226,7 @@ impl AuroraRunner { &vm_promise_results, Some(&self.cache), ) - .unwrap(); + .unwrap(); if let Some(error) = outcome.aborted.as_ref() { return Err(into_engine_error(outcome.used_gas, error)); @@ -331,7 +331,7 @@ impl AuroraRunner { ft_key.as_slice(), self.context.current_account_id.as_bytes(), ] - .concat(); + .concat(); let aurora_balance_value = { let mut current_balance: u128 = trie .get(&aurora_balance_key) @@ -414,7 +414,7 @@ impl AuroraRunner { max_gas_price, gas_token_address, ) - .map(|(result, _)| result) + .map(|(result, _)| result) } pub fn submit_transaction_with_args_profiled( @@ -436,7 +436,7 @@ impl AuroraRunner { CALLER_ACCOUNT_ID, borsh::to_vec(&args).unwrap(), ) - .map(Self::profile_outcome) + .map(Self::profile_outcome) } fn profile_outcome(outcome: VMOutcome) -> (SubmitResult, ExecutionProfile) { @@ -719,7 +719,7 @@ pub fn deploy_runner() -> AuroraRunner { assert!(result.is_ok()); #[cfg(not(feature = "ext-connector"))] - let result = { + let result = { let args = InitCallArgs { prover_account: str_to_account_id("prover.near"), eth_custodian_address: "d045f7e19B2488924B97F9c145b5E51D0D895A65".to_string(), @@ -733,7 +733,7 @@ pub fn deploy_runner() -> AuroraRunner { }; #[cfg(feature = "ext-connector")] - let result = { + let result = { let args = SetEthConnectorContractAccountArgs { account: AccountId::new("aurora_eth_connector.root").unwrap(), withdraw_serialize_type: WithdrawSerializeType::Borsh, @@ -1029,10 +1029,9 @@ pub fn assert_gas_bound(total_gas: u64, tgas_bound: u64) { /// Returns true if `abs(a - b) / max(a, b) <= x / 100`. The implementation is written differently than /// this simpler formula to avoid floating point arithmetic. -pub const fn within_x_percent(x: u64, a: u64, b: u64) -> bool { +pub fn within_x_percent(x: u64, a: u64, b: u64) -> bool { let (larger, smaller) = if a < b { (b, a) } else { (a, b) }; - - (100 / x) * (larger - smaller) <= larger + (100. / x as f64) * (larger as f64 - smaller as f64) <= larger as f64 } fn into_engine_error(gas_used: u64, aborted: &FunctionCallError) -> EngineError { diff --git a/engine/src/engine.rs b/engine/src/engine.rs index 3f4409cf8..ef07d782b 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -1012,17 +1012,17 @@ pub fn submit_with_alt_modexp< handler: &mut P, ) -> EngineResult { #[cfg(feature = "contract")] - let transaction = NormalizedEthTransaction::try_from( + let transaction = NormalizedEthTransaction::try_from( EthTransactionKind::try_from(args.tx_data.as_slice()) .map_err(EngineErrorKind::FailedTransactionParse)?, ) - .map_err(|_e| EngineErrorKind::InvalidSignature)?; + .map_err(|_e| EngineErrorKind::InvalidSignature)?; #[cfg(not(feature = "contract"))] - // The standalone engine must use the backwards compatible parser to reproduce the NEAR state, - // but the contract itself does not need to make such checks because it never executes historical - // transactions. - let transaction: NormalizedEthTransaction = { + // The standalone engine must use the backwards compatible parser to reproduce the NEAR state, + // but the contract itself does not need to make such checks because it never executes historical + // transactions. + let transaction: NormalizedEthTransaction = { let adapter = aurora_engine_transactions::backwards_compatibility::EthTransactionKindAdapter::new( ZERO_ADDRESS_FIX_HEIGHT, @@ -1135,10 +1135,10 @@ pub fn submit_with_alt_modexp< &relayer_address, fixed_gas, ) - .map_err(|e| EngineError { - gas_used, - kind: EngineErrorKind::GasPayment(e), - })?; + .map_err(|e| EngineError { + gas_used, + kind: EngineErrorKind::GasPayment(e), + })?; // return result to user result @@ -1302,9 +1302,9 @@ pub fn setup_deploy_erc20_input( erc20_metadata: Option, ) -> Vec { #[cfg(feature = "error_refund")] - let erc20_contract = include_bytes!("../../etc/eth-contracts/res/EvmErc20V2.bin"); + let erc20_contract = include_bytes!("../../etc/eth-contracts/res/EvmErc20V2.bin"); #[cfg(not(feature = "error_refund"))] - let erc20_contract = include_bytes!("../../etc/eth-contracts/res/EvmErc20.bin"); + let erc20_contract = include_bytes!("../../etc/eth-contracts/res/EvmErc20.bin"); let erc20_admin_address = current_address(current_account_id); let erc20_metadata = erc20_metadata.unwrap_or_default(); @@ -1336,7 +1336,7 @@ pub fn deploy_erc20_token( io, env, ) - .map_err(DeployErc20Error::State)?; + .map_err(DeployErc20Error::State)?; let address = match engine.deploy_code_with_input(input, None, handler) { Ok(result) => match result.status { @@ -1375,7 +1375,7 @@ pub fn mirror_erc20_token( io, env, ) - .map_err(DeployErc20Error::State)?; + .map_err(DeployErc20Error::State)?; let address = match engine.deploy_code_with_input(input, Some(erc20_address), handler) { Ok(result) => match result.status { @@ -1544,10 +1544,16 @@ pub fn get_storage(io: &I, address: &Address, key: &H256, generation: u32 .unwrap_or_default() } +pub fn storage_has_key(io: &I, address: &Address, key: &H256, generation: u32) -> bool { + io.storage_has_key(storage_to_key(address, key, generation).as_ref()) +} + +/// EIP-7610: balance, nonce, code, storage should be empty pub fn is_account_empty(io: &I, address: &Address) -> bool { get_balance(io, address).is_zero() && get_nonce(io, address).is_zero() && get_code_size(io, address) == 0 + && !storage_has_key(io, address, &H256::zero(), get_generation(io, &address)) } /// Increments storage generation for a given address. @@ -1609,10 +1615,10 @@ fn filter_promises_from_logs( logs: T, current_account_id: &AccountId, ) -> Vec -where - T: IntoIterator, - P: PromiseHandler, - I: IO + Copy, + where + T: IntoIterator, + P: PromiseHandler, + I: IO + Copy, { let mut previous_promise: Option = None; logs.into_iter() @@ -1915,6 +1921,28 @@ impl<'env, I: IO + Copy, E: Env, M: ModExpAlgorithm> Backend for Engine<'env, I, result } + /// Check is storage empty for address + /// EIP-7610: non-empty storGE + fn is_empty_storage(&self, address: H160) -> bool { + let address = Address::new(address); + // As we can't read all storage data for account we assuming that if storage exists + // `index = 0` always true + let index = H256::zero(); + let generation = *self + .generation_cache + .borrow_mut() + .entry(address) + .or_insert_with(|| get_generation(&self.io, &address)); + // First we're checking cache to not produce read-storage operation + if self + .contract_storage_cache + .borrow() + .contains_key((address, index)) { + return false; + } + !storage_has_key(&self.io, &address, &index, generation) + } + /// Get original storage value of address at index, if available. /// /// Since `SputnikVM` collects storage changes in memory until the transaction is over, @@ -1935,10 +1963,10 @@ impl<'env, I: IO + Copy, E: Env, M: ModExpAlgorithm> Backend for Engine<'env, I, impl<'env, J: IO + Copy, E: Env, M: ModExpAlgorithm> ApplyBackend for Engine<'env, J, E, M> { fn apply(&mut self, values: A, _logs: L, delete_empty: bool) - where - A: IntoIterator>, - I: IntoIterator, - L: IntoIterator, + where + A: IntoIterator>, + I: IntoIterator, + L: IntoIterator, { let mut writes_counter: usize = 0; let mut code_bytes_written: usize = 0; @@ -2046,7 +2074,7 @@ impl<'env, J: IO + Copy, E: Env, M: ModExpAlgorithm> ApplyBackend for Engine<'en // These variable are only used if logging feature is enabled. // In production logging is always enabled, so we can ignore the warnings. #[allow(unused_variables)] - let total_bytes = 32 * writes_counter + code_bytes_written; + let total_bytes = 32 * writes_counter + code_bytes_written; #[allow(unused_assignments)] if code_bytes_written > 0 { writes_counter += 1; @@ -2742,8 +2770,8 @@ mod tests { let public_key = serde_json::from_str::( r#"{"public_key":"ed25519:DcA2MzgpJbrUATQLLceocVckhhAqrkingax4oJ9kZ847"}"#, ) - .map(|args| args.public_key) - .unwrap(); + .map(|args| args.public_key) + .unwrap(); let result = remove_function_call_key(&mut io, &public_key); assert!(result.is_err()); // should fail because the key doesn't exist yet. From fd74e702f12bc6be15e44c4c4b21e07d57fe3fe2 Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Fri, 28 Jun 2024 12:37:37 +0200 Subject: [PATCH 2/7] Gas cost optimizations for EVM --- Cargo.lock | 8 ++--- Cargo.toml | 9 +++-- engine-precompiles/src/xcc.rs | 2 +- engine-sdk/src/caching.rs | 4 +-- engine-tests/src/tests/repro.rs | 10 +++--- engine-tests/src/tests/uniswap.rs | 2 +- engine-tests/src/utils/mod.rs | 15 +++++---- engine/src/engine.rs | 55 ++++++++++++++++--------------- 8 files changed, 53 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 399a7bf6a..c0443e2a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1758,7 +1758,7 @@ dependencies = [ [[package]] name = "evm" version = "0.43.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.44.0-alpha.0#bee8e90ce9bb23edbfc731e4840018df5d1691b9" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.44.0-alpha.2#9763a1d051592ba95d2b8796edcb4735bc73ca72" dependencies = [ "auto_impl", "environmental", @@ -1778,7 +1778,7 @@ dependencies = [ [[package]] name = "evm-core" version = "0.43.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.44.0-alpha.0#bee8e90ce9bb23edbfc731e4840018df5d1691b9" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.44.0-alpha.2#9763a1d051592ba95d2b8796edcb4735bc73ca72" dependencies = [ "parity-scale-codec", "primitive-types 0.12.2", @@ -1789,7 +1789,7 @@ dependencies = [ [[package]] name = "evm-gasometer" version = "0.43.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.44.0-alpha.0#bee8e90ce9bb23edbfc731e4840018df5d1691b9" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.44.0-alpha.2#9763a1d051592ba95d2b8796edcb4735bc73ca72" dependencies = [ "environmental", "evm-core", @@ -1800,7 +1800,7 @@ dependencies = [ [[package]] name = "evm-runtime" version = "0.43.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.44.0-alpha.0#bee8e90ce9bb23edbfc731e4840018df5d1691b9" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.44.0-alpha.2#9763a1d051592ba95d2b8796edcb4735bc73ca72" dependencies = [ "auto_impl", "environmental", diff --git a/Cargo.toml b/Cargo.toml index cd67ca2a9..758700e59 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,11 +31,10 @@ byte-slice-cast = { version = "1", default-features = false } criterion = "0.5" digest = "0.10" ethabi = { version = "18", default-features = false } -# ref = "000196f608568f6ea558adbcdc0c6cb5819f82b4" -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.0-alpha.0", default-features = false } -evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.0-alpha.0", default-features = false, features = ["std"] } -evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.0-alpha.0", default-features = false, features = ["std", "tracing"] } -evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.0-alpha.0", default-features = false, features = ["std", "tracing"] } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.0-alpha.2", default-features = false } +evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.0-alpha.2", default-features = false, features = ["std"] } +evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.0-alpha.2", default-features = false, features = ["std", "tracing"] } +evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.0-alpha.2", default-features = false, features = ["std", "tracing"] } fixed-hash = { version = "0.8", default-features = false } function_name = "0.3" git2 = "0.18" diff --git a/engine-precompiles/src/xcc.rs b/engine-precompiles/src/xcc.rs index 540274588..9deb62595 100644 --- a/engine-precompiles/src/xcc.rs +++ b/engine-precompiles/src/xcc.rs @@ -338,7 +338,7 @@ mod tests { let amount = U256::from_big_endian(&amount); #[allow(deprecated)] - let transfer_from_function = ethabi::Function { + let transfer_from_function = ethabi::Function { name: "transferFrom".into(), inputs: vec![ ethabi::Param { diff --git a/engine-sdk/src/caching.rs b/engine-sdk/src/caching.rs index f28a3ebc7..bedf60954 100644 --- a/engine-sdk/src/caching.rs +++ b/engine-sdk/src/caching.rs @@ -11,7 +11,7 @@ impl FullCache { self.inner.entry(k).or_insert_with(f) } - pub fn contains_key(&self, k: K) -> bool { - self.inner.contains_key(&k) + pub fn contains_key(&self, k: &K) -> bool { + self.inner.contains_key(k) } } diff --git a/engine-tests/src/tests/repro.rs b/engine-tests/src/tests/repro.rs index 5a04e2371..3ad007b31 100644 --- a/engine-tests/src/tests/repro.rs +++ b/engine-tests/src/tests/repro.rs @@ -26,7 +26,7 @@ fn repro_GdASJ3KESs() { block_timestamp: 1_645_717_564_644_206_730, input_path: "src/tests/res/input_GdASJ3KESs.hex", evm_gas_used: 706_713, - near_gas_used: 117, + near_gas_used: 116, }); } @@ -51,7 +51,7 @@ fn repro_8ru7VEA() { block_timestamp: 1_648_829_935_343_349_589, input_path: "src/tests/res/input_8ru7VEA.hex", evm_gas_used: 1_732_181, - near_gas_used: 211, + near_gas_used: 210, }); } @@ -71,7 +71,7 @@ fn repro_FRcorNv() { block_timestamp: 1_650_960_438_774_745_116, input_path: "src/tests/res/input_FRcorNv.hex", evm_gas_used: 1_239_721, - near_gas_used: 171, + near_gas_used: 170, }); } @@ -106,7 +106,7 @@ fn repro_D98vwmi() { block_timestamp: 1_651_753_443_421_003_245, input_path: "src/tests/res/input_D98vwmi.hex", evm_gas_used: 1_035_348, - near_gas_used: 173, + near_gas_used: 172, }); } @@ -125,7 +125,7 @@ fn repro_Emufid2() { block_timestamp: 1_662_118_048_636_713_538, input_path: "src/tests/res/input_Emufid2.hex", evm_gas_used: 1_156_364, - near_gas_used: 296, + near_gas_used: 295, }); } diff --git a/engine-tests/src/tests/uniswap.rs b/engine-tests/src/tests/uniswap.rs index 4af587f44..ffae3ab1c 100644 --- a/engine-tests/src/tests/uniswap.rs +++ b/engine-tests/src/tests/uniswap.rs @@ -38,7 +38,7 @@ fn test_uniswap_input_multihop() { let (_amount_out, _evm_gas, profile) = context.exact_input(&tokens, INPUT_AMOUNT.into()); - assert_eq!(110, profile.all_gas() / 1_000_000_000_000); + assert_eq!(109, profile.all_gas() / 1_000_000_000_000); } #[test] diff --git a/engine-tests/src/utils/mod.rs b/engine-tests/src/utils/mod.rs index 267cae0a5..2d0493d0c 100644 --- a/engine-tests/src/utils/mod.rs +++ b/engine-tests/src/utils/mod.rs @@ -150,7 +150,7 @@ impl<'a> OneShotAuroraRunner<'a> { &[], Some(&self.base.cache), ) - .unwrap(); + .unwrap(); if let Some(aborted) = outcome.aborted.as_ref() { Err(into_engine_error(outcome.used_gas, aborted)) @@ -226,7 +226,7 @@ impl AuroraRunner { &vm_promise_results, Some(&self.cache), ) - .unwrap(); + .unwrap(); if let Some(error) = outcome.aborted.as_ref() { return Err(into_engine_error(outcome.used_gas, error)); @@ -331,7 +331,7 @@ impl AuroraRunner { ft_key.as_slice(), self.context.current_account_id.as_bytes(), ] - .concat(); + .concat(); let aurora_balance_value = { let mut current_balance: u128 = trie .get(&aurora_balance_key) @@ -414,7 +414,7 @@ impl AuroraRunner { max_gas_price, gas_token_address, ) - .map(|(result, _)| result) + .map(|(result, _)| result) } pub fn submit_transaction_with_args_profiled( @@ -436,7 +436,7 @@ impl AuroraRunner { CALLER_ACCOUNT_ID, borsh::to_vec(&args).unwrap(), ) - .map(Self::profile_outcome) + .map(Self::profile_outcome) } fn profile_outcome(outcome: VMOutcome) -> (SubmitResult, ExecutionProfile) { @@ -719,7 +719,7 @@ pub fn deploy_runner() -> AuroraRunner { assert!(result.is_ok()); #[cfg(not(feature = "ext-connector"))] - let result = { + let result = { let args = InitCallArgs { prover_account: str_to_account_id("prover.near"), eth_custodian_address: "d045f7e19B2488924B97F9c145b5E51D0D895A65".to_string(), @@ -733,7 +733,7 @@ pub fn deploy_runner() -> AuroraRunner { }; #[cfg(feature = "ext-connector")] - let result = { + let result = { let args = SetEthConnectorContractAccountArgs { account: AccountId::new("aurora_eth_connector.root").unwrap(), withdraw_serialize_type: WithdrawSerializeType::Borsh, @@ -1029,6 +1029,7 @@ pub fn assert_gas_bound(total_gas: u64, tgas_bound: u64) { /// Returns true if `abs(a - b) / max(a, b) <= x / 100`. The implementation is written differently than /// this simpler formula to avoid floating point arithmetic. +#[allow(clippy::cast_precision_loss, clippy::as_conversions)] pub fn within_x_percent(x: u64, a: u64, b: u64) -> bool { let (larger, smaller) = if a < b { (b, a) } else { (a, b) }; (100. / x as f64) * (larger as f64 - smaller as f64) <= larger as f64 diff --git a/engine/src/engine.rs b/engine/src/engine.rs index ef07d782b..1c2d8dd3f 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -1012,17 +1012,17 @@ pub fn submit_with_alt_modexp< handler: &mut P, ) -> EngineResult { #[cfg(feature = "contract")] - let transaction = NormalizedEthTransaction::try_from( + let transaction = NormalizedEthTransaction::try_from( EthTransactionKind::try_from(args.tx_data.as_slice()) .map_err(EngineErrorKind::FailedTransactionParse)?, ) - .map_err(|_e| EngineErrorKind::InvalidSignature)?; + .map_err(|_e| EngineErrorKind::InvalidSignature)?; #[cfg(not(feature = "contract"))] - // The standalone engine must use the backwards compatible parser to reproduce the NEAR state, - // but the contract itself does not need to make such checks because it never executes historical - // transactions. - let transaction: NormalizedEthTransaction = { + // The standalone engine must use the backwards compatible parser to reproduce the NEAR state, + // but the contract itself does not need to make such checks because it never executes historical + // transactions. + let transaction: NormalizedEthTransaction = { let adapter = aurora_engine_transactions::backwards_compatibility::EthTransactionKindAdapter::new( ZERO_ADDRESS_FIX_HEIGHT, @@ -1135,10 +1135,10 @@ pub fn submit_with_alt_modexp< &relayer_address, fixed_gas, ) - .map_err(|e| EngineError { - gas_used, - kind: EngineErrorKind::GasPayment(e), - })?; + .map_err(|e| EngineError { + gas_used, + kind: EngineErrorKind::GasPayment(e), + })?; // return result to user result @@ -1302,9 +1302,9 @@ pub fn setup_deploy_erc20_input( erc20_metadata: Option, ) -> Vec { #[cfg(feature = "error_refund")] - let erc20_contract = include_bytes!("../../etc/eth-contracts/res/EvmErc20V2.bin"); + let erc20_contract = include_bytes!("../../etc/eth-contracts/res/EvmErc20V2.bin"); #[cfg(not(feature = "error_refund"))] - let erc20_contract = include_bytes!("../../etc/eth-contracts/res/EvmErc20.bin"); + let erc20_contract = include_bytes!("../../etc/eth-contracts/res/EvmErc20.bin"); let erc20_admin_address = current_address(current_account_id); let erc20_metadata = erc20_metadata.unwrap_or_default(); @@ -1336,7 +1336,7 @@ pub fn deploy_erc20_token( io, env, ) - .map_err(DeployErc20Error::State)?; + .map_err(DeployErc20Error::State)?; let address = match engine.deploy_code_with_input(input, None, handler) { Ok(result) => match result.status { @@ -1375,7 +1375,7 @@ pub fn mirror_erc20_token( io, env, ) - .map_err(DeployErc20Error::State)?; + .map_err(DeployErc20Error::State)?; let address = match engine.deploy_code_with_input(input, Some(erc20_address), handler) { Ok(result) => match result.status { @@ -1553,7 +1553,7 @@ pub fn is_account_empty(io: &I, address: &Address) -> bool { get_balance(io, address).is_zero() && get_nonce(io, address).is_zero() && get_code_size(io, address) == 0 - && !storage_has_key(io, address, &H256::zero(), get_generation(io, &address)) + && !storage_has_key(io, address, &H256::zero(), get_generation(io, address)) } /// Increments storage generation for a given address. @@ -1615,10 +1615,10 @@ fn filter_promises_from_logs( logs: T, current_account_id: &AccountId, ) -> Vec - where - T: IntoIterator, - P: PromiseHandler, - I: IO + Copy, +where + T: IntoIterator, + P: PromiseHandler, + I: IO + Copy, { let mut previous_promise: Option = None; logs.into_iter() @@ -1937,7 +1937,8 @@ impl<'env, I: IO + Copy, E: Env, M: ModExpAlgorithm> Backend for Engine<'env, I, if self .contract_storage_cache .borrow() - .contains_key((address, index)) { + .contains_key(&(address, index)) + { return false; } !storage_has_key(&self.io, &address, &index, generation) @@ -1963,10 +1964,10 @@ impl<'env, I: IO + Copy, E: Env, M: ModExpAlgorithm> Backend for Engine<'env, I, impl<'env, J: IO + Copy, E: Env, M: ModExpAlgorithm> ApplyBackend for Engine<'env, J, E, M> { fn apply(&mut self, values: A, _logs: L, delete_empty: bool) - where - A: IntoIterator>, - I: IntoIterator, - L: IntoIterator, + where + A: IntoIterator>, + I: IntoIterator, + L: IntoIterator, { let mut writes_counter: usize = 0; let mut code_bytes_written: usize = 0; @@ -2074,7 +2075,7 @@ impl<'env, J: IO + Copy, E: Env, M: ModExpAlgorithm> ApplyBackend for Engine<'en // These variable are only used if logging feature is enabled. // In production logging is always enabled, so we can ignore the warnings. #[allow(unused_variables)] - let total_bytes = 32 * writes_counter + code_bytes_written; + let total_bytes = 32 * writes_counter + code_bytes_written; #[allow(unused_assignments)] if code_bytes_written > 0 { writes_counter += 1; @@ -2770,8 +2771,8 @@ mod tests { let public_key = serde_json::from_str::( r#"{"public_key":"ed25519:DcA2MzgpJbrUATQLLceocVckhhAqrkingax4oJ9kZ847"}"#, ) - .map(|args| args.public_key) - .unwrap(); + .map(|args| args.public_key) + .unwrap(); let result = remove_function_call_key(&mut io, &public_key); assert!(result.is_err()); // should fail because the key doesn't exist yet. From ab483162d5434fd7a6647aa82639b31c120d0089 Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Mon, 1 Jul 2024 20:08:07 +0200 Subject: [PATCH 3/7] Tests: within_x_percent - removed f64 casting --- engine-tests/src/utils/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/engine-tests/src/utils/mod.rs b/engine-tests/src/utils/mod.rs index 2d0493d0c..9633d95e9 100644 --- a/engine-tests/src/utils/mod.rs +++ b/engine-tests/src/utils/mod.rs @@ -1029,10 +1029,9 @@ pub fn assert_gas_bound(total_gas: u64, tgas_bound: u64) { /// Returns true if `abs(a - b) / max(a, b) <= x / 100`. The implementation is written differently than /// this simpler formula to avoid floating point arithmetic. -#[allow(clippy::cast_precision_loss, clippy::as_conversions)] -pub fn within_x_percent(x: u64, a: u64, b: u64) -> bool { +pub const fn within_x_percent(x: u64, a: u64, b: u64) -> bool { let (larger, smaller) = if a < b { (b, a) } else { (a, b) }; - (100. / x as f64) * (larger as f64 - smaller as f64) <= larger as f64 + 100 * (larger - smaller) <= larger * x } fn into_engine_error(gas_used: u64, aborted: &FunctionCallError) -> EngineError { From b93ff81c906730be4bb75eb89c6b401ee0217933 Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Tue, 2 Jul 2024 15:46:46 +0200 Subject: [PATCH 4/7] Fix typo --- engine/src/engine.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/engine/src/engine.rs b/engine/src/engine.rs index 1c2d8dd3f..8c37b460b 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -1921,8 +1921,8 @@ impl<'env, I: IO + Copy, E: Env, M: ModExpAlgorithm> Backend for Engine<'env, I, result } - /// Check is storage empty for address - /// EIP-7610: non-empty storGE + /// Check is storage empty for the address + /// EIP-7610: non-empty storage fn is_empty_storage(&self, address: H160) -> bool { let address = Address::new(address); // As we can't read all storage data for account we assuming that if storage exists From 32c09d8b29193cd38dd74b5f2ed19751b4fb511f Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Wed, 3 Jul 2024 19:56:14 +0200 Subject: [PATCH 5/7] Set SputnikVM to v0.44.1 --- Cargo.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 758700e59..0f96121bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,10 +31,10 @@ byte-slice-cast = { version = "1", default-features = false } criterion = "0.5" digest = "0.10" ethabi = { version = "18", default-features = false } -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.0-alpha.2", default-features = false } -evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.0-alpha.2", default-features = false, features = ["std"] } -evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.0-alpha.2", default-features = false, features = ["std", "tracing"] } -evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.0-alpha.2", default-features = false, features = ["std", "tracing"] } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.1", default-features = false } +evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.1", default-features = false, features = ["std"] } +evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.1", default-features = false, features = ["std", "tracing"] } +evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.1", default-features = false, features = ["std", "tracing"] } fixed-hash = { version = "0.8", default-features = false } function_name = "0.3" git2 = "0.18" From 6c76f7b7ceebae411599378401b8d17b15d7bcb1 Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Wed, 3 Jul 2024 20:33:43 +0200 Subject: [PATCH 6/7] Set SputnikVM to v0.43.1 --- Cargo.lock | 8 ++++---- Cargo.toml | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c0443e2a5..cc75c819d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1758,7 +1758,7 @@ dependencies = [ [[package]] name = "evm" version = "0.43.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.44.0-alpha.2#9763a1d051592ba95d2b8796edcb4735bc73ca72" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.43.1-aurora#a201e15e56eddac80872045e6b5015ee3859c900" dependencies = [ "auto_impl", "environmental", @@ -1778,7 +1778,7 @@ dependencies = [ [[package]] name = "evm-core" version = "0.43.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.44.0-alpha.2#9763a1d051592ba95d2b8796edcb4735bc73ca72" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.43.1-aurora#a201e15e56eddac80872045e6b5015ee3859c900" dependencies = [ "parity-scale-codec", "primitive-types 0.12.2", @@ -1789,7 +1789,7 @@ dependencies = [ [[package]] name = "evm-gasometer" version = "0.43.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.44.0-alpha.2#9763a1d051592ba95d2b8796edcb4735bc73ca72" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.43.1-aurora#a201e15e56eddac80872045e6b5015ee3859c900" dependencies = [ "environmental", "evm-core", @@ -1800,7 +1800,7 @@ dependencies = [ [[package]] name = "evm-runtime" version = "0.43.0" -source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.44.0-alpha.2#9763a1d051592ba95d2b8796edcb4735bc73ca72" +source = "git+https://github.com/aurora-is-near/sputnikvm.git?tag=v0.43.1-aurora#a201e15e56eddac80872045e6b5015ee3859c900" dependencies = [ "auto_impl", "environmental", diff --git a/Cargo.toml b/Cargo.toml index 0f96121bb..cbb99e982 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,10 +31,10 @@ byte-slice-cast = { version = "1", default-features = false } criterion = "0.5" digest = "0.10" ethabi = { version = "18", default-features = false } -evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.1", default-features = false } -evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.1", default-features = false, features = ["std"] } -evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.1", default-features = false, features = ["std", "tracing"] } -evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.44.1", default-features = false, features = ["std", "tracing"] } +evm = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.43.1-aurora", default-features = false } +evm-core = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.43.1-aurora", default-features = false, features = ["std"] } +evm-gasometer = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.43.1-aurora", default-features = false, features = ["std", "tracing"] } +evm-runtime = { git = "https://github.com/aurora-is-near/sputnikvm.git", tag = "v0.43.1-aurora", default-features = false, features = ["std", "tracing"] } fixed-hash = { version = "0.8", default-features = false } function_name = "0.3" git2 = "0.18" From 871037ae92162b34b7f0ec165dd66e5cadd9291b Mon Sep 17 00:00:00 2001 From: Evgeny Ukhanov Date: Tue, 13 Aug 2024 18:03:19 +0200 Subject: [PATCH 7/7] Fix gas costs --- engine-tests/src/tests/repro.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/engine-tests/src/tests/repro.rs b/engine-tests/src/tests/repro.rs index ba062e595..7c1aa29cd 100644 --- a/engine-tests/src/tests/repro.rs +++ b/engine-tests/src/tests/repro.rs @@ -26,7 +26,7 @@ fn repro_GdASJ3KESs() { block_timestamp: 1_645_717_564_644_206_730, input_path: "src/tests/res/input_GdASJ3KESs.hex", evm_gas_used: 706_713, - near_gas_used: 114, + near_gas_used: 113, }); } @@ -71,7 +71,7 @@ fn repro_FRcorNv() { block_timestamp: 1_650_960_438_774_745_116, input_path: "src/tests/res/input_FRcorNv.hex", evm_gas_used: 1_239_721, - near_gas_used: 166, + near_gas_used: 165, }); } @@ -88,7 +88,7 @@ fn repro_5bEgfRQ() { block_timestamp: 1_651_073_772_931_594_646, input_path: "src/tests/res/input_5bEgfRQ.hex", evm_gas_used: 6_414_105, - near_gas_used: 646, + near_gas_used: 645, }); } @@ -125,7 +125,7 @@ fn repro_Emufid2() { block_timestamp: 1_662_118_048_636_713_538, input_path: "src/tests/res/input_Emufid2.hex", evm_gas_used: 1_156_364, - near_gas_used: 292, + near_gas_used: 291, }); }