ERC7739Utils
*Utilities to process https://ercs.ethereum.org/ERCS/erc-7739[ERC-7739] typed data signatures that are specific to an EIP-712 domain. This library provides methods to wrap, unwrap and operate over typed data signatures with a defensive rehashing mechanism that includes the app's xref:api:utils/cryptography#EIP712-_domainSeparatorV4[EIP-712] and preserves readability of the signed content using an EIP-712 nested approach. A smart contract domain can validate a signature for a typed data structure in two ways:
- As an application validating a typed data signature. See typedDataSignStructHash.
- As a smart contract validating a raw message signature. See {personalSignStructHash}.
NOTE: A provider for a smart contract wallet would need to return this signature as the
result of a call to
personal_signoreth_signTypedData, and this may be unsupported by API clients that expect a return value of 129 bytes, or specifically ther,s,vparameters of an xref:api:utils/cryptography#ECDSA[ECDSA] signature, as is for example specified for xref:api:utils/cryptography#EIP712[EIP-712].*
State Variables
PERSONAL_SIGN_TYPEHASH
An EIP-712 type to represent "personal" signatures
(i.e. mimic of personal_sign for smart contracts).
bytes32 private constant PERSONAL_SIGN_TYPEHASH = keccak256("PersonalSign(bytes prefixed)");
Functions
encodeTypedDataSig
Nest a signature for a given EIP-712 type into a nested signature for the domain of the app. Counterpart of decodeTypedDataSig to extract the original signature and the nested components.
function encodeTypedDataSig(
bytes memory signature,
bytes32 appSeparator,
bytes32 contentsHash,
string memory contentsDescr
) internal pure returns (bytes memory);
decodeTypedDataSig
*Parses a nested signature into its components.
Constructed as follows:
signature ‖ APP_DOMAIN_SEPARATOR ‖ contentsHash ‖ contentsDescr ‖ uint16(contentsDescr.length)
signatureis the signature for the (ERC-7739) nested struct hash. This signature indirectly signs over the original "contents" hash (from the app) and the account's domain separator.APP_DOMAIN_SEPARATORis the EIP-712 EIP712-_domainSeparatorV4 of the application smart contract that is requesting the signature verification (though ERC-1271).contentsHashis the hash of the underlying data structure or message.contentsDescris a descriptor of the "contents" part of the the EIP-712 type of the nested signature. NOTE: This function returns empty if the input format is invalid instead of reverting. data instead.*
function decodeTypedDataSig(bytes calldata encodedSignature)
internal
pure
returns (bytes calldata signature, bytes32 appSeparator, bytes32 contentsHash, string calldata contentsDescr);
personalSignStructHash
Nests an ERC-191 digest into a PersonalSign EIP-712 struct, and returns the corresponding struct hash.
This struct hash must be combined with a domain separator, using MessageHashUtils-toTypedDataHash before
being verified/recovered.
This is used to simulates the personal_sign RPC method in the context of smart contracts.
function personalSignStructHash(bytes32 contents) internal pure returns (bytes32);
typedDataSignStructHash
Nests an EIP-712 hash (contents) into a TypedDataSign EIP-712 struct, and returns the corresponding
struct hash. This struct hash must be combined with a domain separator, using MessageHashUtils-toTypedDataHash
before being verified/recovered.
function typedDataSignStructHash(
string calldata contentsName,
string calldata contentsType,
bytes32 contentsHash,
bytes memory domainBytes
) internal pure returns (bytes32 result);
typedDataSignStructHash
Variant of {typedDataSignStructHash-string-string-bytes32-bytes} that takes a content descriptor
and decodes the contentsName and contentsType out of it.
function typedDataSignStructHash(string calldata contentsDescr, bytes32 contentsHash, bytes memory domainBytes)
internal
pure
returns (bytes32 result);
typedDataSignTypehash
Compute the EIP-712 typehash of the TypedDataSign structure for a given type (and typename).
function typedDataSignTypehash(string calldata contentsName, string calldata contentsType)
internal
pure
returns (bytes32);
decodeContentsDescr
Parse the type name out of the ERC-7739 contents type description. Supports both the implicit and explicit
modes.
Following ERC-7739 specifications, a contentsName is considered invalid if it's empty or it contains
any of the following bytes , )\x00
If the contentsType is invalid, this returns an empty string. Otherwise, the return string has non-zero
length.
function decodeContentsDescr(string calldata contentsDescr)
internal
pure
returns (string calldata contentsName, string calldata contentsType);
_isForbiddenChar
function _isForbiddenChar(bytes1 char) private pure returns (bool);