Skip to content

Add ERC7803Utils and ERC7803#5722

Closed
ernestognw wants to merge 3 commits intoOpenZeppelin:masterfrom
ernestognw:feat/erc-7803
Closed

Add ERC7803Utils and ERC7803#5722
ernestognw wants to merge 3 commits intoOpenZeppelin:masterfrom
ernestognw:feat/erc-7803

Conversation

@ernestognw
Copy link
Member

Fixes #????

PR Checklist

  • Tests
  • Documentation
  • Changeset entry (run npx changeset add)

@changeset-bot
Copy link

changeset-bot bot commented Jun 7, 2025

⚠️ No Changeset found

Latest commit: 100db0f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@ernestognw ernestognw changed the title Add ERC7803 Add ERC7803Utils and ERC7803 Jun 7, 2025
@ernestognw ernestognw added this to the 5.x milestone Jun 7, 2025
Comment on lines +38 to +49
return
signingDomainSeparators.length == 0
? MessageHashUtils.toTypedDataHash(verifyingDomainSeparator, structHash)
: MessageHashUtils.toSigningDomainHash(
signingDomainSeparators[0],
// TODO: Make iterative?
encodeForSigningDomains(
_splice(signingDomainSeparators, 1, signingDomainSeparators.length),
verifyingDomainSeparator,
structHash
)
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of the recurtion here, particularly because it require a _splice that is memory intensive. A simple for loop should work just fine

Suggested change
return
signingDomainSeparators.length == 0
? MessageHashUtils.toTypedDataHash(verifyingDomainSeparator, structHash)
: MessageHashUtils.toSigningDomainHash(
signingDomainSeparators[0],
// TODO: Make iterative?
encodeForSigningDomains(
_splice(signingDomainSeparators, 1, signingDomainSeparators.length),
verifyingDomainSeparator,
structHash
)
);
bytes32 result = MessageHashUtils.toTypedDataHash(verifyingDomainSeparator, structHash);
for (uint256 i = signingDomainSeparators.length; i > 0; --i) {
result = MessageHashUtils.toSigningDomainHash(signingDomainSeparators[i-1], result);
}
return result;

Comment on lines +60 to +68
if (methodBytes.length < 4) return (false, 0);

// Check if it starts with "ERC-"
if (!(methodBytes[0] == "E" && methodBytes[1] == "R" && methodBytes[2] == "C" && methodBytes[3] == "-")) {
return (false, 0);
}

// Extract and validate the ERC number
return Strings.tryParseUint(string(Bytes.slice(methodBytes, 4)));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (methodBytes.length < 4) return (false, 0);
// Check if it starts with "ERC-"
if (!(methodBytes[0] == "E" && methodBytes[1] == "R" && methodBytes[2] == "C" && methodBytes[3] == "-")) {
return (false, 0);
}
// Extract and validate the ERC number
return Strings.tryParseUint(string(Bytes.slice(methodBytes, 4)));
return (methodBytes.length > 4 && bytes4(methodBytes) == 0x4552432d)
? Strings.tryParseUint(string(Bytes.slice(methodBytes, 4)))
: (false, 0);


/// @dev Checks if an authentication method ID corresponds to ECDSA.
function isECDSA(string memory methodId) internal pure returns (bool) {
return Strings.equal(methodId, "ECDSA");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we know the string, and when the length is <=32, it is cheaper (but arguably less readable) to compare things directly

Suggested change
return Strings.equal(methodId, "ECDSA");
return bytes(methodId).length == 5 && bytes5(bytes(methodId)) == 0x4543445341;

return
(_isValidERC7803Signature(hash, signature) || _rawSignatureValidation(hash, signature))
? IERC1271.isValidSignature.selector
: (hash == 0x7803780378037803780378037803780378037803780378037803780378037803 && signature.length == 0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK, ERC-7803 doesn't document anything like this

Copy link
Collaborator

@Amxx Amxx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • isECDSA and isERC are not (currently) used. I'm not sure we really need them.
  • the signature decoding is not standardized in the ERC document. We should probably ask the ERC to standardized that part. Note that the bytes32[] could be packed encoded.

One thing I'm concerned with is that passing the signingDomainSeparators through the signature is probably not the right way to proceed. We need some sort of verification that the domain separator of the actual contract was used. I would expect the implementation to not add anything in the signature (as opposed to ERC-7739).

On the "onchain" side, ERC-7803 would be an abstract signer layer that would "only" do something like:

abstract contract ERC7803 is AbstractSigner, EIP712 {
    using MessageHashUtils from bytes32;

    function isValidSignature(bytes32 hash, bytes calldata signature) public view virtual returns (bytes4 result) {
        return 
            _rawSignatureValidation(_domainSeparatorV4().toSigningDomainHash(hash), signature)
                ? bytes4(0x78030001)
                : bytes4(0xffffffff);
    }
}

_rawSignatureValidation would then either verify the signature directly (P256/ECDSA/...) or pass that to another SCA (through 127) that would eventually repeat the ERC-7803 hash processing, encapsulating it with the next signingDomainSeparators

@Amxx
Copy link
Collaborator

Amxx commented Jun 18, 2025

As discussed yesterday, closing this PR.

@Amxx Amxx closed this Jun 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants