diff --git a/boa/__init__.py b/boa/__init__.py index e8cea0b5..9f595984 100644 --- a/boa/__init__.py +++ b/boa/__init__.py @@ -13,9 +13,11 @@ load, load_abi, load_partial, + load_vyi, loads, loads_abi, loads_partial, + loads_vyi, ) from boa.network import NetworkEnv from boa.precompile import precompile @@ -35,25 +37,20 @@ @contextlib.contextmanager def swap_env(new_env): - old_env = env - try: - set_env(new_env) + with set_env(new_env): yield - finally: - set_env(old_env) -def set_env(new_env): +def _set_env(new): global env - env = new_env + env = new + Env._singleton = new - Env._singleton = new_env - -def _env_mgr(new_env): +def set_env(new_env): global env get_env = lambda: env # noqa: E731 - return Open(get_env, set_env, new_env) + return Open(get_env, _set_env, new_env) def fork( @@ -67,7 +64,7 @@ def fork( new_env = Env() new_env.fork(url=url, block_identifier=block_identifier, deprecated=False, **kwargs) - return _env_mgr(new_env) + return set_env(new_env) def set_browser_env(address=None): @@ -75,12 +72,12 @@ def set_browser_env(address=None): # import locally because jupyter is generally not installed from boa.integrations.jupyter import BrowserEnv - return _env_mgr(BrowserEnv(address)) + return set_env(BrowserEnv(address)) def set_network_env(url): """Set the environment to use a custom network URL""" - return _env_mgr(NetworkEnv.from_url(url)) + return set_env(NetworkEnv.from_url(url)) def set_etherscan(*args, **kwargs): diff --git a/boa/contracts/vvm/vvm_contract.py b/boa/contracts/vvm/vvm_contract.py index 2c2c783a..87038a2d 100644 --- a/boa/contracts/vvm/vvm_contract.py +++ b/boa/contracts/vvm/vvm_contract.py @@ -3,6 +3,7 @@ from boa.contracts.abi.abi_contract import ABIContractFactory, ABIFunction from boa.environment import Env +from boa.util.eip5202 import generate_blueprint_bytecode # TODO: maybe this doesn't detect release candidates VERSION_RE = re.compile(r"\s*#\s*(pragma\s+version|@version)\s+(\d+\.\d+\.\d+)") @@ -18,7 +19,19 @@ def _detect_version(source_code: str): class VVMDeployer: + """ + A deployer that uses the Vyper Version Manager (VVM). + This allows deployment of contracts written in older versions of Vyper that + can interact with new versions using the ABI definition. + """ + def __init__(self, abi, bytecode, filename): + """ + Initialize a VVMDeployer instance. + :param abi: The contract's ABI. + :param bytecode: The contract's bytecode. + :param filename: The filename of the contract. + """ self.abi = abi self.bytecode = bytecode self.filename = filename @@ -41,7 +54,7 @@ def constructor(self): return ABIFunction(t, contract_name=self.filename) return None - def deploy(self, *args, env=None): + def deploy(self, *args, contract_name=None, env=None, **kwargs): encoded_args = b"" if self.constructor is not None: encoded_args = self.constructor.prepare_calldata(*args) @@ -51,10 +64,37 @@ def deploy(self, *args, env=None): if env is None: env = Env.get_singleton() - address, _ = env.deploy_code(bytecode=self.bytecode + encoded_args) + address, _ = env.deploy_code(bytecode=self.bytecode + encoded_args, **kwargs) + # TODO: pass thru contract_name return self.at(address) + @cached_property + def _blueprint_deployer(self): + # TODO: add filename + return ABIContractFactory.from_abi_dict([]) + + def deploy_as_blueprint(self, env=None, blueprint_preamble=None, **kwargs): + """ + Deploy a new blueprint from this contract. + :param blueprint_preamble: The preamble to use for the blueprint. + :param env: The environment to deploy the blueprint in. + :param kwargs: Keyword arguments to pass to the environment `deploy_code` method. + :returns: A contract instance. + """ + if env is None: + env = Env.get_singleton() + + blueprint_bytecode = generate_blueprint_bytecode( + self.bytecode, blueprint_preamble + ) + address, _ = env.deploy_code(bytecode=blueprint_bytecode, **kwargs) + + ret = self._blueprint_deployer.at(address) + + env.register_blueprint(self.bytecode, ret) + return ret + def __call__(self, *args, **kwargs): return self.deploy(*args, **kwargs) diff --git a/boa/contracts/vyper/vyper_contract.py b/boa/contracts/vyper/vyper_contract.py index e2e7acec..4bf5e9db 100644 --- a/boa/contracts/vyper/vyper_contract.py +++ b/boa/contracts/vyper/vyper_contract.py @@ -56,6 +56,7 @@ from boa.environment import Env from boa.profiling import cache_gas_used_for_computation from boa.util.abi import Address, abi_decode, abi_encode +from boa.util.eip5202 import generate_blueprint_bytecode from boa.util.lrudict import lrudict from boa.vm.gas_meters import ProfilingGasMeter from boa.vm.utils import to_bytes, to_int @@ -99,8 +100,8 @@ def stomp(self, address: Any, data_section=None) -> "VyperContract": address = Address(address) ret = self.deploy(override_address=address, skip_initcode=True) - vm = ret.env.vm - old_bytecode = vm.state.get_code(address.canonical_address) + vm = ret.env.evm + old_bytecode = vm.get_code(address) new_bytecode = self.compiler_data.bytecode_runtime immutables_size = self.compiler_data.global_ctx.immutable_section_bytes @@ -108,7 +109,7 @@ def stomp(self, address: Any, data_section=None) -> "VyperContract": data_section = old_bytecode[-immutables_size:] new_bytecode += data_section - vm.state.set_code(address.canonical_address, new_bytecode) + vm.set_code(address, new_bytecode) ret.env.register_contract(address, ret) ret._set_bytecode(new_bytecode) return ret @@ -143,10 +144,13 @@ class _BaseVyperContract(_BaseEVMContract): def __init__( self, compiler_data: CompilerData, + contract_name: Optional[str] = None, env: Optional[Env] = None, filename: Optional[str] = None, ): - contract_name = Path(compiler_data.contract_path).stem + if contract_name is None: + contract_name = Path(compiler_data.contract_path).stem + super().__init__(contract_name, env, filename) self.compiler_data = compiler_data @@ -183,24 +187,16 @@ def __init__( compiler_data, env=None, override_address=None, - blueprint_preamble=b"\xFE\x71\x00", + blueprint_preamble=None, + contract_name=None, filename=None, gas=None, ): - # note slight code duplication with VyperContract ctor, - # maybe use common base class? - super().__init__(compiler_data, env, filename) - - if blueprint_preamble is None: - blueprint_preamble = b"" - - blueprint_bytecode = blueprint_preamble + compiler_data.bytecode + super().__init__(compiler_data, contract_name, env, filename) - # the length of the deployed code in bytes - len_bytes = len(blueprint_bytecode).to_bytes(2, "big") - deploy_bytecode = b"\x61" + len_bytes + b"\x3d\x81\x60\x0a\x3d\x39\xf3" - - deploy_bytecode += blueprint_bytecode + deploy_bytecode = generate_blueprint_bytecode( + compiler_data.bytecode, blueprint_preamble + ) addr, computation = self.env.deploy( bytecode=deploy_bytecode, override_address=override_address, gas=gas @@ -522,10 +518,11 @@ def __init__( # whether to skip constructor skip_initcode=False, created_from: Address = None, + contract_name=None, filename: str = None, gas=None, ): - super().__init__(compiler_data, env, filename) + super().__init__(compiler_data, contract_name, env, filename) self.created_from = created_from self._computation = None diff --git a/boa/deployments.py b/boa/deployments.py index 3eb5c5a0..03a3e2af 100644 --- a/boa/deployments.py +++ b/boa/deployments.py @@ -3,7 +3,7 @@ import uuid from dataclasses import asdict, dataclass, field, fields from pathlib import Path -from typing import Any, Optional +from typing import Any, Generator, Optional from boa.util.abi import Address from boa.util.open_ctx import Open @@ -39,6 +39,7 @@ class Deployment: tx_dict: dict # raw tx fields receipt_dict: dict # raw receipt fields source_code: Optional[Any] # optional source code or bundle + abi: Optional[Any] session_id: str = field(default_factory=get_session_id) deployment_id: Optional[int] = None # the db-assigned id - primary key @@ -49,6 +50,8 @@ def sql_values(self): ret["receipt_dict"] = json.dumps(ret["receipt_dict"]) if ret["source_code"] is not None: ret["source_code"] = json.dumps(ret["source_code"]) + if ret["abi"] is not None: + ret["abi"] = json.dumps(ret["abi"]) return ret def to_dict(self): @@ -75,6 +78,8 @@ def from_sql_tuple(cls, values): ret["receipt_dict"] = json.loads(ret["receipt_dict"]) if ret["source_code"] is not None: ret["source_code"] = json.loads(ret["source_code"]) + if ret["abi"] is not None: + ret["abi"] = json.loads(ret["abi"]) return cls(**ret) @@ -91,7 +96,8 @@ def from_sql_tuple(cls, values): broadcast_ts real, tx_dict text, receipt_dict text, - source_code text + source_code text, + abi text ); """ @@ -123,15 +129,23 @@ def insert_deployment(self, deployment: Deployment): def _get_deployments_from_sql(self, sql_query: str, parameters=(), /): cur = self.db.execute(sql_query, parameters) - ret = [Deployment.from_sql_tuple(item) for item in cur.fetchall()] - return ret + return (Deployment.from_sql_tuple(item) for item in cur) def _get_fieldnames_str(self) -> str: return ",".join(field.name for field in fields(Deployment)) - def get_deployments(self) -> list[Deployment]: + def get_deployments(self) -> Generator[Deployment, None, None]: + """ + Return all the deployments from the database. Returns an iterator + which can be converted to a list with `list(db.get_deployments())`. + + Returns the deployments ordered by most recent first, i.e. using + an `ORDER BY deployment_id DESC` clause. + """ fieldnames = self._get_fieldnames_str() - return self._get_deployments_from_sql(f"SELECT {fieldnames} FROM deployments") + return self._get_deployments_from_sql( + f"SELECT {fieldnames} FROM deployments order by deployment_id desc" + ) _db: Optional[DeploymentsDB] = None diff --git a/boa/interpret.py b/boa/interpret.py index 4447335f..8870b168 100644 --- a/boa/interpret.py +++ b/boa/interpret.py @@ -8,6 +8,7 @@ import vvm import vyper +from vyper.ast.parse import parse_to_ast from vyper.cli.vyper_compile import get_search_paths from vyper.compiler.input_bundle import ( ABIInput, @@ -17,6 +18,7 @@ ) from vyper.compiler.phases import CompilerData from vyper.compiler.settings import Settings, anchor_settings +from vyper.semantics.analysis.module import analyze_module from vyper.semantics.types.module import ModuleT from vyper.utils import sha256sum @@ -127,11 +129,15 @@ def get_module_fingerprint( def compiler_data( - source_code: str, contract_name: str, filename: str | Path, deployer=None, **kwargs + source_code: str, + contract_name: str | None, + filename: str | Path, + deployer=None, + **kwargs, ) -> CompilerData: global _disk_cache, _search_path - path = Path(contract_name) + path = Path(filename) resolved_path = Path(filename).resolve(strict=False) file_input = FileInput( @@ -162,7 +168,7 @@ def get_compiler_data(): assert isinstance(deployer, type) or deployer is None deployer_id = repr(deployer) # a unique str identifying the deployer class - cache_key = str((contract_name, fingerprint, kwargs, deployer_id)) + cache_key = str((contract_name, filename, fingerprint, kwargs, deployer_id)) return _disk_cache.caching_lookup(cache_key, get_compiler_data) @@ -186,14 +192,15 @@ def loads( ): d = loads_partial(source_code, name, filename=filename, compiler_args=compiler_args) if as_blueprint: - return d.deploy_as_blueprint(**kwargs) + return d.deploy_as_blueprint(contract_name=name, **kwargs) else: - return d.deploy(*args, **kwargs) + return d.deploy(*args, contract_name=name, **kwargs) def load_abi(filename: str, *args, name: str = None, **kwargs) -> ABIContractFactory: if name is None: name = Path(filename).stem + # TODO: pass filename to ABIContractFactory with open(filename) as fp: return loads_abi(fp.read(), *args, name=name, **kwargs) @@ -202,6 +209,33 @@ def loads_abi(json_str: str, *args, name: str = None, **kwargs) -> ABIContractFa return ABIContractFactory.from_abi_dict(json.loads(json_str), name, *args, **kwargs) +# load from .vyi file. +# NOTE: substantially same interface as load_abi and loads_abi, consider +# fusing them into load_interface? +def load_vyi(filename: str, name: str = None) -> ABIContractFactory: + if name is None: + name = Path(filename).stem + with open(filename) as fp: + return loads_vyi(fp.read(), name=name, filename=filename) + + +# load interface from .vyi file string contents. +def loads_vyi(source_code: str, name: str = None, filename: str = None): + global _search_path + + ast = parse_to_ast(source_code) + + if name is None: + name = "VyperContract.vyi" + + search_paths = get_search_paths(_search_path) + input_bundle = FilesystemInputBundle(search_paths) + + module_t = analyze_module(ast, input_bundle, is_interface=True) + abi = module_t.interface.to_toplevel_abi_dict() + return ABIContractFactory(name, abi, filename=filename) + + def loads_partial( source_code: str, name: str = None, @@ -209,8 +243,8 @@ def loads_partial( dedent: bool = True, compiler_args: dict = None, ) -> VyperDeployer: - name = name or "VyperContract" - filename = filename or "" + if filename is None: + filename = "" if dedent: source_code = textwrap.dedent(source_code) diff --git a/boa/network.py b/boa/network.py index 9b9ad5de..23dd0dd1 100644 --- a/boa/network.py +++ b/boa/network.py @@ -414,6 +414,7 @@ def deploy( msg += f" trace:\n```\n{e}\n```\nContinuing.\n" warnings.warn(msg, stacklevel=2) source_bundle = None + abi = getattr(contract, "abi", None) deployment_data = Deployment( create_address, @@ -425,6 +426,7 @@ def deploy( txdata, receipt, source_bundle, + abi, ) deployments_db.insert_deployment(deployment_data) diff --git a/boa/util/eip5202.py b/boa/util/eip5202.py index 2e6c6d31..10b7c321 100644 --- a/boa/util/eip5202.py +++ b/boa/util/eip5202.py @@ -3,6 +3,23 @@ from eth_utils import to_canonical_address, to_checksum_address from vyper.utils import keccak256 +DEFAULT_BLUEPRINT_PREAMBLE = b"\xFE\x71\x00" + + +def generate_blueprint_bytecode( + contract_bytecode: bytes, blueprint_preamble: bytes = None +): + if blueprint_preamble is None: + blueprint_preamble = DEFAULT_BLUEPRINT_PREAMBLE + + blueprint_bytecode = blueprint_preamble + contract_bytecode + + # the length of the deployed code in bytes + len_bytes = len(blueprint_bytecode).to_bytes(2, "big") + deploy_bytecode = b"\x61" + len_bytes + b"\x3d\x81\x60\x0a\x3d\x39\xf3" + + return deploy_bytecode + blueprint_bytecode + # TODO replace return type with upcoming AddressType wrapper def get_create2_address( diff --git a/dev-requirements.txt b/dev-requirements.txt index 93d94bad..eeb2522a 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -12,6 +12,7 @@ pytest pytest-xdist pytest-cov sphinx-rtd-theme +requests-cache # jupyter jupyter_server diff --git a/pyproject.toml b/pyproject.toml index 73d3659f..2ed482e0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "titanoboa" -version = "0.2.3" +version = "0.2.5b1" description = "A Vyper interpreter" #authors = [] license = { file = "LICENSE" } diff --git a/tests/integration/fork/test_abi_contract.py b/tests/integration/fork/test_abi_contract.py index 8712796f..7cbd28ad 100644 --- a/tests/integration/fork/test_abi_contract.py +++ b/tests/integration/fork/test_abi_contract.py @@ -185,7 +185,8 @@ def test_call_trace_abi_and_vyper(crvusd): @external def foo(x: IERC20): extcall x.transfer(self, 100) - """ + """, + name="VyperContract", ) boa.env.set_balance(boa.env.eoa, 1000) with boa.reverts(): diff --git a/tests/integration/network/anvil/test_network_env.py b/tests/integration/network/anvil/test_network_env.py index c21ed885..6a289523 100644 --- a/tests/integration/network/anvil/test_network_env.py +++ b/tests/integration/network/anvil/test_network_env.py @@ -73,24 +73,55 @@ def test_failed_transaction(): # XXX: probably want to test deployment revert behavior -def test_deployment_db(): +def test_deployment_db_overriden_contract_name(): with set_deployments_db(DeploymentsDB(":memory:")) as db: arg = 5 + contract_name = "test_deployment" + + # contract is written to deployments db + contract = boa.loads(code, arg, name=contract_name) + + # test get_deployments() + deployment = next(db.get_deployments()) + + initcode = contract.compiler_data.bytecode + arg.to_bytes(32, "big") + + # sanity check all the fields + assert deployment.contract_address == contract.address + assert deployment.contract_name == contract.contract_name + assert deployment.contract_name == contract_name + assert deployment.deployer == boa.env.eoa + assert deployment.rpc == boa.env._rpc.name + assert deployment.source_code == contract.deployer.solc_json + assert deployment.abi == contract.abi + + # some sanity checks on tx_dict and rx_dict fields + assert to_bytes(deployment.tx_dict["data"]) == initcode + assert deployment.tx_dict["chainId"] == hex(boa.env.get_chain_id()) + assert Address(deployment.receipt_dict["contractAddress"]) == contract.address + + +def test_deployment_db_no_overriden_name(): + with set_deployments_db(DeploymentsDB(":memory:")) as db: + arg = 5 + non_contract_name = "test_deployment" # contract is written to deployments db contract = boa.loads(code, arg) # test get_deployments() - deployment = db.get_deployments()[-1] + deployment = next(db.get_deployments()) initcode = contract.compiler_data.bytecode + arg.to_bytes(32, "big") # sanity check all the fields assert deployment.contract_address == contract.address assert deployment.contract_name == contract.contract_name + assert deployment.contract_name != non_contract_name assert deployment.deployer == boa.env.eoa assert deployment.rpc == boa.env._rpc.name assert deployment.source_code == contract.deployer.solc_json + assert deployment.abi == contract.abi # some sanity checks on tx_dict and rx_dict fields assert to_bytes(deployment.tx_dict["data"]) == initcode diff --git a/tests/integration/network/sepolia/test_sepolia_env.py b/tests/integration/network/sepolia/test_sepolia_env.py index d37ba0bc..e0e9de12 100644 --- a/tests/integration/network/sepolia/test_sepolia_env.py +++ b/tests/integration/network/sepolia/test_sepolia_env.py @@ -42,7 +42,7 @@ def test_verify(simple_contract): api_key = os.getenv("BLOCKSCOUT_API_KEY") blockscout = Blockscout("https://eth-sepolia.blockscout.com", api_key) with boa.set_verifier(blockscout): - result = boa.verify(simple_contract, blockscout) + result = boa.verify(simple_contract) result.wait_for_verification() assert result.is_verified() @@ -75,18 +75,20 @@ def test_raise_exception(simple_contract, amount): def test_deployment_db(): with set_deployments_db(DeploymentsDB(":memory:")) as db: arg = 5 + contract_name = "test_deployment" # contract is written to deployments db - contract = boa.loads(code, arg) + contract = boa.loads(code, arg, name=contract_name) # test get_deployments() - deployment = db.get_deployments()[-1] + deployment = next(db.get_deployments()) initcode = contract.compiler_data.bytecode + arg.to_bytes(32, "big") # sanity check all the fields assert deployment.contract_address == contract.address assert deployment.contract_name == contract.contract_name + assert deployment.contract_name == contract_name assert deployment.deployer == boa.env.eoa assert deployment.rpc == boa.env._rpc.name assert deployment.source_code == contract.deployer.solc_json diff --git a/tests/unitary/contracts/vvm/test_vvm.py b/tests/unitary/contracts/vvm/test_vvm.py index 6a2da16f..3f10106d 100644 --- a/tests/unitary/contracts/vvm/test_vvm.py +++ b/tests/unitary/contracts/vvm/test_vvm.py @@ -37,3 +37,16 @@ def test_loads_vvm(): assert contract.foo() == 42 assert contract.bar() == 43 + + +def test_forward_args_on_deploy(): + with open(mock_3_10_path) as f: + code = f.read() + + contract_vvm_deployer = boa.loads_partial(code) + + random_addy = boa.env.generate_address() + + contract = contract_vvm_deployer.deploy(43, override_address=random_addy) + + assert random_addy == contract.address diff --git a/tests/unitary/contracts/vyper/test_vyi.py b/tests/unitary/contracts/vyper/test_vyi.py new file mode 100644 index 00000000..8269c9b2 --- /dev/null +++ b/tests/unitary/contracts/vyper/test_vyi.py @@ -0,0 +1,42 @@ +import pytest + +import boa + +FOO_CONTRACT = """ +@external +def foo() -> uint256: + return 5 +""" + +FOO_INTERFACE = """ +@external +def foo() -> uint256: + ... +""" + + +@pytest.fixture +def foo_contract(): + return boa.loads(FOO_CONTRACT) + + +@pytest.fixture +def foo_interface(foo_contract): + return boa.loads_vyi(FOO_INTERFACE).at(foo_contract.address) + + +# from file +@pytest.fixture +def foo_interface2(foo_contract, tmp_path): + p = tmp_path / "foo.vyi" + with p.open("w") as f: + f.write(FOO_INTERFACE) + return boa.load_vyi(p).at(foo_contract.address) + + +def test_foo_interface(foo_interface): + assert foo_interface.foo() == 5 + + +def test_foo_interface2(foo_interface2): + assert foo_interface2.foo() == 5 diff --git a/tests/unitary/contracts/vyper/test_vyper_contract.py b/tests/unitary/contracts/vyper/test_vyper_contract.py index b522e935..4fd8e70a 100644 --- a/tests/unitary/contracts/vyper/test_vyper_contract.py +++ b/tests/unitary/contracts/vyper/test_vyper_contract.py @@ -72,3 +72,81 @@ def foo() -> bool: c = boa.loads(code) c.foo() + + +def test_contract_name(): + code = """ +@external +def foo() -> bool: + return True + """ + c = boa.loads(code, name="return_one", filename="return_one.vy") + + assert c.contract_name == "return_one" + assert c.filename == "return_one.vy" + + c = boa.loads(code, filename="a/b/return_one.vy") + + assert c.contract_name == "return_one" + assert c.filename == "a/b/return_one.vy" + + c = boa.loads(code, filename=None, name="dummy_name") + + assert c.contract_name == "dummy_name" + assert c.filename == "" + + c = boa.loads(code, filename=None, name=None) + + assert c.contract_name == "" + assert c.filename == "" + + +def test_stomp(): + code1 = """ +VAR: immutable(uint256) + +@deploy +def __init__(): + VAR = 12345 + +@external +def foo() -> uint256: + return VAR + +@external +def bar() -> bool: + return True + """ + code2 = """ +VAR: immutable(uint256) + +@deploy +def __init__(): + VAR = 12345 + +@external +def foo() -> uint256: + return VAR + +@external +def bar() -> bool: + return False + """ + + deployer = boa.loads_partial(code1) + + c = deployer.deploy() + + assert c.foo() == 12345 + assert c.bar() is True + + deployer2 = boa.loads_partial(code2) + + c2 = deployer2.stomp(c.address) + + assert c2.foo() == 12345 + assert c2.bar() is False + + # the bytecode at the original contract has been stomped :scream: + assert c.foo() == 12345 + assert c.bar() is False diff --git a/tests/unitary/test_blueprints.py b/tests/unitary/test_blueprints.py index b3ef067c..3a5b3451 100644 --- a/tests/unitary/test_blueprints.py +++ b/tests/unitary/test_blueprints.py @@ -1,23 +1,45 @@ import pytest +import vyper from eth_utils import to_canonical_address import boa from boa.util.eip5202 import get_create2_address -blueprint_code = """ +_blueprint_code = """ +# pragma version {} + @external def some_function() -> uint256: return 5 """ -factory_code = """ +_factory_code = """ +# pragma version {} + @external def create_child(blueprint: address, salt: bytes32) -> address: return create_from_blueprint(blueprint, code_offset=3, salt=salt) """ +VERSIONS = [vyper.__version__, "0.3.10"] + + +@pytest.fixture(params=VERSIONS) +def version(request): + return request.param + + +@pytest.fixture +def blueprint_code(version): + return _blueprint_code.format(version) + + +@pytest.fixture +def factory_code(version): + return _factory_code.format(version) + -def test_create2_address(): +def test_create2_address(blueprint_code, factory_code): blueprint = boa.loads_partial(blueprint_code).deploy_as_blueprint() factory = boa.loads(factory_code) @@ -31,7 +53,7 @@ def test_create2_address(): ) -def test_create2_address_bad_salt(): +def test_create2_address_bad_salt(blueprint_code): blueprint = boa.loads_partial(blueprint_code).deploy_as_blueprint() blueprint_bytecode = boa.env.get_code(to_canonical_address(blueprint.address)) with pytest.raises(ValueError) as e: diff --git a/tests/unitary/test_boa.py b/tests/unitary/test_boa.py index 4d38b906..b15e1707 100644 --- a/tests/unitary/test_boa.py +++ b/tests/unitary/test_boa.py @@ -4,7 +4,7 @@ def test_env_mgr_noctx(): s = boa.env t = boa.Env() - boa._env_mgr(t) + boa.set_env(t) assert boa.env is not s assert boa.env is t @@ -13,7 +13,7 @@ def test_env_mgr_with_ctx(): s = boa.env t = boa.Env() - with boa._env_mgr(t): + with boa.set_env(t): assert boa.env is not s assert boa.env is t diff --git a/tests/unitary/utils/test_cache.py b/tests/unitary/utils/test_cache.py index 64659821..ad58eec5 100644 --- a/tests/unitary/utils/test_cache.py +++ b/tests/unitary/utils/test_cache.py @@ -22,12 +22,12 @@ def test_cache_contract_name(): x: constant(int128) = 1000 """ assert _disk_cache is not None - test1 = compiler_data(code, "test1", __file__, VyperDeployer) - test2 = compiler_data(code, "test2", __file__, VyperDeployer) - test3 = compiler_data(code, "test1", __file__, VyperDeployer) + test1 = compiler_data(code, "test1", "test1.vy", VyperDeployer) + test2 = compiler_data(code, "test2", "test2.vy", VyperDeployer) + test3 = compiler_data(code, "test1", "test1.vy", VyperDeployer) assert _to_dict(test1) == _to_dict(test3), "Should hit the cache" assert _to_dict(test1) != _to_dict(test2), "Should be different objects" - assert str(test2.contract_path) == "test2" + assert str(test2.contract_path) == "test2.vy" def test_cache_vvm():