Add ERC7913 signers and utilities (#5659)

Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
This commit is contained in:
Ernesto García
2025-06-05 09:22:26 -06:00
committed by GitHub
parent 8bff2a72d9
commit 1d9400e053
17 changed files with 1374 additions and 6 deletions

View File

@ -97,6 +97,80 @@ function _verify(
IMPORTANT: Always use keys of at least 2048 bits. Additionally, be aware that PKCS#1 v1.5 allows for replayability due to the possibility of arbitrary optional parameters. To prevent replay attacks, consider including an onchain nonce or unique identifier in the message.
=== Signature Verification
The xref:api:utils.adoc#SignatureChecker[`SignatureChecker`] library provides a unified interface for verifying signatures from different sources. It seamlessly supports:
* ECDSA signatures from externally owned accounts (EOAs)
* ERC-1271 signatures from smart contract wallets like Argent and Safe Wallet
* ERC-7913 signatures from keys that don't have their own Ethereum address
This allows developers to write signature verification code once and have it work across all these different signature types.
==== Basic Signature Verification
For standard signature verification that supports both EOAs and ERC-1271 contracts:
[source,solidity]
----
using SignatureChecker for address;
function _verifySignature(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) {
return SignatureChecker.isValidSignatureNow(signer, hash, signature);
}
----
The library automatically detects whether the signer is an EOA or a contract and uses the appropriate verification method.
==== ERC-1271 Contract Signatures
For smart contract wallets that implement ERC-1271, you can explicitly use:
[source,solidity]
----
function _verifyContractSignature(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) {
return SignatureChecker.isValidERC1271SignatureNow(signer, hash, signature);
}
----
==== ERC-7913 Extended Signatures
ERC-7913 extends signature verification to support keys that don't have their own Ethereum address. This is useful for integrating non-Ethereum cryptographic curves, hardware devices, or other identity systems.
A signer is represented as a `bytes` object that concatenates a verifier address and a key: `verifier || key`.
[source,solidity]
----
function _verifyERC7913Signature(bytes memory signer, bytes32 hash, bytes memory signature) internal view returns (bool) {
return SignatureChecker.isValidERC7913SignatureNow(signer, hash, signature);
}
----
The verification process works as follows:
* If `signer.length < 20`: verification fails
* If `signer.length == 20`: verification is done using standard signature checking
* Otherwise: verification is done using an ERC-7913 verifier
==== Batch Verification
For verifying multiple ERC-7913 signatures at once:
[source,solidity]
----
function _verifyMultipleSignatures(
bytes32 hash,
bytes[] memory signers,
bytes[] memory signatures
) internal view returns (bool) {
return SignatureChecker.areValidERC7913SignaturesNow(hash, signers, signatures);
}
----
This function will reject inputs that contain duplicated signers. Sorting the signers by their `keccak256` hash is recommended to minimize the gas cost.
This unified approach allows smart contracts to accept signatures from any supported source without needing to implement different verification logic for each type.
=== Verifying Merkle Proofs
Developers can build a Merkle Tree off-chain, which allows for verifying that an element (leaf) is part of a set by using a Merkle Proof. This technique is widely used for creating whitelists (e.g., for airdrops) and other advanced use cases.