diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index b139f32..ff63629 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -26,17 +26,17 @@ jobs: pip install -r dev-requirements.txt pip install . - echo "Installing zkvyper and era_test_node" - # Install zkvyper and era_test_node from binary repositories + echo "Installing zkvyper and anvil-zksync" + # Install zkvyper and anvil-zksync from binary repositories curl --location https://raw.githubusercontent.com/matter-labs/zkvyper-bin/v1.5.7/linux-amd64/zkvyper-linux-amd64-musl-v1.5.7 \ --silent --output /usr/local/bin/zkvyper && \ chmod +x /usr/local/bin/zkvyper && \ zkvyper --version - curl --location https://github.com/matter-labs/era-test-node/releases/download/v0.1.0-alpha.32/era_test_node-v0.1.0-alpha.32-x86_64-unknown-linux-gnu.tar.gz \ + curl --location https://github.com/matter-labs/anvil-zksync/releases/download/v0.1.0-alpha.35/era_test_node-v0.1.0-alpha.35-x86_64-unknown-linux-gnu.tar.gz \ --silent --output era_test_node.tar.gz && \ tar --extract --file=era_test_node.tar.gz && \ - mv era_test_node /usr/local/bin/era_test_node && \ - era_test_node --version && \ + mv era_test_node /usr/local/bin/anvil-zksync && \ + anvil-zksync --version && \ rm era_test_node.tar.gz - run: make coverage lint diff --git a/README.md b/README.md index 15ec9e7..7e2622c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # titanoboa-zksync A Zksync plugin for the Titanoboa Vyper interpreter - ## Installation First install the following dependencies, depending on your system: @@ -24,15 +23,15 @@ Then, make sure this is available in your system PATH. #### ZkSync Node -If you want to test with forks or a local test node, you will need to install the ZkSync [era-test-node](https://github.com/matter-labs/era-test-node/releases). +If you want to test with forks or a local test node, you will need to install the ZkSync [anvil-zksyncs](https://github.com/matter-labs/anvil-zksync/releases). -1. Download `era-test-node` from latest [Release](https://github.com/matter-labs/era-test-node/releases/latest) +1. Download and install `anvil-zksync` -2. Extract the binary and mark as executable: - ```bash - tar xz -f era_test_node.tar.gz -C /usr/local/bin/ - chmod +x /usr/local/bin/era_test_node - ``` +```bash +curl --proto '=https' -sSf https://raw.githubusercontent.com/matter-labs/anvil-zksync/main/scripts/install.sh > install.sh +chmod +x install.sh +sudo ./install.sh +``` Then, make sure this is available in your system PATH. diff --git a/boa_zksync/__init__.py b/boa_zksync/__init__.py index 7080dc4..0a6b3f7 100644 --- a/boa_zksync/__init__.py +++ b/boa_zksync/__init__.py @@ -4,7 +4,7 @@ from boa_zksync.contract import ZksyncContract from boa_zksync.environment import ZksyncEnv -from boa_zksync.node import EraTestNode +from boa_zksync.node import AnvilZKsync from boa_zksync.verifiers import ZksyncExplorer @@ -15,7 +15,7 @@ def set_zksync_env(url, explorer_url=None, nickname=None): def set_zksync_test_env(node_args=(), nickname=None): return boa.set_env( - ZksyncEnv(rpc=EraTestNode(node_args=node_args), nickname=nickname) + ZksyncEnv(rpc=AnvilZKsync(node_args=node_args), nickname=nickname) ) diff --git a/boa_zksync/browser.py b/boa_zksync/browser.py index d46ad69..76b7039 100644 --- a/boa_zksync/browser.py +++ b/boa_zksync/browser.py @@ -5,7 +5,7 @@ from boa.rpc import EthereumRPC from boa_zksync.environment import ZksyncEnv -from boa_zksync.util import install_era_test_node, install_zkvyper_compiler +from boa_zksync.util import install_anvil_zksync, install_zkvyper_compiler class ZksyncBrowserEnv(ZksyncEnv): @@ -34,10 +34,10 @@ def set_chain_id(self, chain_id: int | str): def fork_rpc( self, rpc: EthereumRPC, reset_traces=True, block_identifier="safe", **kwargs ): - if colab_eval_js and not which("era_test_node"): + if colab_eval_js and not which("anvil-zksync"): logging.warning( - "Automatically installing era-test-node in the Colab environment." + "Automatically installing anvil-zksync in the Colab environment." ) - install_era_test_node() + install_anvil_zksync() return super().fork_rpc(rpc, reset_traces, block_identifier, **kwargs) diff --git a/boa_zksync/compiler_utils.py b/boa_zksync/compiler_utils.py index 2c0f11b..36a014e 100644 --- a/boa_zksync/compiler_utils.py +++ b/boa_zksync/compiler_utils.py @@ -80,7 +80,12 @@ def get_compiler_output(output): # from the compiler. Assuming key names could change and also assuming that the # number of keys could change, this method breaks if any of that happens: - excluded_keys = {"version", "zk_version", "__VYPER_MINIMAL_PROXY_CONTRACT", "extra_data"} + excluded_keys = { + "version", + "zk_version", + "__VYPER_MINIMAL_PROXY_CONTRACT", + "extra_data", + } contract_keys = set(output.keys()) - excluded_keys if len(contract_keys) != 1: diff --git a/boa_zksync/environment.py b/boa_zksync/environment.py index e02acd3..e42e953 100644 --- a/boa_zksync/environment.py +++ b/boa_zksync/environment.py @@ -17,7 +17,7 @@ from requests import HTTPError from boa_zksync.deployer import ZksyncDeployer -from boa_zksync.node import EraTestNode +from boa_zksync.node import AnvilZKsync from boa_zksync.types import ( CONTRACT_DEPLOYER_ADDRESS, DEFAULT_SALT, @@ -66,7 +66,7 @@ def _reset_fork(self, block_identifier="latest"): self._vm = None if ( block_identifier == "latest" - and isinstance(self._rpc, EraTestNode) + and isinstance(self._rpc, AnvilZKsync) and (inner_rpc := self._rpc.inner_rpc) ): del self._rpc # close the old rpc @@ -93,7 +93,7 @@ def fork_rpc( if reset_traces: self.sha3_trace: dict = {} self.sstore_trace: dict = {} - self._rpc = EraTestNode(rpc, block_identifier, **kwargs) + self._rpc = AnvilZKsync(rpc, block_identifier, **kwargs) def register_contract(self, address, obj): addr = Address(address) diff --git a/boa_zksync/node.py b/boa_zksync/node.py index 58c6bea..eeced91 100644 --- a/boa_zksync/node.py +++ b/boa_zksync/node.py @@ -8,48 +8,48 @@ from boa_zksync.util import find_free_port, stop_subprocess, wait_url -class EraTestNode(EthereumRPC): - # list of public+private keys for test accounts in the era_test_node +class AnvilZKsync(EthereumRPC): + # list of public+private keys for test accounts in the anvil-zksync TEST_ACCOUNTS = [ ( - "0xBC989fDe9e54cAd2aB4392Af6dF60f04873A033A", - "0x3d3cbc973389cb26f657686445bcc75662b415b656078503592ac8c1abb8810e", + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", ), ( - "0x55bE1B079b53962746B2e86d12f158a41DF294A6", - "0x509ca2e9e6acf0ba086477910950125e698d4ea70fa6f63e000c5a22bda9361c", + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", ), ( - "0xCE9e6063674DC585F6F3c7eaBe82B9936143Ba6C", - "0x71781d3a358e7a65150e894264ccc594993fbc0ea12d69508a340bc1d4f5bfbc", + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", + "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", ), ( - "0xd986b0cB0D1Ad4CCCF0C4947554003fC0Be548E9", - "0x379d31d4a7031ead87397f332aab69ef5cd843ba3898249ca1046633c0c7eefe", + "0x90F79bf6EB2c4f870365E785982E1f101E93b906", + "0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", ), ( - "0x87d6ab9fE5Adef46228fB490810f0F5CB16D6d04", - "0x105de4e75fe465d075e1daae5647a02e3aad54b8d23cf1f70ba382b9f9bee839", + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65", + "0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a", ), ( - "0x78cAD996530109838eb016619f5931a03250489A", - "0x7becc4a46e0c3b512d380ca73a4c868f790d1055a7698f38fb3ca2b2ac97efbb", + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc", + "0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba", ), ( - "0xc981b213603171963F81C687B9fC880d33CaeD16", - "0xe0415469c10f3b1142ce0262497fe5c7a0795f0cbfd466a6bfa31968d0f70841", + "0x976EA74026E726554dB657fA54763abd0C3a0aa9", + "0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e", ), ( - "0x42F3dc38Da81e984B92A95CBdAAA5fA2bd5cb1Ba", - "0x4d91647d0a8429ac4433c83254fb9625332693c848e578062fe96362f32bfe91", + "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955", + "0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356", ), ( - "0x64F47EeD3dC749d13e49291d46Ea8378755fB6DF", - "0x41c9f9518aa07b50cb1c0cc160d45547f57638dd824a8d85b5eb3bf99ed2bdeb", + "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f", + "0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97", ), ( - "0xe2b8Cb53a43a56d4d2AB6131C81Bd76B86D3AFe5", - "0xb0680d66303a0163a19294f1ef8c95cd69a9d7902a4aca99c05f3e134e68a11a", + "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720", + "0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6", ), ] @@ -67,8 +67,12 @@ def __init__( if isinstance(block_identifier, int) else [] ) - command = ["fork", inner_rpc._rpc_url] + fork_at if inner_rpc else ["run"] - args = ["era_test_node"] + list(node_args) + ["--port", f"{port}"] + command + command = ( + ["fork", "--fork-url", inner_rpc._rpc_url] + fork_at + if inner_rpc + else ["run"] + ) + args = ["anvil-zksync"] + list(node_args) + ["--port", f"{port}"] + command self._test_node = Popen(args, stdout=sys.stdout, stderr=sys.stderr) super().__init__(f"http://localhost:{port}") diff --git a/boa_zksync/types.py b/boa_zksync/types.py index 09d87c7..2c78082 100644 --- a/boa_zksync/types.py +++ b/boa_zksync/types.py @@ -203,7 +203,7 @@ def to_deployment( ): contract_name = getattr(contract, "contract_name", None) if (filename := getattr(contract, "filename", None)) is not None: - filename = str(filename) # can be Path sometimes + filename = str(filename) # can be Path sometimes try: source_bundle = get_verification_bundle(contract) except Exception as e: diff --git a/boa_zksync/util.py b/boa_zksync/util.py index 1643747..23615b9 100644 --- a/boa_zksync/util.py +++ b/boa_zksync/util.py @@ -1,5 +1,6 @@ import os import socket +import warnings from datetime import datetime, timedelta from subprocess import Popen, TimeoutExpired from time import sleep @@ -57,6 +58,27 @@ def install_zkvyper_compiler( assert os.system("zkvyper --version") == 0 # check if it works +def install_anvil_zksync( + source="https://github.com/matter-labs/anvil-zksync/releases/download/v0.1.0-alpha.35/era_test_node-v0.1.0-alpha.35-x86_64-unknown-linux-gnu.tar.gz", # noqa: E501 + destination="/usr/local/bin/anvil-zksync", +): + """ + Downloads the anvil-zksync binary from the given source URL and installs it to + the destination directory. + + This is a very basic implementation - usually users want to install the binary + manually, but in the Colab environment, we can automate this process. + """ + response = requests.get(source) + with open("era_test_node.tar.gz", "wb") as f: + f.write(response.content) + + os.system("tar --extract --file=era_test_node.tar.gz") + os.system(f"mv era_test_node {destination}") + os.system(f"{destination} --version") + os.system("rm era_test_node.tar.gz") + + def install_era_test_node( source="https://github.com/matter-labs/era-test-node/releases/download/v0.1.0-alpha.32/era_test_node-v0.1.0-alpha.32-x86_64-unknown-linux-gnu.tar.gz", # noqa: E501 destination="/usr/local/bin/era_test_node", @@ -68,6 +90,13 @@ def install_era_test_node( This is a very basic implementation - usually users want to install the binary manually, but in the Colab environment, we can automate this process. """ + warnings.warn( + """This feature is deprecated and will be removed in a future release. + era_test_node has since been renamed to anvil-zksync.""", + DeprecationWarning, + stacklevel=2, + ) + response = requests.get(source) with open("era_test_node.tar.gz", "wb") as f: f.write(response.content) diff --git a/pyproject.toml b/pyproject.toml index d0a9c48..8d0abe9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "titanoboa-zksync" -version = "0.2.8" +version = "0.2.9" description = "A Zksync plugin for the Titanoboa Vyper interpreter" license = { file = "LICENSE" } readme = "README.md" @@ -48,4 +48,9 @@ dev-dependencies = [ "nest-asyncio>=1.6.0", "pytest-xdist>=3.6.1", "pytest>=8.3.3", + "mypy>=1.13.0", + "pip>=24.3.1", + "black>=24.10.0", + "flake8>=7.1.1", + "isort>=5.13.2", ] diff --git a/tests/conftest.py b/tests/conftest.py index f54f408..d114243 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -6,7 +6,7 @@ from eth_account import Account import boa_zksync -from boa_zksync import EraTestNode +from boa_zksync import AnvilZKsync from boa_zksync.deployer import ZksyncDeployer STARTING_SUPPLY = 100 @@ -58,7 +58,7 @@ def zksync_sepolia_env(): @pytest.fixture(scope="module") def account(): # default rich account from era_test_node - _public_key, private_key = EraTestNode.TEST_ACCOUNTS[0] + _public_key, private_key = AnvilZKsync.TEST_ACCOUNTS[0] return Account.from_key(private_key) diff --git a/tests/test_boa_loads.py b/tests/test_boa_loads.py index 7d4dc15..f54e8f7 100644 --- a/tests/test_boa_loads.py +++ b/tests/test_boa_loads.py @@ -131,7 +131,7 @@ def get_name_of(addr: HasName) -> String[32]: f"{caller_contract.address}> (file " ").get_name_of(address) -> ['string'])", " ", - " ", + " ", " Test an error( (file ).get_name_of(address) -> " "['string'])", @@ -139,16 +139,15 @@ def get_name_of(addr: HasName) -> String[32]: ) assert isinstance(call_trace, TraceFrame) assert str(call_trace).split("\n") == [ - f'[E] [24505] CallerContract.get_name_of(addr = "{called_addr}") <0x>', - " [E] [23574] Unknown contract 0x0000000000000000000000000000000000008002.0x4de2e468", - " [566] Unknown contract 0x000000000000000000000000000000000000800B.0x29f172ad", + f'[E] [21325] CallerContract.get_name_of(addr = "{called_addr}") <0x>', + " [E] [19164] Unknown contract 0x000000000000000000000000000000000000800B.0x29f172ad", " [1909] Unknown contract 0x000000000000000000000000000000000000800B.0x06bed036", " [159] Unknown contract 0x0000000000000000000000000000000000008010.0x00000000", - " [449] Unknown contract 0x000000000000000000000000000000000000800B.0xa225efcb", + " [395] Unknown contract 0x000000000000000000000000000000000000800B.0xa225efcb", " [2226] Unknown contract 0x0000000000000000000000000000000000008002.0x4de2e468", - " [427] Unknown contract 0x000000000000000000000000000000000000800B.0xa851ae78", + " [373] Unknown contract 0x000000000000000000000000000000000000800B.0xa851ae78", " [398] Unknown contract 0x0000000000000000000000000000000000008004.0xe516761e", - " [E] [2548] Unknown contract 0x0000000000000000000000000000000000008009.0xb47fade1", + " [E] [2554] Unknown contract 0x0000000000000000000000000000000000008009.0xb47fade1", f' [E] [1365] CallerContract.get_name_of(addr = "{called_addr}") <0x>', " [E] [397] CalledContract.name() <0x>", ] @@ -198,7 +197,7 @@ def transfer(_to : address, _value : uint256) -> bool: contract = boa.loads(code, 100) assert [str(e) for e in contract.get_logs()] == [ "Transfer(sender=0x0000000000000000000000000000000000000000, " - "receiver=0xBC989fDe9e54cAd2aB4392Af6dF60f04873A033A, value=100)" + "receiver=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, value=100)" ] to = boa.env.generate_address() diff --git a/tests/test_sepolia.py b/tests/test_sepolia.py index abe0087..91f70d1 100644 --- a/tests/test_sepolia.py +++ b/tests/test_sepolia.py @@ -3,7 +3,7 @@ from boa.rpc import EthereumRPC import boa_zksync -from boa_zksync import EraTestNode +from boa_zksync import AnvilZKsync from boa_zksync.environment import ZERO_ADDRESS @@ -37,7 +37,7 @@ def set_implementation(_implementation: address): def test_fork_rpc(zksync_sepolia_fork): - assert isinstance(boa.env._rpc, EraTestNode) + assert isinstance(boa.env._rpc, AnvilZKsync) assert isinstance(boa.env._rpc.inner_rpc, EthereumRPC)