Utilities
This document is better viewed at https://docs.openzeppelin.com/community-contracts/utils |
Miscellaneous contracts and libraries containing utility functions you can use to improve security, work with new data types, or safely use low-level primitives.
-
Masks
: Library to handlebytes32
masks. -
ERC7739Utils
: Utilities library that implements a defensive rehashing mechanism to prevent replayability of smart contract signatures based on ERC-7739. -
ERC7739Signer
: An abstract contract to validate signatures following the rehashing scheme fromERC7739Utils
.
Cryptography
ERC7739Signer
import "@openzeppelin/contracts/utils/cryptography/draft-ERC7739Signer.sol";
Validates signatures wrapping the message hash in a nested EIP712 type. See ERC7739Utils
.
Linking the signature to the EIP-712 domain separator is a security measure to prevent signature replay across different EIP-712 domains (e.g. a single offchain owner of multiple contracts).
This contract requires implementing the _validateSignature
function, which passes the wrapped message hash,
which may be either an typed data or a personal sign nested type.
{EIP712} uses {ShortStrings} to optimize gas costs for short strings (up to 31 characters). Consider that strings longer than that will use storage, which may limit the ability of the signer to be used within the ERC-4337 validation phase (due to ERC-7562 storage access rules). |
-
isValidSignature(hash, signature)
-
_isValidSignature(hash, signature)
-
_isValidNestedPersonalSignSignature(hash, signature)
-
_isValidNestedTypedDataSignature(hash, encodedSignature)
-
_validateSignature(hash, signature)
-
_domainSeparatorV4()
-
_hashTypedDataV4(structHash)
-
eip712Domain()
-
_EIP712Name()
-
_EIP712Version()
-
EIP712DomainChanged()
isValidSignature(bytes32 hash, bytes signature) → bytes4 result
public
Attempts validating the signature in a nested EIP-712 type.
A nested EIP-712 type might be presented in 2 different ways:
-
As a nested EIP-712 typed data
-
As a personal signature (an EIP-712 mimic of the
eth_personalSign
for a smart contract)
_isValidSignature(bytes32 hash, bytes signature) → bool
internal
Internal version of isValidSignature
that returns a boolean.
_isValidNestedPersonalSignSignature(bytes32 hash, bytes signature) → bool
internal
Nested personal signature verification.
_isValidNestedTypedDataSignature(bytes32 hash, bytes encodedSignature) → bool
internal
Nested EIP-712 typed data verification.
_validateSignature(bytes32 hash, bytes signature) → bool
internal
Signature validation algorithm.
Implementing a signature validation algorithm is a security-sensitive operation as it involves cryptographic verification. It is important to review and test thoroughly before deployment. Consider using one of the signature verification libraries ({ECDSA}, {P256} or {RSA}). |
ERC7739Utils
import "@openzeppelin/contracts/utils/cryptography/draft-ERC7739Utils.sol";
Utilities to process 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 application’s {EIP712-_domainSeparatorV4} 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 {toNestedTypedDataHash}.
-
As a smart contract validating a raw message signature. See {toNestedPersonalSignHash}.
A provider for a smart contract wallet would need to return this signature as the
result of a call to personal_sign or eth_signTypedData , and this may be unsupported by
API clients that expect a return value of 129 bytes, or specifically the r,s,v parameters
of an {ECDSA} signature, as is for example specified for {EIP712}.
|
-
encodeTypedDataSig(signature, appSeparator, contentsHash, contentsDescr)
-
decodeTypedDataSig(encodedSignature)
-
personalSignStructHash(contents)
-
typedDataSignStructHash(contentsTypeName, contentsType, contentsHash, domainBytes)
-
typedDataSignStructHash(contentsDescr, contentsHash, domainBytes)
-
typedDataSignTypehash(contentsTypeName, contentsType)
-
decodeContentsDescr(contentsDescr)
-
InvalidContentsType()
encodeTypedDataSig(bytes signature, bytes32 appSeparator, bytes32 contentsHash, string contentsDescr) → bytes
internal
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.
decodeTypedDataSig(bytes encodedSignature) → bytes signature, bytes32 appSeparator, bytes32 contentsHash, string contentsDescr
internal
Parses a nested signature into its components.
Constructed as follows:
signature ‖ DOMAIN_SEPARATOR ‖ contentsHash ‖ contentsDescr ‖ uint16(contentsDescr.length)
-
signature
is the original signature for the nested struct hash that includes the "contents" hash -
DOMAIN_SEPARATOR
is the EIP-712 {EIP712-_domainSeparatorV4} of the smart contract verifying the signature -
contentsHash
is the hash of the underlying data structure or message -
contentsDescr
is a descriptor of the "contents" part of the the EIP-712 type of the nested signature
personalSignStructHash(bytes32 contents) → bytes32
internal
Nests an ERC-191
digest into a PersonalSign
EIP-712 struct, and return 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.
typedDataSignStructHash(string contentsTypeName, string contentsType, bytes32 contentsHash, bytes domainBytes) → bytes32 result
internal
Nests an EIP-712
hash (contents
) into a TypedDataSign
EIP-712 struct, and return the corresponding
struct hash. This struct hash must be combined with a domain separator, using {MessageHashUtils-toTypedDataHash}
before being verified/recovered.
typedDataSignStructHash(string contentsDescr, bytes32 contentsHash, bytes domainBytes) → bytes32 result
internal
Variant of {typedDataSignStructHash-string-string-bytes32-string-bytes} that takes a content descriptor
and decodes the contentsTypeName
and contentsType
out of it.
typedDataSignTypehash(string contentsTypeName, string contentsType) → bytes32
internal
Compute the EIP-712 typehash of the TypedDataSign
structure for a given type (and typename).
decodeContentsDescr(string contentsDescr) → string contentsTypeName, string contentsType
internal
Parse the type name out of the ERC-7739 contents type description. Supports both the implicit and explicit modes.
Following ERC-7739 specifications, a contentsTypeName
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.
Libraries
Masks
import "@openzeppelin/contracts/utils/Masks.sol";
Library for handling bit masks
-
toMask(group)
-
toMask(groups)
-
get(self, group)
-
isEmpty(self)
-
complement(m1)
-
union(m1, m2)
-
intersection(m1, m2)
-
difference(m1, m2)
-
symmetric_difference(m1, m2)
toMask(uint8[] groups) → Masks.Mask
internal
Returns a new mask with the bits at groups
indices set to 1.
union(Masks.Mask m1, Masks.Mask m2) → Masks.Mask
internal
Perform a bitwise OR operation on two masks
intersection(Masks.Mask m1, Masks.Mask m2) → Masks.Mask
internal
Perform a bitwise AND operation on two masks