Signature Validation Method for NFTs

A way to verify signatures when the signing entity is an ERC-721 or ERC-1155 NFT
FinalStandards Track: ERC
Created: 2022-11-29
Requires: EIP-165, EIP-721, EIP-1155, EIP-1271, EIP-5750
Jack Boyuan Xu (@boyuanx)
DiscussionsOriginal linkEdit
1 min read

ERC-6066 proposes a standard method for validating signatures made by Non-Fungible Tokens (NFTs) such as ERC-721 and ERC-1155. The motivation behind this proposal is to create a more tangible link between NFTs, digital art, owners, and artists. The proposal suggests that a concise standard for art will make it easier for artists to maintain a connection with the Ethereum blockchain and their fans who purchase their tokens. The proposal also aims to designate an original NFT and printed editions with signatures in a trustless manner. The proposal does not include a signature generation standard as it would restrict flexibility, but instead references Gnosis Safe's contract signing approach. The proposal is compatible with ERC-721 compliant contracts and is consistent with Gnosis Safe's contract signature implementation. The revokable nature of contract-based signatures should be taken into consideration by developers and users. Overall, ERC-6066 aims to provide a standard way for anyone to validate whether a signature made by an NFT is valid, which will aid the community in discovering alternative uses for NFTs beyond artwork.

Anyone may contribute to propose contents.
Go propose


While Externally Owned Accounts can validate signed messages with ecrecover() and smart contracts can validate signatures using specifications outlined in ERC-1271, currently there is no standard method to create or validate signatures made by NFTs. We propose a standard way for anyone to validate whether a signature made by an NFT is valid. This is possible via a modified signature validation function originally found in ERC-1271: isValidSignature(tokenId, hash, data).


With billions of ETH in trading volume, the Non-Fungible Token standard has exploded into tremendous popularity in recent years. Despite the far-reaching implications of having unique tokenized items on-chain, NFTs have mainly been used to represent artwork in the form of avatars or profile pictures. While this is certainly not a trivial use case for the ERC-721 & ERC-1155 token standards, we reckon more can be done to aid the community in discovering alternative uses for NFTs.

One of the alternative use cases for NFTs is using them to represent offices in an organization. In this case, tying signatures to transferrable NFTs instead of EOAs or smart contracts becomes crucial. Suppose there exists a DAO that utilizes NFTs as badges that represent certain administrative offices (i.e., CEO, COO, CFO, etc.) with a quarterly democratic election that potentially replaces those who currently occupy said offices. If the sitting COO has previously signed agreements or authorized certain actions, their past signatures would stay with the EOA who used to be the COO instead of the COO's office itself once they are replaced with another EOA as the new COO-elect. Although a multisig wallet for the entire DAO is one way to mitigate this problem, often it is helpful to generate signatures on a more intricate level so detailed separation of responsibilities are established and maintained. It is also feasible to appoint a smart contract instead of an EOA as the COO, but the complexities this solution brings are unnecessary. If a DAO uses ENS to establish their organizational hierarchy, this proposal would allow wrapped ENS subdomains (which are NFTs) to generate signatures.


The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.

pragma solidity ^0.8.0;

interface IERC6066 {
     * @dev MUST return if the signature provided is valid for the provided tokenId and hash
     * @param tokenId   Token ID of the signing NFT
     * @param hash      Hash of the data to be signed
     * @param data      OPTIONAL arbitrary data that may aid verification
     * MUST return the bytes4 magic value 0x12edb34f 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(
        uint256 tokenId,
        bytes32 hash,
        bytes calldata data
    ) external view returns (bytes4 magicValue);

isValidSignature can call arbitrary methods to validate a given signature.

This function MAY be implemented by ERC-721 or ERC-1155 compliant contracts that desire to enable its token holders to sign messages using their NFTs. Compliant callers wanting to support contract signatures MUST call this method if the signer is the holder of an NFT (ERC-721 or ERC-1155).


We have purposefully decided to not include a signature generation standard in this proposal as it would restrict flexibility of such mechanism, just as ERC-1271 does not enforce a signing standard for smart contracts. We also decided to reference Gnosis Safe's contract signing approach as it is both simplistic and proven to be adequate. The bytes calldata data parameter is considered optional if extra data is needed for signature verification, also conforming this EIP to ERC-5750 for future-proofing purposes.

Backwards Compatibility

This EIP is incompatible with previous work on signature validation as it does not validate any cryptographically generated signatures. Instead, signature is merely a boolean flag indicating consent. This is consistent with Gnosis Safe's contract signature implementation.

Reference Implementation

Example implementation of an ERC-721 compliant contract that conforms to ERC-6066 with a custom signing function:

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "./interfaces/IERC6066.sol";

contract ERC6066Reference is ERC721, IERC6066 {
    // type(IERC6066).interfaceId
    bytes4 public constant MAGICVALUE = 0x12edb34f;
    bytes4 public constant BADVALUE = 0xffffffff;

    mapping(uint256 => mapping(bytes32 => bool)) internal _signatures;

    error ENotTokenOwner();

     * @dev Checks if the sender owns NFT with ID tokenId
     * @param tokenId   Token ID of the signing NFT
    modifier onlyTokenOwner(uint256 tokenId) {
        if (ownerOf(tokenId) != _msgSender()) revert ENotTokenOwner();

    constructor(string memory name_, string memory symbol_)
        ERC721(name_, symbol_)

     * @dev SHOULD sign the provided hash with NFT of tokenId given sender owns said NFT
     * @param tokenId   Token ID of the signing NFT
     * @param hash      Hash of the data to be signed
    function sign(uint256 tokenId, bytes32 hash)
        _signatures[tokenId][hash] = true;

     * @dev MUST return if the signature provided is valid for the provided tokenId, hash, and optionally data
    function isValidSignature(uint256 tokenId, bytes32 hash, bytes calldata data)
        returns (bytes4 magicValue)
        // The data parameter is unused in this example
        return _signatures[tokenId][hash] ? MAGICVALUE : BADVALUE;

     * @dev ERC-165 support
    function supportsInterface(
        bytes4 interfaceId
    ) public view virtual override returns (bool) {
            interfaceId == type(IERC6066).interfaceId ||

Security Considerations

The revokable nature of contract-based signatures carries over to this EIP. Developers and users alike should take it into consideration.

Copyright and related rights waived via CC0.

Further reading
Anyone may contribute to propose contents.
Go propose
Adopted by projects
Anyone may contribute to propose contents.
Go propose

Not miss a beat of EIPs' update?

Subscribe EIPs Fun to receive the latest updates of EIPs Good for Buidlers to follow up.

View all
Serve Ethereum Builders, Scale the Community.
Supported by