Skip to content

Commit

Permalink
feat: block number getter + setter
Browse files Browse the repository at this point in the history
  • Loading branch information
skellet0r committed Jun 30, 2021
1 parent 31cbe5a commit 001bd0a
Showing 1 changed file with 21 additions and 6 deletions.
27 changes: 21 additions & 6 deletions brownie/network/multicall.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@ def __repr__(self) -> str:


class Multicall:
"""Context manager for batching multiple calls to constant contract functions."""

def __init__(
self, address: str = None, block_identifier: Union[int, str, bytes] = None
) -> None:
self.address = address
self.block_identifier = block_identifier or chain.height
self._block_identifier = block_identifier or chain.height
self._pending_calls: List[Call] = []
self._complete = True

Expand All @@ -55,21 +57,21 @@ def __init__(
elif "cmd" in active_network:
if block_identifier is not None:
raise ContractNotFound(
f"Must deploy Multicall2 before block {self.block_identifier}. "
f"Must deploy Multicall2 before block {self._block_identifier}. "
"Use `Multicall2.deploy` classmethod to deploy an instance of Multicall2."
)
deployment = self.deploy({"from": accounts[0]})
self.address = deployment.address
self.block_identifier = deployment.tx.block_number # type: ignore
self._block_identifier = deployment.tx.block_number # type: ignore
else:
# live network and no address
raise ContractNotFound("Must provide Multicall2 address as argument")

if not web3.eth.get_code(self.address, self.block_identifier):
if not web3.eth.get_code(self.address, self._block_identifier):
# TODO: Handle deploying multicall in a test network without breaking the expected chain
# For Geth client's we can use state override to have multicall at any arbitrary address
raise ContractNotFound(
f"Multicall2 at `{self.address}` not available at block `{self.block_identifier}`"
f"Multicall2 at `{self.address}` not available at block `{self._block_identifier}`"
)

contract = Contract.from_abi("Multicall2", self.address, MULTICALL2_ABI) # type: ignore
Expand All @@ -84,7 +86,7 @@ def _flush(self, future_result: Result = None) -> Any:
results = self._contract.tryAggregate(
False,
[_call.calldata for _call in self._pending_calls],
block_identifier=self.block_identifier,
block_identifier=self._block_identifier,
)
if not self._complete:
ContractCall.__call__.__code__ = getattr(ContractCall, "__proxy_call_code")
Expand Down Expand Up @@ -141,6 +143,19 @@ def __exit__(self, exc_type: Exception, exc_val: Any, exc_tb: TracebackType) ->
self._complete = True
ContractCall.__call__.__code__ = getattr(ContractCall, "__original_call_code")

@property
def block_number(self) -> Union[int, str, bytes]:
return self._block_identifier

@block_number.setter
def block_number(self, value: Union[int, str, bytes]) -> None:
self.flush()
if not web3.eth.get_code(self.address, self._block_identifier):
raise ContractNotFound(
f"Multicall2 at `{self.address}` not available at block `{value}`"
)
self._block_identifier = value

@classmethod
def deploy(cls, tx_params: Dict) -> Contract:
project = compile_source(MULTICALL2_SOURCE)
Expand Down

0 comments on commit 001bd0a

Please sign in to comment.