Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ def _convert_v2_selector(
creator_name=descriptor.metadata.owner,
creator_legal_name=creator_legal_name,
creator_url=creator_url,
contract_name=descriptor.context.id,
contract_name=descriptor.metadata.contractName or descriptor.context.id,
deploy_date=deploy_date,
)

Expand Down
4 changes: 4 additions & 0 deletions src/erc7730/convert/calldata/v1/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ def convert_container_path(
field = CalldataDescriptorContainerPathValueV1.VALUE
type_family = CalldataDescriptorTypeFamily.UINT
type_size = 32
case ContainerField.CHAIN_ID:
field = CalldataDescriptorContainerPathValueV1.CHAIN_ID
type_family = CalldataDescriptorTypeFamily.UINT
type_size = 32
case _:
assert_never(path.field)
return CalldataDescriptorValuePathV1(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -483,16 +483,18 @@ def _convert_resolved(
domain = context.eip712.domain
has_deployments = len(context.eip712.deployments) > 0

# Get contract name from metadata
contract_name = descriptor.metadata.owner
if contract_name is None:
# owner is required for legacy EIP-712 conversion
if (owner := descriptor.metadata.owner) is None:
return out.error(
title="Missing owner",
message="metadata.owner is required for legacy EIP-712 conversion.",
)

# Get contract name from metadata, preferring the explicit contractName field
contract_name = descriptor.metadata.contractName or owner

# Get dapp name: prefer domain.name, fall back to metadata.owner
dapp_name: str = (domain.name if domain is not None and domain.name is not None else None) or contract_name
dapp_name: str = (domain.name if domain is not None and domain.name is not None else None) or owner

# Reconstruct EIP712Domain type
domain_fields = _reconstruct_eip712_domain(domain, has_deployments, out)
Expand Down
7 changes: 4 additions & 3 deletions src/erc7730/lint/v2/lint_validate_max_length.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,11 @@ def _validate_metadata_lengths(cls, descriptor: ResolvedERC7730Descriptor, out:
f"{CREATOR_URL_MAX_LENGTH} characters and may be truncated on Ledger devices.",
)

if descriptor.context.id is not None and len(descriptor.context.id) > CONTRACT_NAME_MAX_LENGTH:
contract_name = descriptor.metadata.contractName or descriptor.context.id
if contract_name is not None and len(contract_name) > CONTRACT_NAME_MAX_LENGTH:
out.warning(
title="Contract id too long",
message=f"Contract id `{descriptor.context.id}` exceeds "
title="Contract name too long",
message=f"Contract name `{contract_name}` exceeds "
f"{CONTRACT_NAME_MAX_LENGTH} characters and may be truncated on Ledger devices.",
)

Expand Down
1 change: 1 addition & 0 deletions src/erc7730/model/calldata/v1/value.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class CalldataDescriptorContainerPathValueV1(IntEnum):
FROM = 0x0
TO = 0x1
VALUE = 0x2
CHAIN_ID = 0x3


class CalldataDescriptorPathElementBaseV1(Model):
Expand Down
3 changes: 3 additions & 0 deletions src/erc7730/model/paths/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ class ContainerField(StrEnum):
TO = auto()
"""The destination address of the containing transaction, ie the target smart contract address."""

CHAIN_ID = "chainId"
"""The chain id of the transaction / verifying contract of the message."""


DataPathElement = Annotated[
Field | ArrayElement | ArraySlice | Array,
Expand Down
2 changes: 1 addition & 1 deletion src/erc7730/model/paths/path_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
?descriptor_path_component: field | array_element

container_path: "@." container_field
!container_field: "from" | "to" | "value"
!container_field: "from" | "to" | "value" | "chainId"

?data_path: absolute_data_path | relative_data_path
absolute_data_path: "#." data_path_component ("." data_path_component)*
Expand Down
16 changes: 16 additions & 0 deletions tests/model/paths/test_path_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ def test_valid_input_container_path() -> None:
)


def test_valid_input_container_path_chain_id() -> None:
_test_valid_input_path(
string="@.chainId",
obj=ContainerPath(field=ContainerField.CHAIN_ID),
json="""{ "type": "container", "field": "chainId" }""",
)


def test_valid_input_data_path_absolute() -> None:
_test_valid_input_path(
string="#.params.[].[-2].[1:5].[:5].[5:].amountIn",
Expand Down Expand Up @@ -135,6 +143,14 @@ def test_valid_resolved_container_path() -> None:
)


def test_valid_resolved_container_path_chain_id() -> None:
_test_valid_resolved_path(
string="@.chainId",
obj=ContainerPath(field=ContainerField.CHAIN_ID),
json="""{ "type": "container", "field": "chainId" }""",
)


def test_valid_resolved_data_path() -> None:
_test_valid_resolved_path(
string="#.params.[].[-2].[1:5].amountIn",
Expand Down
Loading