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.
-
AbstractSigner
: Abstract contract for internal signature validation in smart contracts. -
ERC7739Signer
: An abstract contract to validate signatures following the rehashing scheme fromERC7739Utils
. -
ERC7739Utils
: Utilities library that implements a defensive rehashing mechanism to prevent replayability of smart contract signatures based on ERC-7739. -
SignerECDSA
,SignerP256
,SignerRSA
: Implementations of anAbstractSigner
with specific signature validation algorithms. -
Masks
: Library to handlebytes32
masks.
Cryptography
AbstractSigner
import "@openzeppelin/contracts/utils/cryptography/AbstractSigner.sol";
Abstract contract for signature validation.
Developers must implement _rawSignatureValidation
and use it as the lowest-level signature validation mechanism.
-
_rawSignatureValidation(hash, signature)
ERC7739Signer
import "@openzeppelin/contracts/utils/cryptography/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 _rawSignatureValidation
function, which passes the wrapped message hash,
which may be either an typed data or a personal sign nested type.
EIP-712 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)
-
_domainSeparatorV4()
-
_hashTypedDataV4(structHash)
-
eip712Domain()
-
_EIP712Name()
-
_EIP712Version()
-
_rawSignatureValidation(hash, signature)
-
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)
ERC7739Utils
import "@openzeppelin/contracts/utils/cryptography/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 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
.
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 EIP-712.
|
-
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.
SignerECDSA
import "@openzeppelin/contracts/utils/cryptography/SignerECDSA.sol";
Implementation of AbstractSigner
using
ECDSA signatures.
For Account
usage, an _initializeSigner
function is provided to set the signer
address.
Doing so it’s easier for a factory, whose likely to use initializable clones of this contract.
Example of usage:
contract MyAccountECDSA is Account, SignerECDSA {
constructor() EIP712("MyAccountECDSA", "1") {}
function initializeSigner(address signerAddr) public virtual initializer {
// Will revert if the signer is already initialized
_initializeSigner(signerAddr);
}
}
Avoiding to call _initializeSigner either during construction (if used standalone)
or during initialization (if used as a clone) may leave the signer either front-runnable or unusable.
|
-
_initializeSigner(signerAddr)
-
signer()
-
_rawSignatureValidation(hash, signature)
-
SignerECDSAUninitializedSigner(signer)
_initializeSigner(address signerAddr)
internal
Initializes the signer with the address of the native signer. This function can be called only once.
_rawSignatureValidation(bytes32 hash, bytes signature) → bool
internal
Signature validation algorithm.
SignerECDSAUninitializedSigner(address signer)
error
The signer
is already initialized.
SignerP256
import "@openzeppelin/contracts/utils/cryptography/SignerP256.sol";
Implementation of AbstractSigner
using
P256 signatures.
For Account
usage, an _initializeSigner
function is provided to set the signer
public key.
Doing so it’s easier for a factory, whose likely to use initializable clones of this contract.
Example of usage:
contract MyAccountP256 is Account, SignerP256 {
constructor() EIP712("MyAccountP256", "1") {}
function initializeSigner(bytes32 qx, bytes32 qy) public virtual initializer {
// Will revert if the signer is already initialized
_initializeSigner(qx, qy);
}
}
Avoiding to call _initializeSigner either during construction (if used standalone)
or during initialization (if used as a clone) may leave the signer either front-runnable or unusable.
|
-
_initializeSigner(qx, qy)
-
signer()
-
_rawSignatureValidation(hash, signature)
-
SignerP256UninitializedSigner(qx, qy)
_initializeSigner(bytes32 qx, bytes32 qy)
internal
Initializes the signer with the P256 public key. This function can be called only once.
_rawSignatureValidation(bytes32 hash, bytes signature) → bool
internal
Signature validation algorithm.
SignerP256UninitializedSigner(bytes32 qx, bytes32 qy)
error
The signer
is already initialized.
SignerRSA
import "@openzeppelin/contracts/utils/cryptography/SignerRSA.sol";
Implementation of AbstractSigner
using
RSA signatures.
For Account
usage, an _initializeSigner
function is provided to set the signer
public key.
Doing so it’s easier for a factory, whose likely to use initializable clones of this contract.
Example of usage:
contract MyAccountRSA is Account, SignerRSA {
constructor() EIP712("MyAccountRSA", "1") {}
function initializeSigner(bytes memory e, bytes memory n) external {
// Will revert if the signer is already initialized
_initializeSigner(e, n);
}
}
Avoiding to call _initializeSigner either during construction (if used standalone)
or during initialization (if used as a clone) may leave the signer either front-runnable or unusable.
|
-
_initializeSigner(e, n)
-
signer()
-
_rawSignatureValidation(hash, signature)
-
SignerRSAUninitializedSigner(e, n)
_initializeSigner(bytes e, bytes n)
internal
Initializes the signer with the RSA public key. This function can be called only once.
_rawSignatureValidation(bytes32 hash, bytes signature) → bool
internal
Signature validation algorithm.
SignerRSAUninitializedSigner(bytes e, bytes n)
error
The signer
is already initialized.
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)
-
symmetricDifference(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