EIP712, a full-stack example

Apurba Pokharel
Coinmonks
5 min readAug 1, 2021

--

I was working on a project that required the use of EIP712. There are many articles and examples in GitHub that explain and show how to use the EIP712, but I had a lot of trouble understanding how it works as a whole and how the code in the front end and smart contracts are related. This is an example(not an explanation) of EIP712. For explanations and other code examples see the links section below.

Prerequisite and the version I used

  1. Solidity basic knowledge
  2. npm 7.19.1
  3. node 16.2.0
  4. Metamask 9.8.4
  5. truffle 5.4.0

EIP-712

EIP-712 is a more advanced and secure method of signing a transaction. Using this standard not only can a transaction be signed and that signature can be verified but data can be passed into the smart contract along with a signature and the signature can be verified against that data to know if the signer is the one who actually sent the data to be invoked in the transaction.

The implementation of EIP-712 can be seen in the Uniswap V2 Periphery contract to remove liquidity with a permit which ends up calling the method in Uniswap V2 Core to get this done.
The signature from the front end is passed to the method in the Periphery and the signature is used to approve the Router contract on behalf of the user using the method in Core.

Example coding

Our example will use the EIP-721 proposal to sign a transaction with data (address, value of storedData and deadline) that are used to change value of a variable in a contract.

If the signature and hash gives the address of the signer and deadline is not exceeded then the value of storedData is changed.

A useless example but still understanding this will ensure you can use this standard in other places. A proper use of EIP-712 is to create a ERC20-permit as done by the uniswap team.

Step 1

Go ahead and clone the truffle’s react box.

We will simply tweak and add code as needed in this repo to get the EIP 712 working.

Step 2

The data is the most crucial part of EIP 712. These data to be signed must conform to a predefined format. It must have an EIP712Domain and the data to be signed (set in our example). The combination of both of these will be signed and sent over to the smart contract for verification.

Every data to be signed under the EIP-712 must have a EIP712Domain and another data. The structure of both of these can be anything but must be same on both the JS code and the SC code.

The structure of EIP712Domain is a well accepted standard while using the proposal.

EIP-721 Data standard

The EIP712Domain has parameters that specify on which network and which particular contract will be used to verify the signature. Another contract with the same code will be unable to verify the signature.

Step 3

Let us add a button that when clicked will bring up the metamask popup to sign our data using the eth_signTypedData_v3 method.

The code to do this can be seen here.

Step 4

Once the data as defined above has been signed using the eth_signTypedData_v3 method we get the signature and split the signature into its r,s, and v components and send it over to the smart contract which will then use ercrecover on these params and the data hash to recover the public key of the signer.

Splitting the signature

Step 5

Writing the smart contract.

Just like the JS code where we have defined the data that contains the EIPdomain and the data to sign, the smart contract will also need two variable that represent the hashed data of each EIPdomain and our data(set data) in this case.

Using ercrecover

In the UI side we are signing our data and sending the r,s, and v over to the smart contract.

The code above is doing two things, first it is hashing the datas and generating their hashes. Next, it is using hash of this data (named hash in the SC)and the signature to generate the public key of the signer using the ercrecover method.

Both keccak hash of the data shown above should be similar to the data structure that is defined in out JS code. If these are different then the address of the signer cannot be reccovered.

Structure of our signed data

Step 6

Add the mnemonics from infura to the truffle-config.js file(line 3) and also specify the address of the deployer(line 18). The example above uses rinkeby testnet but anytest can be used and see truffle documentation to deploy to other testnets.

Then deploy the contract. After deploying copy the address of the simplestorage and replace it with the address on line 76 in app.js under verifyingContract. By default it should be 0x803B558Fd23967F9d37BaFe2764329327f45e89E which is the address where my SimpleStorage.sol contract is deloyed.

Deployment snippet

Step 7

Go to the client directory and run npm run start to start the react app.

Press the‘ Press to sign’ button and then sign the signature request on the metamask popup. Next, confirm the transaction to set the value on the smart contract.

After the transaction is completed refresh webapp to see changes reflected.

--

--

Apurba Pokharel
Coinmonks

I work with decentralized stuffs. I play around with algorithms, data structure, compilers, though topics that makes me want to bang my head against a wall.