Skip to content

Fixes bug #16 #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
16 changes: 12 additions & 4 deletions eip712_structs/struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ def data_dict(self):
for k, v in self.values.items():
if isinstance(v, EIP712Struct):
result[k] = v.data_dict()
elif isinstance(v, list) and len(v) and isinstance(v[0], EIP712Struct):
result[k] = [ e.data_dict() for e in v ]
else:
result[k] = v
return result
Expand All @@ -94,7 +96,7 @@ def _encode_type(cls, resolve_references: bool) -> str:
struct_sig = f'{cls.type_name}({",".join(member_sigs)})'

if resolve_references:
reference_structs = set()
reference_structs = list()
cls._gather_reference_structs(reference_structs)
sorted_structs = sorted(list(s for s in reference_structs if s != cls), key=lambda s: s.type_name)
for struct in sorted_structs:
Expand All @@ -105,10 +107,16 @@ def _encode_type(cls, resolve_references: bool) -> str:
def _gather_reference_structs(cls, struct_set):
"""Finds reference structs defined in this struct type, and inserts them into the given set.
"""
structs = [m[1] for m in cls.get_members() if isinstance(m[1], type) and issubclass(m[1], EIP712Struct)]
structs = [
m[1] for m in cls.get_members()
if isinstance(m[1], type) and issubclass(m[1], EIP712Struct)
] + [
m[1].member_type for m in cls.get_members()
if isinstance(m[1], Array) and hasattr(m[1].member_type, "encode_type")
]
for struct in structs:
if struct not in struct_set:
struct_set.add(struct)
struct_set.append(struct)
struct._gather_reference_structs(struct_set)

@classmethod
Expand Down Expand Up @@ -162,7 +170,7 @@ def to_message(self, domain: 'EIP712Struct' = None) -> dict:
:returns: This struct + the domain in dict form, structured as specified for EIP712 messages.
"""
domain = self._assert_domain(domain)
structs = {domain, self}
structs = [domain, self]
self._gather_reference_structs(structs)

# Build type dictionary
Expand Down
5 changes: 4 additions & 1 deletion eip712_structs/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ def __init__(self, member_type: Union[EIP712Type, Type[EIP712Type]], fixed_lengt
def _encode_value(self, value):
"""Arrays are encoded by concatenating their encoded contents, and taking the keccak256 hash."""
encoder = self.member_type
encoded_values = [encoder.encode_value(v) for v in value]
if hasattr(encoder, "hash_struct"):
encoded_values = [v.hash_struct() for v in value]
else:
encoded_values = [encoder.encode_value(v) for v in value]
return keccak(b''.join(encoded_values))


Expand Down