EIP712x
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);