From 673d5e4afdb54c3d714fb2d31d6392189c8b1ae3 Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Tue, 13 Aug 2024 17:32:25 +0200 Subject: [PATCH 1/2] Add shortcut `state` property to env --- boa/environment.py | 4 ++ boa/vm/py_evm.py | 60 ++++++++++--------- tests/integration/fork/test_from_etherscan.py | 4 +- 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/boa/environment.py b/boa/environment.py index 526b3c9a..227a992e 100644 --- a/boa/environment.py +++ b/boa/environment.py @@ -314,6 +314,10 @@ def _hook_trace_computation(self, computation, contract=None): child_contract = self._lookup_contract_fast(child.msg.code_address) self._hook_trace_computation(child, child_contract) + @property + def state(self): + return self.evm.state + def get_code(self, address: _AddressType) -> bytes: return self.evm.get_code(Address(address)) diff --git a/boa/vm/py_evm.py b/boa/vm/py_evm.py index c9603d94..a925798f 100644 --- a/boa/vm/py_evm.py +++ b/boa/vm/py_evm.py @@ -368,14 +368,14 @@ def _init_vm(self, account_db_class=AccountDB): c: Type[titanoboa_computation] = type( "TitanoboaComputation", - (titanoboa_computation, self.vm.state.computation_class), + (titanoboa_computation, self.state.computation_class), {"env": self.env}, ) if self._fast_mode_enabled: - patch_pyevm_state_object(self.vm.state) + patch_pyevm_state_object(self.state) - self.vm.state.computation_class = c + self.state.computation_class = c # patch in tracing opcodes c.opcodes[0x20] = Sha3PreimageTracer(c.opcodes[0x20], self.env) @@ -383,20 +383,20 @@ def _init_vm(self, account_db_class=AccountDB): def enable_fast_mode(self, flag: bool = True): if flag: - patch_pyevm_state_object(self.vm.state) + patch_pyevm_state_object(self.state) else: - unpatch_pyevm_state_object(self.vm.state) + unpatch_pyevm_state_object(self.state) def fork_rpc(self, rpc: RPC, block_identifier: str, **kwargs): account_db_class = AccountDBFork.class_from_rpc(rpc, block_identifier, **kwargs) self._init_vm(account_db_class) - block_info = self.vm.state._account_db._block_info + block_info = self.state._account_db._block_info self.patch.timestamp = int(block_info["timestamp"], 16) self.patch.block_number = int(block_info["number"], 16) self.patch.chain_id = int(rpc.fetch("eth_chainId", []), 16) - self.vm.state._account_db._rpc._init_db() + self.state._account_db._rpc._init_db() @property def is_forked(self): @@ -404,46 +404,50 @@ def is_forked(self): self.vm.__class__._state_class.account_db_class, AccountDBFork ) + @property + def state(self): + return self.vm.state + def get_gas_meter_class(self): - return self.vm.state.computation_class._gas_meter_class + return self.state.computation_class._gas_meter_class def set_gas_meter_class(self, cls: type): - self.vm.state.computation_class._gas_meter_class = cls + self.state.computation_class._gas_meter_class = cls def get_balance(self, address: Address): - return self.vm.state.get_balance(address.canonical_address) + return self.state.get_balance(address.canonical_address) def set_balance(self, address: Address, value): - self.vm.state.set_balance(address.canonical_address, value) + self.state.set_balance(address.canonical_address, value) def get_code(self, address: Address) -> bytes: - return self.vm.state.get_code(address.canonical_address) + return self.state.get_code(address.canonical_address) def set_code(self, address: Address, code: bytes) -> None: - self.vm.state.set_code(address.canonical_address, code) + self.state.set_code(address.canonical_address, code) def get_storage(self, address: Address, slot: int) -> int: - return self.vm.state.get_storage(address.canonical_address, slot) + return self.state.get_storage(address.canonical_address, slot) def set_storage(self, address: Address, slot: int, value: int) -> None: - self.vm.state.set_storage(address.canonical_address, slot, value) + self.state.set_storage(address.canonical_address, slot, value) def get_gas_limit(self): - return self.vm.state.gas_limit + return self.state.gas_limit # advanced: reset warm/cold counters for addresses and storage def reset_access_counters(self): - self.vm.state._account_db._reset_access_counters() + self.state._account_db._reset_access_counters() def snapshot(self) -> Any: - return self.vm.state.snapshot() + return self.state.snapshot() def revert(self, snapshot_id: Any) -> None: - self.vm.state.revert(snapshot_id) + self.state.revert(snapshot_id) def generate_create_address(self, sender: Address): - nonce = self.vm.state.get_nonce(sender.canonical_address) - self.vm.state.increment_nonce(sender.canonical_address) + nonce = self.state.get_nonce(sender.canonical_address) + self.state.increment_nonce(sender.canonical_address) return Address(generate_contract_address(sender.canonical_address, nonce)) def deploy_code( @@ -457,7 +461,7 @@ def deploy_code( bytecode: bytes, ): if gas is None: - gas = self.vm.state.gas_limit + gas = self.state.gas_limit msg = Message( to=constants.CREATE_CONTRACT_ADDRESS, # i.e., b"" @@ -470,13 +474,13 @@ def deploy_code( ) if self.is_forked and self._fork_try_prefetch_state: - self.vm.state._account_db.try_prefetch_state(msg) + self.state._account_db.try_prefetch_state(msg) tx_ctx = BaseTransactionContext( origin=origin.canonical_address, gas_price=gas_price ) - return self.vm.state.computation_class.apply_create_message( - self.vm.state, msg, tx_ctx + return self.state.computation_class.apply_create_message( + self.state, msg, tx_ctx ) def execute_code( @@ -509,14 +513,14 @@ def execute_code( ) if self.is_forked and self._fork_try_prefetch_state: - self.vm.state._account_db.try_prefetch_state(msg) + self.state._account_db.try_prefetch_state(msg) origin = sender.canonical_address # XXX: consider making this parameterizable tx_ctx = BaseTransactionContext(origin=origin, gas_price=gas_price) - return self.vm.state.computation_class.apply_message(self.vm.state, msg, tx_ctx) + return self.state.computation_class.apply_message(self.state, msg, tx_ctx) def get_storage_slot(self, address: Address, slot: int) -> bytes: - data = self.vm.state._account_db.get_storage(address.canonical_address, slot) + data = self.state._account_db.get_storage(address.canonical_address, slot) return data.to_bytes(32, "big") diff --git a/tests/integration/fork/test_from_etherscan.py b/tests/integration/fork/test_from_etherscan.py index 8e8efe9c..da74fe53 100644 --- a/tests/integration/fork/test_from_etherscan.py +++ b/tests/integration/fork/test_from_etherscan.py @@ -55,8 +55,8 @@ def test_prefetch_state(rpc_url, fresh_env, crvusd_contract): code=crvusd_contract._bytecode, data=crvusd_contract.burn.prepare_calldata(0), ) - state = env.evm.vm.state - db = state._account_db + + db = env.state._account_db db.try_prefetch_state(msg) # patch the RPC, so we make sure to use the cache From 15ec9c4701856f98e2db13327aaa6557f158f57f Mon Sep 17 00:00:00 2001 From: Daniel Schiavini Date: Tue, 13 Aug 2024 18:14:55 +0200 Subject: [PATCH 2/2] Linting --- .env.unsafe.example | 2 +- CONTRIBUTING.md | 12 ++++++------ tests/unitary/contracts/abi/test_abi.py | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.env.unsafe.example b/.env.unsafe.example index 1d302dd6..6a6cc081 100644 --- a/.env.unsafe.example +++ b/.env.unsafe.example @@ -2,4 +2,4 @@ # Meaning, you should never store private keys associated with real funds in here! MAINNET_ENDPOINT=xxx SEPOLIA_ENDPOINT=xxx -SEPOLIA_PKEY=xxx \ No newline at end of file +SEPOLIA_PKEY=xxx diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 388001c2..f590c49b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,7 @@ # Contributing -Thank you for wanting to contribute! This project reviews PRs that have an associated issue with -them. If you have not make an issue for your PR, please make one first. +Thank you for wanting to contribute! This project reviews PRs that have an associated issue with +them. If you have not make an issue for your PR, please make one first. Issues, feedback, and sharing that you're using Titanoboa and Vyper on social media is always welcome! @@ -21,7 +21,7 @@ Issues, feedback, and sharing that you're using Titanoboa and Vyper on social me ## Requirements -You must have the following installed to proceed with contributing to this project. +You must have the following installed to proceed with contributing to this project. - [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) - You'll know you did it right if you can run `git --version` and you see a response like `git version x.x.x` @@ -32,7 +32,7 @@ You must have the following installed to proceed with contributing to this proje - Linux and/or MacOS - This project is not tested on Windows, so it is recommended to use a Linux or MacOS machine, or use a tool like [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) for windows users. -## Installing for local development +## Installing for local development Follow the steps to clone the repo for you to make changes to this project. @@ -85,7 +85,7 @@ This will skip the integration tests, which need extra "stuff". ### Integration tests -Once you have setup your virtual environment, to run integration tests, you'll need to add environment variables. +Once you have setup your virtual environment, to run integration tests, you'll need to add environment variables. You can see the `.env.unsafe.example` for environment variables you'll want to use. @@ -110,4 +110,4 @@ pytest tests/integration/ -x # Thank you! -Thank you for wanting to participate in titanoboa! \ No newline at end of file +Thank you for wanting to participate in titanoboa! diff --git a/tests/unitary/contracts/abi/test_abi.py b/tests/unitary/contracts/abi/test_abi.py index 724fe7dc..3ed2e7f3 100644 --- a/tests/unitary/contracts/abi/test_abi.py +++ b/tests/unitary/contracts/abi/test_abi.py @@ -238,6 +238,7 @@ def test_abi_invalid_components(): assert "Components found in non-tuple type uint256" == str(exc_info.value) + def test_abi_factory_multi_deploy(): code = """ foo: public(uint256) @@ -255,4 +256,3 @@ def __init__(x: uint256): assert wrapper.foo() == 5 assert wrapper2.foo() == 6 -