EIP 1271: Standard Signature Validation Method for Contracts
Author | Francisco Giordano, Matt Condon, Philippe Castonguay, Amir Bandeali, Jorge Izquierdo, Bertrand Masius |
---|---|
Discussions-To | https://github.com/ethereum/EIPs/issues/1271 |
Status | Draft |
Type | Standards Track |
Category | ERC |
Created | 2018-07-25 |
Simple Summary
Many blockchain based applications allow users to sign off-chain messages instead of directly requesting users to do an on-chain transaction. This is the case for decentralized exchanges with off-chain orderbooks like 0x and etherdelta. These applications usually assume that the message will be signed by the same address that owns the assets. However, one can hold assets directly in their regular account (controlled by a private key) or in a smart contract that acts as a wallet (e.g. a multisig contract). The current design of many smart contracts prevent contract based accounts from interacting with them, since contracts do not possess private keys and therefore can not directly sign messages. The proposal here outlines a standard way for contracts to verify if a provided signature is valid when the account is a contract.
Abstract
Externally Owned Accounts (EOA) can sign messages with their associated private keys, but currently contracts cannot. This is a problem for many applications that implement signature based off-chain methods, since contracts can’t easily interact with them as they do not possess a private key. Here, we propose a standard way for any contracts to verify whether a signature on a behalf of a given contract is valid.
Motivation
In the future, it is likely that many users will hold their assets in a smart contract instead of holding them in their externally owned account directly since contracts can improve user experience significantly while providing extra security. This means that contracts using signature based functions should not assume that a given address can provide ECDSA signatures. Otherwise, identity based contracts and contracts holding assets may not be able to interact with functions requiring ECDSA signatures directly.
Here, we use the term smart account to refer to any contract that acts as an account, which can include identity based methods (e.g. ERC-725 & ERC-1078), asset ownership (e.g. Multisigs, proxy contracts) and/or executable signed messages methods (e.g. ERC-1077). This terminology is important for the reader to better distinguish a contract that acts as an account (e.g. a multisig, wallet or Gnosis Safe contract) and a contract that does not act as an account but requires signatures.
One example of an application that requires addresses to provide signatures would be decentralized exchanges with off-chain orderbook, where buy/sell orders are signed messages (see 0x and etherdelta for examples). In these applications, EOAs sign orders, signaling their desire to buy/sell a given asset and giving explicit permissions to the exchange smart contracts to conclude a trade via an ECDSA signature. When it comes to contracts however, ECDSA signature is not possible since contracts do not possess a private key. In the first version of the 0x protocol, smart contracts could not generate buy/sell orders for this very reason, as the maker
needed to both own the assets and sign the order via ECDSA method. This was revised in their protocol version 2 (see below).
Specification
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.
pragma solidity ^0.5.0;
contract ERC1271 {
// bytes4(keccak256("isValidSignature(bytes,bytes)")
bytes4 constant internal MAGICVALUE = 0x20c13b0b;
/**
* @dev Should return whether the signature provided is valid for the provided data
* @param _data Arbitrary length data signed on the behalf of address(this)
* @param _signature Signature byte array associated with _data
*
* MUST return the bytes4 magic value 0x20c13b0b when function passes.
* MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5)
* MUST allow external calls
*/
function isValidSignature(
bytes memory _data,
bytes memory _signature)
public
view
returns (bytes4 magicValue);
}
isValidSignature
can call arbitrary methods to validate a given signature, which could be context dependent (e.g. time based or state based), EOA dependant (e.g. signers authorization level within smart wallet), signature scheme Dependant (e.g. ECDSA, multisig, BLS), etc.
Rationale
Such a function is important because it allows other contracts to validate signed messages on the behalf of the smart wallet. This is necessary because not all signed messages will first pass by the smart wallet as in ERC-1077, since signatures can be requested by independent contracts. Action based signed messages do not require this method for external contracts since the action is smart wallet A -> Contract C
(e.g. owner of smart wallet A
wants to transfer tokens T
to contract C
), but when the action is in the opposite direction (Contract A -> SmartAccount
) this external function is necessary (e.g. contract A
requires smart wallet A
to transfer tokens T
when event E
is triggered).
We believe the name of the proposed function to be appropriate considering that an authorized signers providing proper signatures for a given data would see their signature as “valid” by the smart wallet. Hence, an signed action message is only valid when the signer is authorized to perform a given action on the behalf of a smart wallet.
Two arguments are provided for simplicity of separating the data from the signature, but both could be concatenated in a single byte array if community prefers this.
isValidSignature()
should not be able to modify states in order to prevent GasToken
minting or similar attack vectors. A gas limit being passed is being considered, but could prevent some interesting use cases like large multisignatures or more costly validation and cryptographic schemes.
Backwards Compatibility
This EIP is backward compatible with previous work on signature validation since this method is specific to contract based signatures and not EOA signatures.
Implementation
Existing implementations :
- The 0x project implemented this method in their protocol version 2.
- Zeppelin is in the process of implementing this method.
Copyright
Copyright and related rights waived via CC0.