EIP-712 enabled the signing of typed data, which is great for gasless approvals. To name a couple common use cases, EIP-2612 Permits for ERC20 tokens and gasless off-chain NFT listings and offers. Prior to EIP-712, users signed an incomprehensible array of bytes (dangerous). With EIP-712 Web3 wallets now have a formalized way to present human readable information for signature (less dangerous).
Currently though, eth_signTypedData
in a JSON RPC and web3 wallets only support the signing of a single signature at a time.
Motivation:
Consider the example of an NFT marketplace where a user wants to approve a batch of similar approvals. Listing many NFTs for sale with one signature. To create individual signed approvals for 25 items, a user would have to list their NFTs one at a time - a tedious task with a bad UX. An improved UX would be to allow a user to select 25 of their NFTs to list in a single atomic action.
Some marketplaces solve for this by using Merkle Proofs - in effect, users sign a Merkle Root where the leaves in the merkle tree contain the individual orders that can be verified by supply the user’s merkle root and the proofs of the items being purchased. This is a highly over-engineered solution with a couple of problems.
- Signing a merkle root (bytes32) is an opaque blind signature - a false merkle root could be presented by a malicious application to trick a user into signing off on listings to their own detriment.
- If an entire tree structure is signed, the data is technically readable, but verbose enough with so many levels that a user may not fully read it. Furthermore, to ecrecover the full signature, all the data must be available to reconstruct the structured data and recover the signer address. This can potentially bloat calldata.
- The use of merkle proofs can add additional gas overhead that wouldn’t be present if an array of simpler signed approvals could be provided instead of merkle root and proofs.
Proposal:
An update to web3 wallets. To support generation of multiple EIP-712 signatures with a single click to “sign”.
Currently users are presented with human readable typed data for each EIP-712 signature. Update the UI of wallets to include “pages”, where each “page” provides the details of one of the signatures in the batch. Make navigation between pages streamlined and simple. Disable the sign button until all pages have been viewed.
For security, each EIP-712 signature requested in a batch MUST be for the same domain separate and message type (no mixing of approval types, only allow batches of the same type).
After review of all signature data pages is complete, enable the “Sign” button of the wallet. The wallet MUST then use the unlocked account private key to generate and return an array of individual signatures for each requested typed data message.
Recommendation is to create a new RPC and new library functions rather than edit existing functionality. Possibly:
- eth_signTypedDataBatch
- personal_signTypedDataBatch
- web3.eth.signTypedDataBatch
- web3.eth.personal.signTypedDataBatch