diff --git a/README.md b/README.md index 5be3e40..877baf3 100644 --- a/README.md +++ b/README.md @@ -199,12 +199,3 @@ test_global_snapshot[x_fns1-False-slowseq take and restore snapshot] 315.481 test_global_snapshot[x_fns3-True-slowseq no snapshot] 315.5748 (3.32) 328.8318 (3.24) 321.7635 (3.31) 5.0368 (2.12) 321.1631 (3.34) 7.1114 (2.42) 2;0 3.1079 (0.30) 5 1 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ``` - - -## Changes - -### 1.0.0 - -Breaking changes: -- `deterministic_deploy` signature is now changed to `deterministic_deploy(contract_deploy_code, owner=None, data=None, value=None, init_value=None, deploy_to_address=None)`, i.e., `salt` is removed. [Related to [REVM-1182](https://github.com/bluealloy/revm/issues/1182)]. If you want to similate the previous behaviour, it's suggested to use the `deploy_to_address` parameter to specify the address where the contract will be deployed. -- `enabled` in `REVMConfig` is removed. To disable all instrumentation, use diff --git a/benches/infinite_loop.rs b/benches/infinite_loop.rs index 4538866..68d4f37 100644 --- a/benches/infinite_loop.rs +++ b/benches/infinite_loop.rs @@ -1,5 +1,5 @@ use criterion::{criterion_group, criterion_main, Criterion}; -use primitive_types::{H160, U256}; +use primitive_types::U256; use revm::primitives::Address; use tinyevm::{fn_sig_to_prefix, TinyEVM, UZERO}; diff --git a/src/lib.rs b/src/lib.rs index d35c08a..9b9135f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,7 +18,7 @@ use lazy_static::lazy_static; use num_bigint::BigInt; use pyo3::prelude::*; use response::{Response, SeenPcsMap, WrappedBug, WrappedHeuristics, WrappedMissedBranch}; -use revm::inspector_handle_register; +use revm::{inspector_handle_register, primitives::B256}; use thread_local::ThreadLocal; use tokio::runtime::Runtime; use uuid::Uuid; @@ -39,7 +39,7 @@ pub mod instrument; /// Provide response data structure from EVM pub mod response; pub use common::*; -use hex::ToHex; +use hex::{FromHex, ToHex}; use instrument::{ bug_inspector::BugInspector, log_inspector::LogInspector, BugData, Heuristics, InstrumentConfig, }; @@ -705,19 +705,20 @@ impl TinyEVM { /// - `owner`: Owner address as a 20-byte array encoded as hex string /// - `data`: (Optional, default empty) Constructor arguments encoded as hex string. /// - `value`: (Optional, default 0) a U256. Set the value to be included in the contract creation transaction. - /// - `deploy_to_address`: when provided, change the address of the deployed contract to this address + /// - `deploy_to_address`: when provided, change the address of the deployed contract to this address, otherwise deploy to a an address created using `owner.CREATE2(a_fixed_salt, codehash)`. /// - This requires the constructor to be payable. /// - The transaction sender (owner) must have enough balance /// - `init_value`: (Optional) BigInt. Override the initial balance of the contract to this value. /// /// Returns a list consisting of 4 items `[reason, address-as-byte-array, bug_data, heuristics]` - #[pyo3(signature = (contract_deploy_code, owner=None, data=None, value=None, init_value=None, deploy_to_address=None))] + #[pyo3(signature = (contract_deploy_code, salt=None, owner=None, data=None, value=None, init_value=None, deploy_to_address=None))] pub fn deterministic_deploy( &mut self, contract_deploy_code: String, // variable length - owner: Option, // h160 as hex string - data: Option, // variable length + salt: Option, // h256 as hex string, has no effect if deploy_to_address is provided + owner: Option, // h160 as hex string + data: Option, // variable length value: Option, init_value: Option, deploy_to_address: Option, @@ -742,9 +743,23 @@ impl TinyEVM { let value = value.unwrap_or_default(); let mut contract_bytecode = contract_deploy_code.to_vec(); contract_bytecode.extend(data); - let force_address: Option
= deploy_to_address + + let salt = { + if let Some(salt) = salt { + let salt = &salt; + B256::from_hex(salt)? + } else { + B256::ZERO + } + }; + + let force_address: Address = deploy_to_address .map(|s| Address::from_str(&s)) - .transpose()?; + .transpose()? + .unwrap_or_else(|| { + let codehash = keccak256(&contract_bytecode); + owner.create2(salt, codehash) + }); let resp = { let resp = self.deploy_helper( @@ -752,7 +767,7 @@ impl TinyEVM { contract_bytecode, bigint_to_ruint_u256(&value)?, None, - force_address, + Some(force_address), )?; if let Some(balance) = init_value { diff --git a/tests/test_account_snapshot.py b/tests/test_account_snapshot.py index 6083e92..5e9b303 100644 --- a/tests/test_account_snapshot.py +++ b/tests/test_account_snapshot.py @@ -65,12 +65,13 @@ def deploy_contract(salt=None, owner='0x388C818CA8B9251b393131C08a736A67ccB19297 data = encode(['uint256', 'string', 'string', 'uint256'], [_initialSupply, _name, _symbol, _decimals]).hex() + salt = None value = None init_value = 0x223312323 tevm.set_balance(owner, 0xffff0000000000000000000000000000000000000000000000000000000000ff) - resp = tevm.deterministic_deploy(binary, owner, data, value, init_value) + resp = tevm.deterministic_deploy(binary, salt, owner, data, value, init_value) tprint('Deployment resp: {}'.format(resp)) assert resp.success diff --git a/tests/test_global_snapshot.py b/tests/test_global_snapshot.py index 8ce3b4d..07ecb0d 100644 --- a/tests/test_global_snapshot.py +++ b/tests/test_global_snapshot.py @@ -70,10 +70,11 @@ def deploy_contract(salt=None, owner='0x388C818CA8B9251b393131C08a736A67ccB19297 tevm.set_balance(owner, 0xffff0000000000000000000000000000000000000000000000000000000000ff) + salt = None data = '' value = None init_value = None - resp = tevm.deterministic_deploy(binary, owner, data, value, init_value) + resp = tevm.deterministic_deploy(binary, salt, owner, data, value, init_value) tprint('Deployment resp: {}'.format(resp)) assert resp.success diff --git a/tests/test_multithreading.py b/tests/test_multithreading.py index 5886ce7..33817c4 100644 --- a/tests/test_multithreading.py +++ b/tests/test_multithreading.py @@ -7,6 +7,8 @@ from concurrent.futures import ProcessPoolExecutor +salt = None + def handle_exception(exc_type, exc_value, exc_traceback): if issubclass(exc_type, KeyboardInterrupt): sys.__excepthook__(exc_type, exc_value, exc_traceback) @@ -33,7 +35,6 @@ def run_test(): tevm = tinyevm.TinyEVM() contract_bytecode = open('tests/contracts/C.hex').read() - salt = None owner = '0x388C818CA8B9251b393131C08a736A67ccB19297' data = None value = None @@ -43,8 +44,7 @@ def run_test(): balance = tevm.get_balance(owner) tprint('balance before deployment: {}'.format(balance)) - # todo update response object - resp = tevm.deterministic_deploy(contract_bytecode, owner, data, value, init_value) + resp = tevm.deterministic_deploy(contract_bytecode, salt, owner, data, value, init_value) tprint('Deployment resp: {}'.format(resp)) assert resp.success @@ -75,7 +75,6 @@ def run_infinite_loop(): tevm = tinyevm.TinyEVM() contract_bytecode = open('tests/contracts/infinite_loop_Test.hex').read() - salt = None owner = '0x388C818CA8B9251b393131C08a736A67ccB19297' data = None value = None @@ -86,7 +85,7 @@ def run_infinite_loop(): tprint('balance before deployment: {}'.format(balance)) # todo update response object - resp = tevm.deterministic_deploy(contract_bytecode, owner, data, value, init_value) + resp = tevm.deterministic_deploy(contract_bytecode, salt, owner, data, value, init_value) tprint('Deployment resp: {}'.format(resp)) assert resp.success diff --git a/tests/test_tinyevm.py b/tests/test_tinyevm.py index 6609172..268824f 100644 --- a/tests/test_tinyevm.py +++ b/tests/test_tinyevm.py @@ -2,6 +2,8 @@ import unittest from Crypto.Hash import keccak +salt = None + def fn_sig(sig): k = keccak.new(digest_bits=256) k.update(sig.encode()) @@ -56,7 +58,7 @@ def test_get_change_tx_gas_limit(self): init_value = 0x223312323 try: - tevm.deterministic_deploy(contract_bytecode, owner, data, value, init_value) + tevm.deterministic_deploy(contract_bytecode, salt, owner, data, value, init_value) except RuntimeError as e: tprint('Expected error: {}'.format(e)) assert 'OutOfGas' in str(e), 'should raise out of gas error' @@ -79,7 +81,6 @@ def test_deployment(self): tevm = tinyevm.TinyEVM() contract_bytecode = open('tests/contracts/C.hex').read() - salt = None owner = '0x388C818CA8B9251b393131C08a736A67ccB19297' data = None value = None @@ -90,7 +91,7 @@ def test_deployment(self): tprint('balance before deployment: {}'.format(balance)) # todo update response object - resp = tevm.deterministic_deploy(contract_bytecode, owner, data, value, init_value) + resp = tevm.deterministic_deploy(contract_bytecode, salt, owner, data, value, init_value) tprint('Deployment resp: {}'.format(resp)) bugs = list(resp.bug_data)