Skip to content

Commit

Permalink
Expose timestamp
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielSchiavini committed May 15, 2024
1 parent e12f051 commit 7faaa2d
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 6 deletions.
41 changes: 36 additions & 5 deletions boa_zksync/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from functools import cached_property
from hashlib import sha256
from pathlib import Path
from typing import Any, Iterable, Optional
from typing import Any, Iterable, Optional, Type
from unittest.mock import MagicMock

from boa.contracts.abi.abi_contract import ABIContract, ABIContractFactory
Expand Down Expand Up @@ -37,10 +37,7 @@ def __init__(self, rpc: str | RPC, *args, **kwargs):
self.evm = None # not used in zkSync
self.eoa = self.generate_address("eoa")
self.last_receipt: dict | None = None

@property
def vm(self):
return MagicMock() # todo: vyper base contract is calling vm directly
self._reset_vm()

@cached_property
def create(self):
Expand Down Expand Up @@ -77,6 +74,13 @@ def fork_rpc(
self.sha3_trace: dict = {}
self.sstore_trace: dict = {}
self._rpc = EraTestNode(rpc, block_identifier)
self._reset_vm()

def _reset_vm(self):
self.vm = MagicMock(state=_RPCState(self._rpc))
if isinstance(self._rpc, EraTestNode) and not self._rpc.inner_rpc:
# todo: era test node returns wrong block timestamp on startup
self.vm.state.timestamp = self.vm.state.timestamp

def register_contract(self, address, obj):
addr = Address(address)
Expand Down Expand Up @@ -249,3 +253,30 @@ def _hash_code(bytecode: bytes) -> bytes:
assert bytecode_size < 2**16, "Bytecode length must be less than 2^16"
bytecode_hash = sha256(bytecode).digest()
return b"\x01\00" + bytecode_size.to_bytes(2, byteorder="big") + bytecode_hash[4:]


class _RPCProperty:
def __init__(self, getter, setter):
self.getter = getter
self.setter = setter

def __set_name__(self, owner: Type["_RPCState"], name: str) -> None:
... # python descriptor protocol

def __get__(self, state: "_RPCState", owner):
if state is None:
return self # static call
return self.getter(state.rpc)

def __set__(self, state: "_RPCState", value):
self.setter(state.rpc, value)


class _RPCState:
timestamp = _RPCProperty(
lambda rpc: to_int(rpc.fetch("eth_getBlockByNumber", ["latest", False])["timestamp"]),
lambda rpc, value: rpc.fetch("evm_setNextBlockTimestamp", [value]),
)

def __init__(self, rpc):
self.rpc = rpc
1 change: 0 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

@pytest.fixture(scope="module")
def zksync_env(account):
boa.interpret.disable_cache() # todo: remove this when api is stable
old_env = boa.env
boa_zksync.set_zksync_test_env()
boa.env.add_account(account, force_eoa=True)
Expand Down
14 changes: 14 additions & 0 deletions tests/test_deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,17 @@ def transfer(_to : address, _value : uint256) -> bool:
to = boa.env.generate_address()
contract.transfer(to, 10)
assert [str(e) for e in contract.get_logs()] == [f"Transfer(sender={boa.env.eoa}, receiver={to}, value=10)"]


def test_time(zksync_env):
code = """
@external
@view
def get_time() -> uint256:
return block.timestamp
"""
# TODO: For some reason the RPC vs the VM timestamp is off by 1
contract = boa.loads(code)
assert contract.get_time() == boa.env.vm.state.timestamp + 1
boa.env.vm.state.timestamp = 1234567890
assert contract.get_time() == 1234567890 + 1

0 comments on commit 7faaa2d

Please sign in to comment.