Skip to content

Commit

Permalink
Merge pull request #14 from DanielSchiavini/dependencies
Browse files Browse the repository at this point in the history
chore: update dependencies
  • Loading branch information
DanielSchiavini authored Sep 19, 2024
2 parents bd5e0c3 + b07d91c commit b2c83e3
Show file tree
Hide file tree
Showing 11 changed files with 110 additions and 39 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ jobs:
echo "Installing zkvyper and era_test_node"
# Install zkvyper and era_test_node from binary repositories
curl --location https://raw.githubusercontent.com/matter-labs/zkvyper-bin/v1.5.3/linux-amd64/zkvyper-linux-amd64-musl-v1.5.3 \
curl --location https://raw.githubusercontent.com/matter-labs/zkvyper-bin/v1.5.4/linux-amd64/zkvyper-linux-amd64-musl-v1.5.4 \
--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.25/era_test_node-v0.1.0-alpha.25-x86_64-unknown-linux-gnu.tar.gz \
curl --location https://github.com/matter-labs/era-test-node/releases/download/v0.1.0-alpha.27/era_test_node-v0.1.0-alpha.27-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 && \
Expand Down
6 changes: 3 additions & 3 deletions boa_zksync/contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def __init__(self, fn: ContractFunctionT, contract: ZksyncContract):
"name": f"__boa_private_{fn.name}__",
"type": "function",
}
super().__init__(abi, contract._name)
super().__init__(abi, contract.contract_name)
self.contract = contract
self.func_t = fn

Expand All @@ -163,7 +163,7 @@ def __init__(self, var: VarInfo, name: str, contract: ZksyncContract):
"constant": True,
"type": "function",
}
super().__init__(abi, contract._name)
super().__init__(abi, contract.contract_name)
self.contract = contract
self.var = var
self.var_name = name
Expand Down Expand Up @@ -198,7 +198,7 @@ def __init__(self, code: str, contract: ZksyncContract):
"name": "__boa_debug__",
"type": "function",
}
super().__init__(abi, contract._name)
super().__init__(abi, contract.contract_name)
self.contract = contract
self.code = code

Expand Down
17 changes: 15 additions & 2 deletions boa_zksync/deployer.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from boa_zksync.compile import compile_zksync, compile_zksync_source
from boa_zksync.contract import ZksyncContract
from boa_zksync.types import ZksyncCompilerData
from boa_zksync.types import ZksyncCompilerData, DEFAULT_SALT

if TYPE_CHECKING:
from boa_zksync.environment import ZksyncEnv
Expand Down Expand Up @@ -41,10 +41,23 @@ def _compile(
def from_abi_dict(cls, abi, name="<anonymous contract>", filename=None):
raise NotImplementedError("ZksyncDeployer does not support loading from ABI")

def deploy(self, *args, value=0, **kwargs) -> ZksyncContract:
def deploy(
self,
*args,
value=0,
gas=None,
dependency_bytecodes=(),
salt=DEFAULT_SALT,
max_priority_fee_per_gas=None,
**kwargs,
) -> ZksyncContract:
address, _ = self.env.deploy_code(
bytecode=self.zkvyper_data.bytecode,
value=value,
gas=gas,
dependency_bytecodes=dependency_bytecodes,
salt=salt,
max_priority_fee_per_gas=max_priority_fee_per_gas,
constructor_calldata=(
self.constructor.prepare_calldata(*args, **kwargs)
if args or kwargs
Expand Down
35 changes: 21 additions & 14 deletions boa_zksync/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from hashlib import sha256
from pathlib import Path
from typing import Any, Iterable, Optional, Type
from unittest.mock import MagicMock

from boa.contracts.abi.abi_contract import ABIContract, ABIContractFactory
from boa.environment import _AddressType
Expand All @@ -17,10 +16,14 @@

from boa_zksync.deployer import ZksyncDeployer
from boa_zksync.node import EraTestNode
from boa_zksync.types import DeployTransaction, ZksyncComputation, ZksyncMessage
from boa_zksync.types import (
CONTRACT_DEPLOYER_ADDRESS,
ZERO_ADDRESS,
DeployTransaction,
ZksyncComputation,
ZksyncMessage, DEFAULT_SALT,
)

ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"
_CONTRACT_DEPLOYER_ADDRESS = "0x0000000000000000000000000000000000008006"
with open(Path(__file__).parent / "IContractDeployer.json") as f:
CONTRACT_DEPLOYER = ABIContractFactory.from_abi_dict(
json.load(f), "ContractDeployer"
Expand Down Expand Up @@ -52,8 +55,8 @@ def create(self):
@property
def vm(self):
if self._vm is None:
# todo: vyper base contract calls this property
self._vm = MagicMock(state=_RPCState(self._rpc))
self._vm = lambda: None
self._vm.state = _RPCState(self._rpc)
return self._vm

def _reset_fork(self, block_identifier="latest"):
Expand Down Expand Up @@ -132,11 +135,11 @@ def execute_code(
"debug_traceCall",
[args.as_json_dict(), "latest", {"tracer": "callTracer"}],
)
traced_computation = ZksyncComputation.from_call_trace(trace_call)
traced_computation = ZksyncComputation.from_call_trace(self, trace_call)
except (RPCError, HTTPError):
output = self._rpc.fetch("eth_call", [args.as_json_dict(), "latest"])
traced_computation = ZksyncComputation(
args, bytes.fromhex(output.removeprefix("0x"))
self, args, bytes.fromhex(output.removeprefix("0x"))
)

if is_modifying:
Expand All @@ -147,11 +150,13 @@ def execute_code(
assert (
traced_computation.is_error == trace.is_error
), f"VMError mismatch: {traced_computation.error} != {trace.error}"
return ZksyncComputation.from_debug_trace(trace.raw_trace)
return ZksyncComputation.from_debug_trace(self, trace.raw_trace)

except _EstimateGasFailed:
if not traced_computation.is_error: # trace gives more information
return ZksyncComputation(args, error=VMError("Estimate gas failed"))
return ZksyncComputation(
self, args, error=VMError("Estimate gas failed")
)

return traced_computation

Expand All @@ -163,7 +168,8 @@ def deploy_code(
bytecode=b"",
constructor_calldata=b"",
dependency_bytecodes: Iterable[bytes] = (),
salt=b"\0" * 32,
salt=DEFAULT_SALT,
max_priority_fee_per_gas=None,
**kwargs,
) -> tuple[Address, bytes]:
"""
Expand All @@ -175,6 +181,7 @@ def deploy_code(
:param constructor_calldata: The calldata for the contract constructor.
:param dependency_bytecodes: The bytecodes of the blueprints.
:param salt: The salt for the contract deployment.
:param max_priority_fee_per_gas: The max priority fee per gas for the transaction.
:param kwargs: Additional parameters for the transaction.
:return: The address of the deployed contract and the bytecode hash.
"""
Expand All @@ -199,10 +206,10 @@ def deploy_code(
bytecode_hash = _hash_code(bytecode)
tx = DeployTransaction(
sender=sender,
to=_CONTRACT_DEPLOYER_ADDRESS,
to=CONTRACT_DEPLOYER_ADDRESS,
gas=gas or 0,
gas_price=gas_price,
max_priority_fee_per_gas=kwargs.pop("max_priority_fee_per_gas", gas_price),
max_priority_fee_per_gas=max_priority_fee_per_gas or gas_price,
nonce=nonce,
value=value,
calldata=self.create.prepare_calldata(
Expand Down Expand Up @@ -234,7 +241,7 @@ def get_code(self, address: Address) -> bytes:
return self._rpc.fetch("eth_getCode", [address, "latest"])

def set_code(self, address: Address, bytecode: bytes):
return self._rpc.fetch("hardhat_setCode", [address, list(bytecode)])
return self._rpc.fetch("hardhat_setCode", [address, f"0x{bytecode.hex()}"])

def generate_address(self, alias: Optional[str] = None) -> _AddressType:
"""
Expand Down
45 changes: 38 additions & 7 deletions boa_zksync/types.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from dataclasses import dataclass, field
from functools import cached_property
from typing import Optional
from typing import TYPE_CHECKING, Optional

import rlp
from boa.contracts.call_trace import TraceFrame
from boa.contracts.vyper.vyper_contract import VyperDeployer
from boa.interpret import compiler_data
from boa.rpc import fixup_dict, to_bytes, to_hex
Expand All @@ -15,6 +16,13 @@
from vyper.compiler import CompilerData
from vyper.compiler.settings import OptimizationLevel

if TYPE_CHECKING:
from boa_zksync import ZksyncEnv

ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"
CONTRACT_DEPLOYER_ADDRESS = "0x0000000000000000000000000000000000008006"
DEFAULT_SALT = b"\0" * 32

_EIP712_TYPE = bytes.fromhex("71")
_EIP712_TYPES_SPEC = {
"EIP712Domain": [
Expand Down Expand Up @@ -76,7 +84,7 @@ def get_estimate_tx(self):
"to": self.to,
"gas": f"0x{self.gas:0x}",
"gasPrice": f"0x{self.gas_price:0x}",
"maxPriorityFeePerGas": f"0x{self.max_priority_fee_per_gas :0x}",
"maxPriorityFeePerGas": f"0x{self.max_priority_fee_per_gas:0x}",
"nonce": f"0x{self.nonce:0x}",
"value": f"0x{self.value:0x}",
"data": f"0x{self.calldata.hex()}",
Expand Down Expand Up @@ -218,9 +226,14 @@ def as_json_dict(self, sender_field="from"):
def as_tx_params(self):
return self.as_json_dict(sender_field="from_")

@property
def is_create(self) -> bool:
return self.to == CONTRACT_DEPLOYER_ADDRESS


@dataclass
class ZksyncComputation:
env: "ZksyncEnv"
msg: ZksyncMessage
output: bytes | None = None
error: VMError | None = None
Expand All @@ -231,7 +244,7 @@ class ZksyncComputation:
value: int = 0

@classmethod
def from_call_trace(cls, output: dict) -> "ZksyncComputation":
def from_call_trace(cls, env: "ZksyncEnv", output: dict) -> "ZksyncComputation":
"""Recursively constructs a ZksyncComputation from a debug_traceCall output."""
error = None
if output.get("error") is not None:
Expand All @@ -240,6 +253,7 @@ def from_call_trace(cls, output: dict) -> "ZksyncComputation":
error = Revert(output["revertReason"])

return cls(
env=env,
msg=ZksyncMessage(
sender=Address(output["from"]),
to=Address(output["to"]),
Expand All @@ -249,15 +263,17 @@ def from_call_trace(cls, output: dict) -> "ZksyncComputation":
),
output=to_bytes(output["output"]),
error=error,
children=[cls.from_call_trace(call) for call in output.get("calls", [])],
children=[
cls.from_call_trace(env, call) for call in output.get("calls", [])
],
gas_used=int(output["gasUsed"], 16),
revert_reason=output.get("revertReason"),
type=output.get("type", "Call"),
value=int(output.get("value", "0x"), 16),
)

@classmethod
def from_debug_trace(cls, output: dict):
def from_debug_trace(cls, env: "ZksyncEnv", output: dict):
"""
Finds the actual transaction computation, since zksync has system
contract calls in the trace.
Expand All @@ -270,12 +286,12 @@ def _find(calls: list[dict]):
if found := _find(trace["calls"]):
return found
if trace["to"] == to and trace["from"] == sender:
return cls.from_call_trace(trace)
return cls.from_call_trace(env, trace)

if result := _find(output["calls"]):
return result
# in production mode the result is not always nested
return cls.from_call_trace(output)
return cls.from_call_trace(env, output)

@property
def is_success(self) -> bool:
Expand All @@ -302,3 +318,18 @@ def raise_if_error(self) -> None:

def get_gas_used(self):
return self.gas_used

@property
def net_gas_used(self) -> int:
return self.get_gas_used()

@property
def call_trace(self) -> TraceFrame:
return self._get_call_trace()

def _get_call_trace(self, depth=0) -> TraceFrame:
address = self.msg.to
contract = self.env.lookup_contract(address)
source = contract.trace_source(self) if contract else None
children = [child._get_call_trace(depth + 1) for child in self.children]
return TraceFrame(self, source, depth, children)
4 changes: 2 additions & 2 deletions boa_zksync/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def stop_subprocess(proc: Popen[bytes]):


def install_zkvyper_compiler(
source="https://raw.githubusercontent.com/matter-labs/zkvyper-bin/v1.5.3/linux-amd64/zkvyper-linux-amd64-musl-v1.5.3", # noqa: E501
source="https://raw.githubusercontent.com/matter-labs/zkvyper-bin/v1.5.4/linux-amd64/zkvyper-linux-amd64-musl-v1.5.4", # noqa: E501
destination="/usr/local/bin/zkvyper",
):
"""
Expand All @@ -58,7 +58,7 @@ def install_zkvyper_compiler(


def install_era_test_node(
source="https://github.com/matter-labs/era-test-node/releases/download/v0.1.0-alpha.25/era_test_node-v0.1.0-alpha.25-x86_64-unknown-linux-gnu.tar.gz", # noqa: E501
source="https://github.com/matter-labs/era-test-node/releases/download/v0.1.0-alpha.27/era_test_node-v0.1.0-alpha.27-x86_64-unknown-linux-gnu.tar.gz", # noqa: E501
destination="/usr/local/bin/era_test_node",
):
"""
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "titanoboa-zksync"
version = "0.2.2"
version = "0.2.3"
description = "A Zksync plugin for the Titanoboa Vyper interpreter"
license = { file = "LICENSE" }
readme = "README.md"
Expand All @@ -14,7 +14,7 @@ keywords = [
]
classifiers = ["Topic :: Software Development"]

dependencies = ["titanoboa>=0.2.0"]
dependencies = ["titanoboa>=0.2.2"]

[project.optional-dependencies]
forking-recommended = ["ujson"]
Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def zksync_sepolia_fork(account):
fork_url = os.getenv("FORK_URL", "https://sepolia.era.zksync.dev")
boa_zksync.set_zksync_fork(
fork_url,
block_identifier=1689570,
block_identifier=3000000,
node_args=("--show-calls", "all", "--show-outputs", "true"),
)
boa.env.add_account(account, force_eoa=True)
Expand Down
5 changes: 4 additions & 1 deletion tests/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ def _javascript_call(js_func: str, *args, timeout_message: str) -> Any:
if method == "evm_snapshot":
return 1

if method == "eth_requestAccounts":
return [ZERO_ADDRESS]

if method == "evm_revert":
assert args[1:] == ([1],), f"Bad args passed to mock: {args}"
return None
Expand All @@ -26,7 +29,7 @@ def _javascript_call(js_func: str, *args, timeout_message: str) -> Any:

raise KeyError(args)

if js_func == "loadSigner":
if js_func in "loadSigner":
return ZERO_ADDRESS

raise KeyError(js_func)
Expand Down
4 changes: 2 additions & 2 deletions tests/test_computation.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def test_from_debug_trace_nested():
},
],
}
assert ZksyncComputation.from_debug_trace(output).output == result
assert ZksyncComputation.from_debug_trace(boa.env, output).output == result


def test_from_debug_trace_production_mode():
Expand All @@ -51,4 +51,4 @@ def test_from_debug_trace_production_mode():
"calls": [],
**_required_fields,
}
assert ZksyncComputation.from_debug_trace(output).output == result
assert ZksyncComputation.from_debug_trace(boa.env, output).output == result
Loading

0 comments on commit b2c83e3

Please sign in to comment.