diff --git a/engine-tests/src/tests/uniswap.rs b/engine-tests/src/tests/uniswap.rs index 49fdb41f2..21b7dfc28 100644 --- a/engine-tests/src/tests/uniswap.rs +++ b/engine-tests/src/tests/uniswap.rs @@ -57,7 +57,7 @@ fn test_uniswap_exact_output() { test_utils::assert_gas_bound(profile.all_gas(), 58); let wasm_fraction = 100 * profile.wasm_gas() / profile.all_gas(); assert!( - 20 <= wasm_fraction && wasm_fraction <= 30, + 25 <= wasm_fraction && wasm_fraction <= 35, "{}% is not between 20% and 30%", wasm_fraction ); diff --git a/engine/src/engine.rs b/engine/src/engine.rs index 2d1a9181f..b0c630b7e 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -408,6 +408,7 @@ pub struct Engine<'env, I: IO, E: Env> { env: &'env E, generation_cache: RefCell>, account_info_cache: RefCell>, + contract_code_cache: RefCell>>, contract_storage_cache: RefCell>, } @@ -442,6 +443,7 @@ impl<'env, I: IO + Copy, E: Env> Engine<'env, I, E> { env, generation_cache: RefCell::new(BTreeMap::new()), account_info_cache: RefCell::new(DupCache::default()), + contract_code_cache: RefCell::new(DupCache::default()), contract_storage_cache: RefCell::new(PairDupCache::default()), } } @@ -1420,7 +1422,18 @@ impl<'env, I: IO + Copy, E: Env> evm::backend::Backend for Engine<'env, I, E> { /// Checks if an address exists. fn exists(&self, address: H160) -> bool { - !is_account_empty(&self.io, &Address::new(address)) + let address = Address::new(address); + let mut cache = self.account_info_cache.borrow_mut(); + let basic_info = cache.get_or_insert_with(&address, || Basic { + nonce: get_nonce(&self.io, &address), + balance: get_balance(&self.io, &address).raw(), + }); + if !basic_info.balance.is_zero() || !basic_info.nonce.is_zero() { + return false; + } + let mut cache = self.contract_code_cache.borrow_mut(); + let code = cache.get_or_insert_with(&address, || get_code(&self.io, &address)); + !code.is_empty() } /// Returns basic account information. @@ -1439,7 +1452,11 @@ impl<'env, I: IO + Copy, E: Env> evm::backend::Backend for Engine<'env, I, E> { /// Returns the code of the contract from an address. fn code(&self, address: H160) -> Vec { - get_code(&self.io, &Address::new(address)) + let address = Address::new(address); + self.contract_code_cache + .borrow_mut() + .get_or_insert_with(&address, || get_code(&self.io, &address)) + .clone() } /// Get storage value of address at index.