Skip to content

Commit

Permalink
Merge pull request #167 from DanielSchiavini/prepare-calldata
Browse files Browse the repository at this point in the history
feat: Extract prepare_calldata method for abi functions
  • Loading branch information
charles-cooper authored Feb 19, 2024
2 parents d5b4bf2 + f81d850 commit cd9ca25
Showing 1 changed file with 23 additions and 3 deletions.
26 changes: 23 additions & 3 deletions boa/contracts/abi/abi_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ def is_encodable(self, *args, **kwargs) -> bool:
for abi_type, arg in zip(self.argument_types, parsed_args)
)

def prepare_calldata(self, *args, **kwargs) -> bytes:
"""Prepare the call data for the function call."""
abi_args = self._merge_kwargs(*args, **kwargs)
return self.method_id + abi_encode(self.signature, abi_args)

def _merge_kwargs(self, *args, **kwargs) -> list:
"""Merge positional and keyword arguments into a single list."""
if len(kwargs) + len(args) != self.argument_count:
Expand All @@ -102,11 +107,10 @@ def __call__(self, *args, value=0, gas=None, sender=None, **kwargs):
if not self.contract or not self.contract.env:
raise Exception(f"Cannot call {self} without deploying contract.")

args = self._merge_kwargs(*args, **kwargs)
computation = self.contract.env.execute_code(
to_address=self.contract.address,
sender=sender,
data=self.method_id + abi_encode(self.signature, args),
data=self.prepare_calldata(*args, **kwargs),
value=value,
gas=gas,
is_modifying=self.is_mutable,
Expand Down Expand Up @@ -151,6 +155,13 @@ def __init__(self, functions: list[ABIFunction]):
def name(self) -> str:
return self.functions[0].name

def prepare_calldata(self, *args, disambiguate_signature=None, **kwargs) -> bytes:
"""Prepare the calldata for the function that matches the given arguments."""
function = self._pick_overload(
*args, disambiguate_signature=disambiguate_signature, **kwargs
)
return function.prepare_calldata(*args, **kwargs)

def __call__(
self,
*args,
Expand All @@ -164,6 +175,15 @@ def __call__(
Call the function that matches the given arguments.
:raises Exception: if a single function is not found
"""
function = self._pick_overload(
*args, disambiguate_signature=disambiguate_signature, **kwargs
)
return function(*args, value=value, gas=gas, sender=sender, **kwargs)

def _pick_overload(
self, *args, disambiguate_signature=None, **kwargs
) -> ABIFunction:
"""Pick the function that matches the given arguments."""
if disambiguate_signature is None:
matches = [f for f in self.functions if f.is_encodable(*args, **kwargs)]
else:
Expand All @@ -174,7 +194,7 @@ def __call__(

match matches:
case [function]:
return function(*args, value=value, gas=gas, sender=sender, **kwargs)
return function
case []:
raise Exception(
f"Could not find matching {self.name} function for given arguments."
Expand Down

0 comments on commit cd9ca25

Please sign in to comment.