WTF Ethers: 26. EIP712 Signature Script
I've been revisiting ethers.js
recently to refresh my understanding of the details and to write a simple tutorial called "WTF Ethers" for beginners.
Twitter: @0xAA_Science
Community: Website wtf.academy | WTF Solidity | discord | WeChat Group Application
All the code and tutorials are open-sourced on GitHub: github.com/WTFAcademy/WTF-Ethers
In this tutorial, we will introduce how to use ethers.js
to write an EIP712 signature script. Please refer to WTF Solidity 52: EIP712 for details on EIP712 contract.
EIP712
EIP712 Typed Data Signatures provides a more advanced and secure method for signatures. When a Dapp supporting EIP712 requests a signature, the wallet will display the original data of the signature message, allowing the user to verify the message data before signing.
EIP712 Signature Script
In this section, we will write a script to sign ERP712 signature.
Create
provider
andwallet
objects. In this example, we will use the private key of the Remix test wallet.// Connect to the Ethereum network using Alchemy's RPC node
// For instructions on setting up Alchemy API, please refer to https://github.com/AmazingAng/WTFSolidity/blob/main/Topics/Tools/TOOL04_Alchemy/readme.md
const ALCHEMY_GOERLI_URL = 'https://eth-goerli.alchemyapi.io/v2/GlaeWuylnNM3uuOo-SAwJxuwTdqHaY5l';
const provider = new ethers.JsonRpcProvider(ALCHEMY_GOERLI_URL);
// Create a wallet object using the private key and provider
const privateKey = '0x503f38a9c967ed597e47fe25643985f032b072db8075426a92110f82df48dfcb'
const wallet = new ethers.Wallet(privateKey, provider)Create the EIP712 Domain, which includes the contract's
name
,version
(usually set to "1"),chainId
, andverifyingContract
(the address of the contract that verifies the signature).// Create the EIP712 Domain
let contractName = "EIP712Storage"
let version = "1"
let chainId = "1"
let contractAddress = "0xf8e81D47203A594245E36C48e151709F0C19fBe8"
const domain = {
name: contractName,
version: version,
chainId: chainId,
verifyingContract: contractAddress,
};Create the typed data for the signature message, where
types
declares the types, andmessage
contains the data.// Create typed data, Storage
let spender = "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4"
let number = "100"
const types = {
Storage: [
{ name: "spender", type: "address" },
{ name: "number", type: "uint256" },
],
};
const message = {
spender: spender,
number: number,
};Call the
signTypedData()
signing method of the wallet object with the previously createddomain
,types
, andmessage
variables:// EIP712 signature
const signature = await wallet.signTypedData(domain, types, message);
console.log("Signature:", signature);
// Signature: 0xdca07f0c1dc70a4f9746a7b4be145c3bb8c8503368e94e3523ea2e8da6eba7b61f260887524f015c82dd77ebd3c8938831c60836f905098bf71b3e6a4a09b7311bYou can use the
verifyTypedData()
method to recover the signer address from the signature and message, and verify the validity of the signature. Typically, this step is executed in a smart contract.// Verify the EIP712 signature and recover the signer address from the signature and message
let eip712Signer = ethers.verifyTypedData(domain, types, message, signature)
console.log("EIP712 Signer: ", eip712Signer)
// EIP712 Signer: 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
Summary
In this tutorial, we have introduced how to write an EIP712 signature script using ethers.js
.