EIP712x

Git Source

Authors: Ultrasound Labs (https://github.com/ultrasoundlabs), Modified from Solady (https://github.com/vectorized/solady/blob/main/src/utils/EIP712.sol), Modified from Solbase (https://github.com/Sol-DAO/solbase/blob/main/src/utils/EIP712.sol), Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol)

Modified EIP-712 contract with chainId hardcoded to 1 for multi-chain signatures.

WARNING: If you are using this for multi-chain signatures, please make sure that the payload you sign handles chainId-based replay protection internally! EIP712x removes this replay protection specifically so that payloads handle it on their end.

State Variables

_HARDCODED_CHAIN_ID

We hardcode chainId to 1 so that signatures generated for Ethereum Mainnet can be verified on other chains using this verifier contract. Why 1? - Because all EVM wallets have Ethereum Mainnet supported by default.

uint256 public constant _HARDCODED_CHAIN_ID = 1;

_DOMAIN_TYPEHASH

keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)").

bytes32 internal constant _DOMAIN_TYPEHASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;

_DOMAIN_TYPEHASH_SANS_CHAIN_ID

keccak256("EIP712Domain(string name,string version,address verifyingContract)"). This is only used in _hashTypedDataSansChainId.

bytes32 internal constant _DOMAIN_TYPEHASH_SANS_CHAIN_ID =
    0x91ab3d17e3a50a9d89e63fd30b92be7f5336b03b287bb946787a83a9d62a2766;

_DOMAIN_TYPEHASH_SANS_CHAIN_ID_AND_VERIFYING_CONTRACT

keccak256("EIP712Domain(string name,string version)"). This is only used in _hashTypedDataSansChainIdAndVerifyingContract.

bytes32 internal constant _DOMAIN_TYPEHASH_SANS_CHAIN_ID_AND_VERIFYING_CONTRACT =
    0xb03948446334eb9b2196d5eb166f69b9d49403eb4a12f36de8d3f9f3cb8e15c3;

_DOMAIN_TYPEHASH_SANS_VERIFYING_CONTRACT

keccak256("EIP712Domain(string name,string version,uint256 chainId)"). This is only used in _hashTypedDataSansVerifyingContract.

bytes32 internal constant _DOMAIN_TYPEHASH_SANS_VERIFYING_CONTRACT =
    0xc2f8787176b8ac6bf7215b4adcc1e069bf4ab82d9ab1df05a57a91d425935b6e;

_cachedThis

uint256 private immutable _cachedThis;

_cachedChainId

uint256 private immutable _cachedChainId;

_cachedNameHash

bytes32 private immutable _cachedNameHash;

_cachedVersionHash

bytes32 private immutable _cachedVersionHash;

_cachedDomainSeparator

bytes32 private immutable _cachedDomainSeparator;

Functions

constructor

Cache the hashes for cheaper runtime gas costs. In the case of upgradeable contracts (i.e. proxies), or if the chain id changes due to a hard fork, the domain separator will be seamlessly calculated on-the-fly.

constructor();

_domainNameAndVersion

*Please override this function to return the domain name and version.

function _domainNameAndVersion()
internal
pure
virtual
returns (string memory name, string memory version)
{
name = "Solady";
version = "1";
}

Note: If the returned result may change after the contract has been deployed, you must override _domainNameAndVersionMayChange() to return true.*

function _domainNameAndVersion() internal view virtual returns (string memory name, string memory version);

_domainNameAndVersionMayChange

Returns if _domainNameAndVersion() may change after the contract has been deployed (i.e. after the constructor). Default: false.

function _domainNameAndVersionMayChange() internal pure virtual returns (bool result);

_domainSeparator

Returns the EIP-712 domain separator.

function _domainSeparator() internal view virtual returns (bytes32 separator);

_hashTypedData

*Returns the hash of the fully encoded EIP-712 message for this domain, given structHash, as defined in https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct. The hash can be used together with ECDSA-recover to obtain the signer of a message:

bytes32 digest = _hashTypedData(keccak256(abi.encode(
keccak256("Mail(address to,string contents)"),
mailTo,
keccak256(bytes(mailContents))
)));
address signer = ECDSA.recover(digest, signature);
```*


```solidity
function _hashTypedData(bytes32 structHash) internal view virtual returns (bytes32 digest);

_hashTypedDataSansChainId

Variant of _hashTypedData that excludes the chain ID. Included for the niche use case of cross-chain workflows.

function _hashTypedDataSansChainId(bytes32 structHash) internal view virtual returns (bytes32 digest);

_hashTypedDataSansChainIdAndVerifyingContract

Variant of _hashTypedData that excludes the chain ID and verifying contract. Included for the niche use case of cross-chain and multi-verifier workflows.

function _hashTypedDataSansChainIdAndVerifyingContract(bytes32 structHash)
    internal
    view
    virtual
    returns (bytes32 digest);

_hashTypedDataSansVerifyingContract

Variant of _hashTypedData that excludes the chain ID and verifying contract. Included for the niche use case of multi-verifier workflows.

function _hashTypedDataSansVerifyingContract(bytes32 structHash) internal view virtual returns (bytes32 digest);

eip712Domain

See: https://eips.ethereum.org/EIPS/eip-5267

function eip712Domain()
    public
    view
    virtual
    returns (
        bytes1 fields,
        string memory name,
        string memory version,
        uint256 chainId,
        address verifyingContract,
        bytes32 salt,
        uint256[] memory extensions
    );

_buildDomainSeparator

Returns the EIP-712 domain separator.

function _buildDomainSeparator() private view returns (bytes32 separator);

_cachedDomainSeparatorInvalidated

Returns if the cached domain separator has been invalidated.

function _cachedDomainSeparatorInvalidated() private view returns (bool result);