Table of contents

EIP-1271: Signature Verification for Smart Contract Wallets

https://www.dynamic.xyz/blog/eip-1271
EIP-1271: Signature Verification for Smart Contract Wallets
EIP-1271: Signature Verification for Smart Contract Wallets
Download

Introduction

The rise of ERC-4337 and the increasing adoption of smart contract wallets, such as Argent, Sequence, and Safe, are reshaping the wallet landscape. These wallets offer greater flexibility, customizable logic, multi-signature access, and social recovery mechanisms. As smart contract wallets become more popular, there is a growing need for a tailored approach to signature authentication that accommodates their unique requirements. Ethereum Improvement Proposal 1271 (EIP-1271) is a standard designed to address this need, enabling efficient and secure signature authentication for smart contract wallets.

In this blog post, we’ll cover why EIP-1271 is needed to support smart contract wallet signature verification, as well as show an example of how EIP-1271 can be implemented in your dApp using ethers.

Did You Know: Externally Owned Accounts (EOA) - Ethereum features two types of accounts - Externally Owned Accounts (EOAs) and Contract Accounts. While Contract Accounts are managed by smart contracts, enabling them to execute code and store data on the Ethereum blockchain, EOAs are controlled by private keys and do not contain any associated code. EOAs can interact with other accounts through signed transactions and are the most frequently used account type in Ethereum wallets.

EIP-1271: A Tailored Approach to Signature Authentication

Traditional signature authentication on the Ethereum blockchain has relied on the ECDSA (Elliptic Curve Digital Signature Algorithm) signatures. In Externally Owned Accounts (EOAs), the private key signs the transactions, whereas in smart contract wallets, the contract itself signs the transactions. This conventional method, however, has limitations when applied to smart contract wallets, as it only supports EOAs.

EIP-1271 emerges as a response to these limitations, introducing a new way of verifying signatures specifically tailored for smart contract wallets. Instead of solely relying on ECDSA, EIP-1271 enables smart contract wallets to define their own custom logic for signature validation. This flexibility caters to various use cases, such as multi-signature wallets and social recovery wallets, accommodating the diverse requirements of DeFi applications.

Integration with SIWE: Sign in with Ethereum

EIP-1271's importance is further highlighted when integrated with the Sign in with Ethereum (SIWE) standard, developed by Spruce and Ethereum Name Service (ENS). SIWE simplifies and secures user access to decentralized applications (dApps) by using their Ethereum wallets as a form of identity. The integration of EIP-1271 with SIWE allows smart contract wallets to validate signatures directly, improving the security and user experience of DeFi applications.

Further Complexities: Asynchronous Signing in Multi-Sig Wallets

The EIP-1271 solution becomes particularly relevant when considering the complexities of multi-signature wallets like Safe. In these wallets, the signing process can be asynchronous, requiring multiple signatures from various parties before a transaction can be executed. EIP-1271 provides a standardized method for validating signatures in smart contract wallets, streamlining the signing process regardless of the wallet's specific signing mechanism.

Safe further introduces a different approach to signing messages compared to EOAs. Since they do not have a private key to sign messages directly, the process becomes asynchronous. Instead of directly signing the message, the multi-sig owners of a Gnosis Safe must execute an on-chain transaction that marks the message as "signed."

In this scenario, the frontend of a dApp needs to listen for the on-chain transaction executed by the Gnosis Safe contract. Once detected, the frontend can proceed with the knowledge that the message has been signed and is ready for validation. This asynchronous signing process adds an extra layer of complexity compared to traditional, off-chain signing methods used by EOAs or by standard smart contract wallets.

As an alternative to the on-chain message signing, Spruce, for example, built a delegate manager for Safe. This manager assigns a single owner who can log in on behalf of an organization, simplifying the workflow for DAO logins and addressing the complexities associated with asynchronous signing in multi-sig wallets.

Validating Regular Signatures vs. EIP-1271

To understand the difference between validating regular signatures and those using EIP-1271, let's examine the coding differences between the two approaches.

Validating Regular Signatures with ecrecover

In a typical Ethereum application, when a user signs a message or a transaction using their private key, the signature is validated using the ecrecover function. This function takes the message hash, signature, and recovery ID as inputs and returns the signer's address.

Here's a simple example of validating a regular signature using Ethers:

const signerAddress = ethers.utils.verifyMessage(message, signature);

Validating Signatures with EIP-1271

With EIP-1271, the signature validation process is different. Instead of using ecrecover, the smart contract wallet itself implements a function called isValidSignature. This function takes the message hash and signature as inputs and returns a specific magic value if the signature is valid.

Here's a simple example of validating a signature:

const IS_VALID_SIGNATURE_ABI = [
  'function isValidSignature(bytes32 _message, bytes _signature) public view returns (bytes4)',
];

const contract = new Contract(
  accountPublicAddress,
  IS_VALID_SIGNATURE_ABI
);

const EIP1271_MAGIC_VALUE = '0x1626ba7e'; 
const result = await contract.isValidSignature(message, signedMessage);

if (result === EIP1271_MAGIC_VALUE) { 
  console.log('Signature is valid'); 
} else { 
  console.log('Signature is invalid'); 
}

By implementing the isValidSignature function, EIP-1271 allows smart contract wallets to define their own custom logic for signature validation. This flexibility makes it easier to support a wide range of use cases, such as multi-signature wallets and social recovery wallets.

Detecting the Need for EIP-1271 vs. ecrecover

Now that we know the difference between validating regular signatures and smart contract signatures, we need to implement a way to determine when to use each. 

To determine whether you need to use EIP-1271 or ecrecover, you can check if the signer's address is a contract or an EOA. If it's a contract, we will assume, in this example, that it supports EIP-1271 and proceed with the isValidSignature call. If it's not a contract, you can use the traditional ecrecover method for signature validation.

Here's a coding example using ethers.js to detect whether to use EIP-1271 or ecrecover:

const ethers = require("ethers"); 
const provider = new ethers.providers.JsonRpcProvider("https://mainnet.infura.io/v3/YOUR-INFURA-KEY"); 

async function isContract(address) { 
  const code = await provider.getCode(address); 
  return code !== "0x"; 
}

async function validateSignature(signerAddress, message, signature) { 
  if (await isContract(signerAddress)) { 
    // Use EIP-1271 
    console.log("Using EIP-1271 for signature validation"); 
    // Replace with EIP-1271 validation logic 
  } else { 
    // Use ecrecover 
    console.log("Using ecrecover for signature validation");     
  }
}

In this example, we use the isContract function to check if the signer's address is a contract or an EOA by getting the code at the given address. If the code is not empty, it's a contract and we can assume it may support EIP-1271. Otherwise, we proceed with the traditional ecrecover method.

By implementing this approach, you can adapt your dApp to support both EOAs and smart contract wallets, ensuring a seamless and secure user experience for all types of Ethereum addresses.

EIP-1271 Support with Dynamic

The above is a simplified version and requires more work to productionize. With multiple moving parts and the need to constantly update things as wallets change their implementation, an alternative approach would be to use a provider that abstracts away the need to deal with EIP-1271. Enter Dynamic 😊.

Dynamic offers a convenient solution with built-in support for EIP-1271. This integration eliminates the need for developers to manually handle the implementation, allowing them to focus on creating innovative and secure dApps while Dynamic takes care of the complexities of signature authentication for smart contract wallets. Dynamic is free to start, and you can get started here.

What happens next

EIP-1271 significantly enhances signature authentication in smart contract wallets, enabling more secure and efficient processes tailored to their unique requirements. Its integration with Sign in with Ethereum (SIWE) demonstrates the crucial role EIP-1271 plays in the development of next-generation decentralized applications. By leveraging the built-in support for EIP-1271 in Dynamic, developers can stay ahead of the curve and create smart dApps that are both secure and user-friendly.

References

  1. EIP-1271: Standard Signature Validation Method for Contracts.
  2. Ethereum: Accounts.
  3. Sequence: Sign Messages with Smart Contract Wallets.
  4. ERC-4337: Account Abstraction via Entry Point Contract Specification.
  5. Spruce: Sign-In with Ethereum (SIWE).

Share this article

https://www.dynamic.xyz/blog/eip-1271
Yoni Goldberg

Yoni is the co-founder and CTO of Dynamic. Prior to Dynamic he was VP at Juul labs, AQR and Even Financial, and a tech lead at Gilt Groupe. He previously completed his thesis at Google Research, and holds B.Sc and M.Eng degrees in Computer Science from MIT.

Related articles

Dynamic takes minutes to set up

(Oh, and we also offer a free multi-chain wallet adapter)

Get started