Skip to content

Commit

Permalink
ERC-7730 to EIP-712 conversion allows invalid paths #27 (#31)
Browse files Browse the repository at this point in the history
* Use dict[str, Any] as type for screen

* Mode prettydiff to dev dependencies

* ERC-7730 to EIP-712 conversion allows invalid paths #27

* Fix glob pattern

---------

Co-authored-by: jnicoulaud-ledger <102984500+jnicoulaud-ledger@users.noreply.github.com>
  • Loading branch information
ClaireGuerreGiordano and jnicoulaud-ledger authored Sep 26, 2024
1 parent 7e43103 commit f56c9d0
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 7 deletions.
4 changes: 2 additions & 2 deletions src/erc7730/model/display.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/erc7730/model/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.\[\]_]+")]
206 changes: 206 additions & 0 deletions tests/resources/eip712_wrong_path.json
Original file line number Diff line number Diff line change
@@ -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": {}
}
}
}
}
19 changes: 14 additions & 5 deletions tests/src/erc7730/common/test_datamodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,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/*/*[!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)

Expand All @@ -30,21 +32,28 @@ def test_from_erc7730(file: str) -> None:
assert json_from_model == original_dict_with_includes


abi_item_json_str = '{"name":"approve","inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"type":"function"}'


def test_23_unset_attributes_must_not_be_serialized_as_set() -> None:
abi_item_json_str = '{"name":"approve","inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"type":"function"}'
abi_item_json = json.loads(abi_item_json_str)
abi_item = AbiJsonSchemaItem.model_validate(abi_item_json, strict=False)
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


display_json_str = '{"formats":{"Permit":{"screens":{"stax":[{"type":"propertyPage","label":"DAI Permit","content":["spender","value","deadline"]}]}}}}'
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


def test_22_screens_serialization_not_symmetric() -> None:
display_json_str = '{"formats":{"Permit":{"screens":{"stax":[{"type":"propertyPage","label":"DAI Permit","content":["spender","value","deadline"]}]}}}}'
display_json = json.loads(display_json_str)
display = Display.model_validate(display_json, strict=True)
display_json_deserialized = json_file_from_model(Display, display)
Expand Down
2 changes: 2 additions & 0 deletions tests/src/erc7730/mapper/test_mapper.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
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
from eip712 import EIP712DAppDescriptor
import pytest
import glob


inputs = glob.glob("clear-signing-erc7730-registry/registry/*/eip712*.json")

with open("tests/resources/eip712.schema.json", "r") as file:
Expand Down

0 comments on commit f56c9d0

Please sign in to comment.