diff --git a/Cargo.lock b/Cargo.lock index 527ccee7b..faffae615 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2249,8 +2249,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.43.1-aurora#a201e15e56eddac80872045e6b5015ee3859c900" dependencies = [ "auto_impl", "environmental", @@ -2269,8 +2269,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.43.1-aurora#a201e15e56eddac80872045e6b5015ee3859c900" dependencies = [ "parity-scale-codec", "primitive-types 0.12.2", @@ -2280,8 +2280,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.43.1-aurora#a201e15e56eddac80872045e6b5015ee3859c900" dependencies = [ "environmental", "evm-core", @@ -2291,8 +2291,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.43.1-aurora#a201e15e56eddac80872045e6b5015ee3859c900" dependencies = [ "auto_impl", "environmental", diff --git a/Cargo.toml b/Cargo.toml index 434b7c9d4..7962fd27c 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.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"] } +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.19" diff --git a/engine-precompiles/src/xcc.rs b/engine-precompiles/src/xcc.rs index 6bcead2d6..9deb62595 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`. diff --git a/engine-sdk/src/caching.rs b/engine-sdk/src/caching.rs index d2baa6c6a..bedf60954 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 649932c90..978b82298 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/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, }); } diff --git a/engine-tests/src/utils/mod.rs b/engine-tests/src/utils/mod.rs index 0972e8cb1..7c36bc40a 100644 --- a/engine-tests/src/utils/mod.rs +++ b/engine-tests/src/utils/mod.rs @@ -1027,8 +1027,7 @@ pub fn assert_gas_bound(total_gas: u64, tgas_bound: u64) { /// this simpler formula to avoid floating point arithmetic. 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) * (larger - smaller) <= larger + 100 * (larger - smaller) <= larger * x } fn into_engine_error(gas_used: u64, aborted: &FunctionCallError) -> EngineError { diff --git a/engine/src/engine.rs b/engine/src/engine.rs index c3c0ba60e..7b799f526 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -1543,10 +1543,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. @@ -1914,6 +1920,29 @@ impl<'env, I: IO + Copy, E: Env, M: ModExpAlgorithm> Backend for Engine<'env, I, result } + /// 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 + // `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,