Gas Optimizations for the Rest of Us
The basics of optimizing Solidity contracts, explained for regular coders.Writing smart contracts is hard. Not only do you get a single chance to write bug-free code, but depending on exactly how you write, it’ll cost your users more or less to interact with it. When you compile a smart contract, every line of Solidity gets converted into a series of operations (called opcodes), which have a set gas cost. Your goal is to write your program using as little opcodes as possible (or replace the m...
Decentralized Comments for Mirror
You can now comment on my Mirror entries! Here’s how I implemented it in a decentralized way.For a while now I’ve been maintaining a custom Mirror client. This allows me to use a custom domain (m1guelpf.blog instead of miguel.mirror.xyz), provide an RSS feed and retain some control over the design. So, when I came across The Convo Space, a “conversation protocol” built on top of IPFS & Libp2p, I decided to try my hand at building a decentralized commenting system for the client.Follow the Con...
How to Learn (Crypto)
Outlining my approach to quickly learning new subjects, and how you too can become a crypto expert in less than you think.In the past few months, I went from knowing almost nothing about crypto to minting NFTs, launching my own token, and getting a job at a crypto startup (TBA). While part of this was definitely being in the right place at the right time, the rest is most likely thanks to a learning strategy I’ve developed over the years, and that helped me structure my dive into the crypto w...
<100 subscribers
Gas Optimizations for the Rest of Us
The basics of optimizing Solidity contracts, explained for regular coders.Writing smart contracts is hard. Not only do you get a single chance to write bug-free code, but depending on exactly how you write, it’ll cost your users more or less to interact with it. When you compile a smart contract, every line of Solidity gets converted into a series of operations (called opcodes), which have a set gas cost. Your goal is to write your program using as little opcodes as possible (or replace the m...
Decentralized Comments for Mirror
You can now comment on my Mirror entries! Here’s how I implemented it in a decentralized way.For a while now I’ve been maintaining a custom Mirror client. This allows me to use a custom domain (m1guelpf.blog instead of miguel.mirror.xyz), provide an RSS feed and retain some control over the design. So, when I came across The Convo Space, a “conversation protocol” built on top of IPFS & Libp2p, I decided to try my hand at building a decentralized commenting system for the client.Follow the Con...
How to Learn (Crypto)
Outlining my approach to quickly learning new subjects, and how you too can become a crypto expert in less than you think.In the past few months, I went from knowing almost nothing about crypto to minting NFTs, launching my own token, and getting a job at a crypto startup (TBA). While part of this was definitely being in the right place at the right time, the rest is most likely thanks to a learning strategy I’ve developed over the years, and that helped me structure my dive into the crypto w...
Share Dialog
Share Dialog

I spent way too much time figuring out how to generate and validate typed data signatures so you don't have to.
For a project I’m working on, I need users to sign some data with their wallet. Normally, I’d just use personal signatures, but in this case, the data has a specific format, and I wanted to get the wallet signature prompt looking a little bit nicer than usual.
When signing some data with an Ethereum wallet, there are multiple signature types you can choose from. You can use the “regular” one, which will sign any string (this is what’s used to sign transactions); you can use personal signatures, which add a prefix to the signed message; or you can use typed data signatures, which allow you to define a format for the message the user will sign (and display it nicely on the signature prompt).
For this project, I decided to go with typed data signatures (or EIP-712 signatures). To start, you need to define your types (the structure the message will be using) and your domain (some information about your app).
// Let's assume we're signing an email message
const message = {
from: {
name: 'Miguel Piedrafita',
wallet: '0xE340b00B6B622C136fFA5CFf130eC8edCdDCb39D'
},
to: {
name: 'Alex Masmej',
wallet: '0xD3e9D60e4E4De615124D5239219F32946d10151D'
},
contents: 'We need more NFTs.'
};
// Our domain will include details about our app
const domain = {
name: 'Ether Mail',
version: '1',
};
// Here we define the different types our message uses
const types = {
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallet', type: 'address' }
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person' },
{ name: 'contents', type: 'string' }
]
};
Once we have our domain and types, we can use the ethers.js library to get our signature.
import { ethers } from 'ethers'
const web3 = new ethers.providers.Web3Provider(provider)
const signature = await web3.getSigner._signTypedData(
domain, types, message,
)
Now we just need a way of verifying the signature in our server. For this, we’ll need the signature we just generated and the wallet address of the signer, as well as our domain and types from the last step.
import { verifyTypedData } from 'ethers/lib/utils'
export const verifySignature = (signature, message, address): boolean => {
return verifyTypedData(
domain, types, message, signature,
).toLowerCase() === address.toLowerCase()
}
This took me quite a while to figure out (+2h 😅), so I thought I’d write it down for the next person that decides to go down this rabbit hole. Hopefully, it’ll help!

I spent way too much time figuring out how to generate and validate typed data signatures so you don't have to.
For a project I’m working on, I need users to sign some data with their wallet. Normally, I’d just use personal signatures, but in this case, the data has a specific format, and I wanted to get the wallet signature prompt looking a little bit nicer than usual.
When signing some data with an Ethereum wallet, there are multiple signature types you can choose from. You can use the “regular” one, which will sign any string (this is what’s used to sign transactions); you can use personal signatures, which add a prefix to the signed message; or you can use typed data signatures, which allow you to define a format for the message the user will sign (and display it nicely on the signature prompt).
For this project, I decided to go with typed data signatures (or EIP-712 signatures). To start, you need to define your types (the structure the message will be using) and your domain (some information about your app).
// Let's assume we're signing an email message
const message = {
from: {
name: 'Miguel Piedrafita',
wallet: '0xE340b00B6B622C136fFA5CFf130eC8edCdDCb39D'
},
to: {
name: 'Alex Masmej',
wallet: '0xD3e9D60e4E4De615124D5239219F32946d10151D'
},
contents: 'We need more NFTs.'
};
// Our domain will include details about our app
const domain = {
name: 'Ether Mail',
version: '1',
};
// Here we define the different types our message uses
const types = {
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallet', type: 'address' }
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person' },
{ name: 'contents', type: 'string' }
]
};
Once we have our domain and types, we can use the ethers.js library to get our signature.
import { ethers } from 'ethers'
const web3 = new ethers.providers.Web3Provider(provider)
const signature = await web3.getSigner._signTypedData(
domain, types, message,
)
Now we just need a way of verifying the signature in our server. For this, we’ll need the signature we just generated and the wallet address of the signer, as well as our domain and types from the last step.
import { verifyTypedData } from 'ethers/lib/utils'
export const verifySignature = (signature, message, address): boolean => {
return verifyTypedData(
domain, types, message, signature,
).toLowerCase() === address.toLowerCase()
}
This took me quite a while to figure out (+2h 😅), so I thought I’d write it down for the next person that decides to go down this rabbit hole. Hopefully, it’ll help!
No comments yet