diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index 15c52b89..ba698df4 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -79,6 +79,7 @@ gnosis.eth.constants gnosis.eth.eip712 ~~~~~~~~~~~~~~~~~~~~ .. code-block:: python + from gnosis.eth.eip712 import eip712_encode_hash types = {'EIP712Domain': [{'name': 'name', 'type': 'string'}, diff --git a/gnosis/eth/eip712/__init__.py b/gnosis/eth/eip712/__init__.py index 1e251c18..17ea2aea 100644 --- a/gnosis/eth/eip712/__init__.py +++ b/gnosis/eth/eip712/__init__.py @@ -137,17 +137,22 @@ def eip712_encode(typed_data: Dict[str, Any]) -> List[bytes]: 1: The encoded types 2: The encoded data """ - parts = [ - bytes.fromhex("1901"), - hash_struct("EIP712Domain", typed_data["domain"], typed_data["types"]), - ] - if typed_data["primaryType"] != "EIP712Domain": - parts.append( - hash_struct( - typed_data["primaryType"], typed_data["message"], typed_data["types"] + try: + parts = [ + bytes.fromhex("1901"), + hash_struct("EIP712Domain", typed_data["domain"], typed_data["types"]), + ] + if typed_data["primaryType"] != "EIP712Domain": + parts.append( + hash_struct( + typed_data["primaryType"], + typed_data["message"], + typed_data["types"], + ) ) - ) - return parts + return parts + except (KeyError, AttributeError, TypeError, IndexError) as exc: + raise ValueError(f"Not valid {typed_data}") from exc def eip712_encode_hash(typed_data: Dict[str, Any]) -> Hash32: diff --git a/gnosis/eth/tests/eip712/__init__.py b/gnosis/eth/tests/eip712/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/gnosis/eth/tests/eip712/test_eip712.py b/gnosis/eth/tests/eip712/test_eip712.py new file mode 100644 index 00000000..446466fc --- /dev/null +++ b/gnosis/eth/tests/eip712/test_eip712.py @@ -0,0 +1,91 @@ +from unittest import TestCase + +from gnosis.eth.eip712 import eip712_encode_hash + + +class TestEIP712(TestCase): + def test_eip712_encode_hash(self): + for value in [ + {}, + None, + ]: + with self.assertRaises(ValueError): + eip712_encode_hash(value) + + address = "0x8e12f01dae5fe7f1122dc42f2cb084f2f9e8aa03" + + wrong_types = { + "EIP712Domain": [ + {"name": "name", "type": "stringa"}, + {"name": "version", "type": "bstring"}, + {"name": "chainId", "type": "aaauint256"}, + {"name": "verifyingContract", "type": "address"}, + ], + "Mailbox": [ + {"name": "owner", "type": "address"}, + {"name": "messages", "type": "Message[]"}, + ], + "Message": [ + {"name": "sender", "type": "address"}, + {"name": "subject", "type": "string"}, + {"name": "isSpam", "type": "bool"}, + {"name": "body", "type": "string"}, + ], + } + + types = { + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "chainId", "type": "uint256"}, + {"name": "verifyingContract", "type": "address"}, + ], + "Mailbox": [ + {"name": "owner", "type": "address"}, + {"name": "messages", "type": "Message[]"}, + ], + "Message": [ + {"name": "sender", "type": "address"}, + {"name": "subject", "type": "string"}, + {"name": "isSpam", "type": "bool"}, + {"name": "body", "type": "string"}, + ], + } + + msgs = [ + { + "sender": address, + "subject": "Hello World", + "body": "The sparrow flies at midnight.", + "isSpam": False, + }, + { + "sender": address, + "subject": "You may have already Won! :dumb-emoji:", + "body": "Click here for sweepstakes!", + "isSpam": True, + }, + ] + + mailbox = {"owner": address, "messages": msgs} + + payload = { + "types": wrong_types, + "primaryType": "Mailbox", + "domain": { + "name": "MyDApp", + "version": "3.0", + "chainId": 41, + "verifyingContract": address, + }, + "message": mailbox, + } + + with self.assertRaises(ValueError): + eip712_encode_hash(payload) + + payload["types"] = types + self.assertEqual( + eip712_encode_hash(payload), + b"\xd5N\xcbf7\xfa\x99\n\xae\x02\x86\xd4 \xacpe\x8d\xb9\x95\xaem\t\xcc\x9b\xb1\xda\xcf6J\x14\x17\xd0", + )