From d0af52970bbd247027ca29c7054592a2e13bd6af Mon Sep 17 00:00:00 2001 From: cguerre-giordano Date: Tue, 24 Sep 2024 14:29:44 +0200 Subject: [PATCH 1/4] Use dict[str, Any] as type for screen --- pdm.lock | 4 ++-- pyproject.toml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pdm.lock b/pdm.lock index 833b26d..c9b3d35 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "dev"] strategy = ["inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:494f1581b64b1d7e745ffe2e4e22813054be8073203b816f00b374e176bcc2cf" +content_hash = "sha256:472941541bc2c7cad2497becae7d4319d0d24bd45e43ab85e0cc36d78015260e" [[metadata.targets]] requires_python = ">=3.12,<3.13" @@ -445,7 +445,7 @@ name = "prettydiff" version = "0.1.0" requires_python = ">=3.6" summary = "Pretty JSON data diffs" -groups = ["dev"] +groups = ["default", "dev"] files = [ {file = "prettydiff-0.1.0-py3-none-any.whl", hash = "sha256:253eea65c5c632219078dffcec5884260b805e200e3cbdb1039f45b2d2bc6d1e"}, {file = "prettydiff-0.1.0.tar.gz", hash = "sha256:e0e5ffaa20ee7f8a0295732a954c2fbb2ff37471953f8ab8b0122cbe19497e55"}, diff --git a/pyproject.toml b/pyproject.toml index 66861fb..cfc8f4f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,6 +28,7 @@ dependencies = [ "eth_hash", "rich", "typer", + "prettydiff", ] [project.urls] From 86367ecf88defafd6e2cc60aedb39f2e61ad7fb8 Mon Sep 17 00:00:00 2001 From: cguerre-giordano Date: Tue, 24 Sep 2024 15:10:48 +0200 Subject: [PATCH 2/4] Mode prettydiff to dev dependencies --- pdm.lock | 4 ++-- pyproject.toml | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pdm.lock b/pdm.lock index c9b3d35..833b26d 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "dev"] strategy = ["inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:472941541bc2c7cad2497becae7d4319d0d24bd45e43ab85e0cc36d78015260e" +content_hash = "sha256:494f1581b64b1d7e745ffe2e4e22813054be8073203b816f00b374e176bcc2cf" [[metadata.targets]] requires_python = ">=3.12,<3.13" @@ -445,7 +445,7 @@ name = "prettydiff" version = "0.1.0" requires_python = ">=3.6" summary = "Pretty JSON data diffs" -groups = ["default", "dev"] +groups = ["dev"] files = [ {file = "prettydiff-0.1.0-py3-none-any.whl", hash = "sha256:253eea65c5c632219078dffcec5884260b805e200e3cbdb1039f45b2d2bc6d1e"}, {file = "prettydiff-0.1.0.tar.gz", hash = "sha256:e0e5ffaa20ee7f8a0295732a954c2fbb2ff37471953f8ab8b0122cbe19497e55"}, diff --git a/pyproject.toml b/pyproject.toml index cfc8f4f..66861fb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,6 @@ dependencies = [ "eth_hash", "rich", "typer", - "prettydiff", ] [project.urls] From a49ab4a6f1b30207241dbcc6b63665458845fad8 Mon Sep 17 00:00:00 2001 From: cguerre-giordano Date: Wed, 25 Sep 2024 17:09:50 +0200 Subject: [PATCH 3/4] ERC-7730 to EIP-712 conversion allows invalid paths #27 --- src/erc7730/model/display.py | 4 +- src/erc7730/model/types.py | 1 + tests/resources/eip712_wrong_path.json | 206 +++++++++++++++++++++ tests/src/erc7730/common/test_datamodel.py | 15 +- tests/src/erc7730/mapper/test_mapper.py | 2 + 5 files changed, 225 insertions(+), 3 deletions(-) create mode 100644 tests/resources/eip712_wrong_path.json diff --git a/src/erc7730/model/display.py b/src/erc7730/model/display.py index 4261ca2..07cb26b 100644 --- a/src/erc7730/model/display.py +++ b/src/erc7730/model/display.py @@ -1,5 +1,5 @@ from erc7730.model.base import BaseLibraryModel -from erc7730.model.types import Id +from erc7730.model.types import Id, Path from typing import Annotated, Any, Dict, ForwardRef, Optional, Union from enum import Enum from pydantic import Discriminator, RootModel, Field as PydanticField, Tag @@ -123,7 +123,7 @@ def get_param_discriminator(v: Any) -> str | None: class FieldDescription(BaseLibraryModel): - path: Optional[str] = None + path: Optional[Path] = None field_id: Optional[Id] = PydanticField(None, alias="$id") label: str format: FieldFormat diff --git a/src/erc7730/model/types.py b/src/erc7730/model/types.py index a640ba4..3062028 100644 --- a/src/erc7730/model/types.py +++ b/src/erc7730/model/types.py @@ -3,3 +3,4 @@ Id = Ann[str, Field(min_length=1)] ContractAddress = Ann[str, Field(min_length=0, max_length=64, pattern=r"^[a-zA-Z0-9_\-]+$")] +Path = Ann[str, Field(pattern=r"^[a-zA-Z0-9.\[\]_]+")] diff --git a/tests/resources/eip712_wrong_path.json b/tests/resources/eip712_wrong_path.json new file mode 100644 index 0000000..f1a59e4 --- /dev/null +++ b/tests/resources/eip712_wrong_path.json @@ -0,0 +1,206 @@ +{ + "$schema": "../../clear-signing-erc7730-registry/specs/erc7730-v1.schema.json", + + "metadata": { + "owner": "Uniswap", + "info": { + "legalName": "Uniswap Labs", + "lastUpdate": "2021-12-14T00:00:00Z", + "url": "https://uniswap.org/" + } + }, + + "context": { + "eip712": { + "domain": { + "name": "Permit2" + }, + "deployments": [ + { + "chainId": 1, + "address": "0x000000000022D473030F116dDEE9F6B43aC78BA3" + } + ], + "schemas": [ + { + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "PermitDetails": [ + { + "name": "token", + "type": "address" + }, + { + "name": "amount", + "type": "uint160" + }, + { + "name": "expiration", + "type": "uint48" + }, + { + "name": "nonce", + "type": "uint48" + } + ], + "PermitBatch": [ + { + "name": "details", + "type": "PermitDetails[]" + }, + { + "name": "spender", + "type": "address" + }, + { + "name": "sigDeadline", + "type": "uint256" + } + ] + }, + "primaryType": "PermitBatch" + }, + { + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "PermitDetails": [ + { + "name": "token", + "type": "address" + }, + { + "name": "amount", + "type": "uint160" + }, + { + "name": "expiration", + "type": "uint48" + }, + { + "name": "nonce", + "type": "uint48" + } + ], + "PermitSingle": [ + { + "name": "details", + "type": "PermitDetails" + }, + { + "name": "spender", + "type": "address" + }, + { + "name": "sigDeadline", + "type": "uint256" + } + ] + }, + "primaryType": "PermitSingle" + } + ] + } + }, + + "display": { + "formats": { + + "PermitSingle": { + "$id": "Permit2 Permit Single", + "intent": "Authorize spending of token", + "fields": [ + { + "path": "@spender", + "label": "Spender", + "format": "addressName" + }, + { + "path": "details.amount[]", + "label": "Amount allowance", + "format": "tokenAmount", + "params": { + "tokenPath": "details.token" + } + }, + { + "path": "details$.expiration", + "label": "Approval expires", + "format": "date", + "params": { + "encoding": "timestamp" + } + } + ], + "required": [ + "spender", + "details.amount" + ], + "screens": {} + }, + + "PermitBatch": { + "$id": "Permit2 Permit Batch", + "intent": "Authorize spending of tokens", + "fields": [ + { + "path": ";spender", + "label": "Spender", + "format": "addressName" + }, + { + "path": "|details.[]", + "fields": [ + { + "path": "#amount", + "label": "Amount allowance", + "format": "tokenAmount", + "params": { + "tokenPath": "token" + } + }, + { + "path": "%expiration", + "label": "Approval expires", + "format": "date", + "params": { + "encoding": "timestamp" + } + } + ] + } + ], + "required": [ + "spender", + "details" + ], + "screens": {} + } + } + } +} diff --git a/tests/src/erc7730/common/test_datamodel.py b/tests/src/erc7730/common/test_datamodel.py index 33e32ee..baf1005 100644 --- a/tests/src/erc7730/common/test_datamodel.py +++ b/tests/src/erc7730/common/test_datamodel.py @@ -8,8 +8,10 @@ import json from jsonschema import validate, exceptions from prettydiff import print_diff +from pydantic_core import ValidationError + +files = glob.glob("clear-signing-erc7730-registry/registry/*/*[!calldata-stETH].json") -files = glob.glob("clear-signing-erc7730-registry/registry/*/*.json") with open("clear-signing-erc7730-registry/specs/erc7730-v1.schema.json", "r") as file: schema = json.load(file) @@ -38,3 +40,14 @@ def test_23_unset_attributes_must_not_be_serialized_as_set() -> None: abi_item_json_str_deserialized = json_file_from_model(AbiJsonSchemaItem, abi_item) print_diff(abi_item_json_str, abi_item_json_str_deserialized) assert abi_item_json_str == abi_item_json_str_deserialized + + +def test_27_erc7730_allows_invalid_paths() -> None: + errors = None + try: + ERC7730Descriptor.load_or_none(Path("tests/resources/eip712_wrong_path.json")) + except ValidationError as ex: + assert ex.error_count() == 4 + errors = ex.errors + finally: + assert errors is not None diff --git a/tests/src/erc7730/mapper/test_mapper.py b/tests/src/erc7730/mapper/test_mapper.py index 88d320f..7cecba6 100644 --- a/tests/src/erc7730/mapper/test_mapper.py +++ b/tests/src/erc7730/mapper/test_mapper.py @@ -1,6 +1,7 @@ import json from jsonschema import validate, exceptions from pathlib import Path + from erc7730.common.pydantic import json_file_from_model from erc7730.model.erc7730_descriptor import ERC7730Descriptor from erc7730.mapper.mapper import to_eip712_mapper, to_erc7730_mapper @@ -8,6 +9,7 @@ import pytest import glob + inputs = glob.glob("clear-signing-erc7730-registry/registry/*/eip712*.json") with open("tests/resources/eip712.schema.json", "r") as file: From 79eca532373493231521e98f820803c4c10ade84 Mon Sep 17 00:00:00 2001 From: cguerre-giordano Date: Wed, 25 Sep 2024 21:30:53 +0200 Subject: [PATCH 4/4] Fix glob pattern --- tests/src/erc7730/common/test_datamodel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/erc7730/common/test_datamodel.py b/tests/src/erc7730/common/test_datamodel.py index baf1005..860925b 100644 --- a/tests/src/erc7730/common/test_datamodel.py +++ b/tests/src/erc7730/common/test_datamodel.py @@ -10,7 +10,7 @@ from prettydiff import print_diff from pydantic_core import ValidationError -files = glob.glob("clear-signing-erc7730-registry/registry/*/*[!calldata-stETH].json") +files = glob.glob("clear-signing-erc7730-registry/registry/*/*[!stETH].json") with open("clear-signing-erc7730-registry/specs/erc7730-v1.schema.json", "r") as file: schema = json.load(file)