Skip to content

Commit

Permalink
Add EIP: Identity aggregated NFT, self soveriegn and composible ident…
Browse files Browse the repository at this point in the history
…ity aggregation in NFTs (SBTs included)
  • Loading branch information
xuxinlai2002 committed Jun 25, 2023
1 parent c58533b commit 3ee8f74
Show file tree
Hide file tree
Showing 10 changed files with 654 additions and 0 deletions.
176 changes: 176 additions & 0 deletions EIPS/eip-XXXX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
---
title: Identity aggregated NFT, self soveriegn and composible identity aggregation in NFTs (SBTs included)
description: The aggregation of web2 and web3 identities to NFTs (SBTs included), authorized by individuals, givies such NFTs the attributes of ownerships, relationships, role-behaviour and experiences. Individuals can also customize information segregation for privacy and data sovereignty on different NFTs. This allows for diversified, simplified authentication (e.g., KYC), accelerated on-chain identity adoption and interoperability, and extends business scenarios.
author: Chloe Gu (@xy_gu), Navid X. ([email protected]), Victor Yu ([email protected]), Archer H.

Check failure on line 4 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

authors in the preamble must match the expected format

error[preamble-author]: authors in the preamble must match the expected format --> EIPS/eip-XXXX.md:4:8 | 4 | author: Chloe Gu (@xy_gu), Navid X. ([email protected]), Victor Yu ([email protected]), Archer H. | ^^^^^^^^^^^^^^^^^^ unrecognized author | = help: Try `Random J. User (@username) <[email protected]>` for an author with a GitHub username plus email. = help: Try `Random J. User (@username)` for an author with a GitHub username. = help: Try `Random J. User <[email protected]>` for an author with an email. = help: Try `Random J. User` for an author without contact information. = help: see https://ethereum.github.io/eipw/preamble-author/

Check failure on line 4 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

authors in the preamble must match the expected format

error[preamble-author]: authors in the preamble must match the expected format --> EIPS/eip-XXXX.md:4:27 | 4 | author: Chloe Gu (@xy_gu), Navid X. ([email protected]), Victor Yu ([email protected]), Archer H. | ^^^^^^^^^^^^^^^^^^^^^^^^^ unrecognized author | = help: Try `Random J. User (@username) <[email protected]>` for an author with a GitHub username plus email. = help: Try `Random J. User (@username)` for an author with a GitHub username. = help: Try `Random J. User <[email protected]>` for an author with an email. = help: Try `Random J. User` for an author without contact information.

Check failure on line 4 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

authors in the preamble must match the expected format

error[preamble-author]: authors in the preamble must match the expected format --> EIPS/eip-XXXX.md:4:8 | 4 | author: Chloe Gu (@xy_gu), Navid X. ([email protected]), Victor Yu ([email protected]), Archer H. | ^^^^^^^^^^^^^^^^^^ unrecognized author | = help: Try `Random J. User (@username) <[email protected]>` for an author with a GitHub username plus email. = help: Try `Random J. User (@username)` for an author with a GitHub username. = help: Try `Random J. User <[email protected]>` for an author with an email. = help: Try `Random J. User` for an author without contact information. = help: see https://ethereum.github.io/eipw/preamble-author/

Check failure on line 4 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

authors in the preamble must match the expected format

error[preamble-author]: authors in the preamble must match the expected format --> EIPS/eip-XXXX.md:4:27 | 4 | author: Chloe Gu (@xy_gu), Navid X. ([email protected]), Victor Yu ([email protected]), Archer H. | ^^^^^^^^^^^^^^^^^^^^^^^^^ unrecognized author | = help: Try `Random J. User (@username) <[email protected]>` for an author with a GitHub username plus email. = help: Try `Random J. User (@username)` for an author with a GitHub username. = help: Try `Random J. User <[email protected]>` for an author with an email. = help: Try `Random J. User` for an author without contact information.
discussions-to: <URL>
status: Draft
type: Standards Track
category: ERC
created: 2023-06-25
requires: 165,721,1271,6066
---


## Abstract

This standard extends ERC-721 by binding individuals' Web2 and Web3 identities to non-fungible tokens (NFTs). By binding multiple identities, aggregated and composible identity infomation can be verified, resulting in more beneficial onchain scenarios for individuals, such as self-authentication, social overlapping, commercial value generation from user targetting, etc.

Check failure on line 16 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> EIPS/eip-XXXX.md | 16 | This standard extends ERC-721 by binding individuals' Web2 and Web3 identities to non-fungible tokens (NFTs). By binding multiple identities, aggregated and composible identity infomation can be verified, resulting in more beneficial onchain scenarios for individuals, such as self-authentication, social overlapping, commercial value generation from user targetting, etc. | = info: the pattern in question: `(?i)(?:eip|erc)-[0-9]+` = help: see https://ethereum.github.io/eipw/markdown-link-first/

Check failure on line 16 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> EIPS/eip-XXXX.md | 16 | This standard extends ERC-721 by binding individuals' Web2 and Web3 identities to non-fungible tokens (NFTs). By binding multiple identities, aggregated and composible identity infomation can be verified, resulting in more beneficial onchain scenarios for individuals, such as self-authentication, social overlapping, commercial value generation from user targetting, etc. | = info: the pattern in question: `(?i)(?:eip|erc)-[0-9]+` = help: see https://ethereum.github.io/eipw/markdown-link-first/

## Motivation

One of the most interesting aspects of Web3 is the ability to bring an individuals own identity to different applications. Even more powerful is the fact that individuals truly own their accounts without relying on centralized gatekeepers, disclosing to different apps components necessary for authentication and approved by individuals.
Exisiting solutions such as ENS, although open, decentralized, and make it more convenient for Ethereum-based applications, lack of data standardization and athentication of itentity due to inherent anominity. Other solutions such as SBTs rely on centralized attestors, can not prevent data tampering, nor inscribe data into the ledger itself in a privacy enabling way. Previous work such as ERC6066 does not bind nor verify user identity data, thus unable to meet the user identity aggregation, user Kyc verification and other application scenarios related to user data sovereignty

Check failure on line 21 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

proposals must be referenced with the form `ERC-N` (not `ERCN` or `ERC N`)

error[markdown-re-erc-dash]: proposals must be referenced with the form `ERC-N` (not `ERCN` or `ERC N`) --> EIPS/eip-XXXX.md | 21 | Exisiting solutions such as ENS, although open, decentralized, and make it more convenient for Ethereum-based applications, lack of data standardization and athentication of itentity due to inherent anominity. Other solutions such as SBTs rely on centralized attestors, can not prevent data tampering, nor inscribe data into the ledger itself in a privacy enabling way. Previous work such as ERC6066 does not bind nor verify user identity data, thus unable to meet the user identity aggregation, user Kyc verification and other application scenarios related to user data sovereignty | = info: the pattern in question: `(?i)erc[\s]*[0-9]+` = help: see https://ethereum.github.io/eipw/markdown-re-erc-dash/

Check failure on line 21 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

proposals must be referenced with the form `ERC-N` (not `ERCN` or `ERC N`)

error[markdown-re-erc-dash]: proposals must be referenced with the form `ERC-N` (not `ERCN` or `ERC N`) --> EIPS/eip-XXXX.md | 21 | Exisiting solutions such as ENS, although open, decentralized, and make it more convenient for Ethereum-based applications, lack of data standardization and athentication of itentity due to inherent anominity. Other solutions such as SBTs rely on centralized attestors, can not prevent data tampering, nor inscribe data into the ledger itself in a privacy enabling way. Previous work such as ERC6066 does not bind nor verify user identity data, thus unable to meet the user identity aggregation, user Kyc verification and other application scenarios related to user data sovereignty | = info: the pattern in question: `(?i)erc[\s]*[0-9]+` = help: see https://ethereum.github.io/eipw/markdown-re-erc-dash/
The proposed ERC-XXXX pushes the boundaries of solving identity problems with Identity Aggregated NFT, i.e., the individual-authenticated aggregation of web2 and web3 identities to NFTs (SBTs included).


## Specification

The keywords “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.

### Every ERC-XXXX compliant contract must implement the Interface
```typescript
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.15;

interface IERCXXXX {

/**
* @notice emit the use binding informain
* @param id nft id
* @param identitiesRoot new identity root
*/
event SetIdentitiesRoot(
uint256 id,
bytes32 identitiesRoot
);

/**
* @notice
* @dev set the user ID binding information of NFT with identitiesRoot
* @param id nft id
* @param identitiesRoot multi UserID Root data hash
* MUST allow external calls
*/
function setIdentitiesRoot(
uint256 id,
bytes32 identitiesRoot
) external;

/**
* @notice
* @dev get the multi-userID root by NFTID
* @param id nft id
* MUST return the bytes32 multiUserIDsRoot
* MUST NOT modify the state
* MUST allow external calls
*/
function getIdentitiesRoot(
uint256 id
) external returns(bytes32);

/**
* @notice
* @dev verify the userIDs binding
* @param id nft id
* @param userIDs userIDs for check
* @param identitiesRoot msg hash to veriry
* @param signature ECDSA signature
* MUST If the verification is passed, return true, otherwise return false
* MUST NOT modify the state
* MUST allow external calls
*/
function verifyIdentitiesBinding(
uint256 id,address nftOwnerAddress,string[] memory userIDs,bytes32 identitiesRoot, bytes calldata signature
) external returns (bool);

}
```

This is the “ERCXXX Metadata JSON Schema” referenced above.
```json
{
"title": "Asset Metadata",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Identifies the asset to which this NFT represents"
},
"description": {
"type": "string",
"description": "Describes the asset to which this NFT represents"
},
"image": {
"type": "string",
"description": "A URI pointing to a resource with mime type image"
},
"MultiIdentities": [
{
"userID": {
"type": "string",
"description": "User ID of Web2 and web3(DID)"
},
"verifierUri": {
"type": "string",
"description": "Verifier Uri of the userID"
},
"memo": {
"type": "string",
"description": "Memo of the userID"
},
"properties": {
"type": "object",
"description": "properties of the user ID information"
}
}
]
}
}
```

## Rationale

Designing the proposal, we considered the following problems that are solved by this standard:
![EIP Flow Diagram](../assets/eip-XXXX/img/Identity-aggregated-NFT-flow.png)


1. Resolve the issue of multiple ID bindings for web2 and web3.
By incorporating the MultiIdentities schema into the metadata file, an authorized bond is established between user identity information and NFTs. This schema encompasses a userID field that can be sourced from a variety of web2 platforms or a decentralized identity (DID) created on blockchain. By binding the NFT ID with the UserIDInfo array, it becomes possible to aggregate multiple identities seamlessly.
2. Users have full ownership and control of their data
Once the user has set the metadata, they can utilize the setIdentitiesRoot function to establish a secure binding between hashed userIDs objects and NFT ID. As only the user holds the authority to carry out this binding, it can be assured that the data belongs solely to the user.
3. Verify the binding relationship between data on-chain and off-chain data through signature based on ERC-1271

Check failure on line 140 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> EIPS/eip-XXXX.md | 140 | 3. Verify the binding relationship between data on-chain and off-chain data through signature based on ERC-1271 | = info: the pattern in question: `(?i)(?:eip|erc)-[0-9]+`

Check failure on line 140 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> EIPS/eip-XXXX.md | 140 | 3. Verify the binding relationship between data on-chain and off-chain data through signature based on ERC-1271 | = info: the pattern in question: `(?i)(?:eip|erc)-[0-9]+`
Through the signature method based on the ERC-1271 protocol, the verifyIdentiesBinding function of this EIP realizes the binding of the userID and NFT owner address between on-chain and off-chain.

Check failure on line 141 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> EIPS/eip-XXXX.md | 141 | Through the signature method based on the ERC-1271 protocol, the verifyIdentiesBinding function of this EIP realizes the binding of the userID and NFT owner address between on-chain and off-chain. | = info: the pattern in question: `(?i)(?:eip|erc)-[0-9]+`

Check failure on line 141 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> EIPS/eip-XXXX.md | 141 | Through the signature method based on the ERC-1271 protocol, the verifyIdentiesBinding function of this EIP realizes the binding of the userID and NFT owner address between on-chain and off-chain. | = info: the pattern in question: `(?i)(?:eip|erc)-[0-9]+`
1. userID format validation
2. IdentitiesRoot Consistency verification
3. Signature validation for NFTs
4. Signature validation for NFT owner

As for how to verify the authenticity of the individuals' identities, wallets, accounts, there are various methods, such as zk-based DID authentication onchain, and offchain authentication algorithms, such as auth2, openID2, etc.

## Backwards Compatibility

As mentioned in the specifications section, this standard can be fully EIP-721 compatible by adding an extension function set.

Check failure on line 151 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> EIPS/eip-XXXX.md | 151 | As mentioned in the specifications section, this standard can be fully EIP-721 compatible by adding an extension function set. | = info: the pattern in question: `(?i)(?:eip|erc)-[0-9]+`

Check failure on line 151 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

references to proposals with a `category` of `ERC` must use a prefix of `ERC`

error[markdown-refs]: references to proposals with a `category` of `ERC` must use a prefix of `ERC` --> EIPS/eip-XXXX.md | 151 | As mentioned in the specifications section, this standard can be fully EIP-721 compatible by adding an extension function set. | = help: see https://ethereum.github.io/eipw/markdown-refs/

Check failure on line 151 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> EIPS/eip-XXXX.md | 151 | As mentioned in the specifications section, this standard can be fully EIP-721 compatible by adding an extension function set. | = info: the pattern in question: `(?i)(?:eip|erc)-[0-9]+`

Check failure on line 151 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

references to proposals with a `category` of `ERC` must use a prefix of `ERC`

error[markdown-refs]: references to proposals with a `category` of `ERC` must use a prefix of `ERC` --> EIPS/eip-XXXX.md | 151 | As mentioned in the specifications section, this standard can be fully EIP-721 compatible by adding an extension function set. | = help: see https://ethereum.github.io/eipw/markdown-refs/
In addition, new functions introduced in this standard have many similarities with the existing functions in EIP-721. This allows developers to easily adopt the standard quickly.

Check failure on line 152 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> EIPS/eip-XXXX.md | 152 | In addition, new functions introduced in this standard have many similarities with the existing functions in EIP-721. This allows developers to easily adopt the standard quickly. | = info: the pattern in question: `(?i)(?:eip|erc)-[0-9]+`

Check failure on line 152 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

references to proposals with a `category` of `ERC` must use a prefix of `ERC`

error[markdown-refs]: references to proposals with a `category` of `ERC` must use a prefix of `ERC` --> EIPS/eip-XXXX.md | 152 | In addition, new functions introduced in this standard have many similarities with the existing functions in EIP-721. This allows developers to easily adopt the standard quickly. |

Check failure on line 152 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> EIPS/eip-XXXX.md | 152 | In addition, new functions introduced in this standard have many similarities with the existing functions in EIP-721. This allows developers to easily adopt the standard quickly. | = info: the pattern in question: `(?i)(?:eip|erc)-[0-9]+`

Check failure on line 152 in EIPS/eip-XXXX.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

references to proposals with a `category` of `ERC` must use a prefix of `ERC`

error[markdown-refs]: references to proposals with a `category` of `ERC` must use a prefix of `ERC` --> EIPS/eip-XXXX.md | 152 | In addition, new functions introduced in this standard have many similarities with the existing functions in EIP-721. This allows developers to easily adopt the standard quickly. |

## Test Cases

Tests are included in [`ercXXXX.ts`](../assets/eip-XXXX/test/ercXXXX.ts).

To run them in terminal, you can use the following commands:

```
cd ../assets/eip-XXXX
npm install
npx hardhat test
```

## Reference Implementation

`ERCXXXX.sol` Implementation: [`ERCXXXX.sol`](../assets/eip-4907/contracts/ERCXXXX.sol)

## Security Considerations

This EIP standard can comprehensively empower individuals to have ownership and control of their identities, wallets, and relevant data by themselves adding or removing the NFTs and identity bound information.

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).
78 changes: 78 additions & 0 deletions assets/eip-XXXX/contracts/ERC6066.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

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

import "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
import "./interfaces/IERC6066.sol";

import "hardhat/console.sol";

contract ERC6066 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)
public
onlyTokenOwner(tokenId)
{
_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)
public
view
override
returns (bytes4 magicValue)
{

bool isVerified = false;
isVerified = SignatureChecker.isValidSignatureNow(msg.sender,hash,data);
if(!isVerified){
return BADVALUE;
}

return _signatures[tokenId][hash] ? MAGICVALUE : BADVALUE;
}

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


}
100 changes: 100 additions & 0 deletions assets/eip-XXXX/contracts/ERCXXXX.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.17;

import { StrSlice, toSlice } from "@dk1a/solidity-stringutils/src/StrSlice.sol";
import "./interfaces/IERCXXXX.sol";
import "./ERC6066.sol";

contract ERCXXXX is ERC6066, IERCXXXX {

using { toSlice } for string;
mapping (uint256 => bytes32) _idMultiIdentitiesRootBinding;
constructor(string memory _name, string memory _symbol) ERC6066(_name, _symbol) {}

/**
* @notice
* @dev set the user ID binding information of NFT with multiIdentitiesRoot
* @param id nft id
* @param multiIdentitiesRoot multi UserID Root data hash
*/
function setIdentitiesRoot(
uint256 id,
bytes32 multiIdentitiesRoot
) external {

sign(id, multiIdentitiesRoot);
_idMultiIdentitiesRootBinding[id] = multiIdentitiesRoot;

emit SetIdentitiesRoot(id,multiIdentitiesRoot);
}

/**
* @notice
* @dev Update the user ID binding information of NFT
* @param id nft id
*/
function getIdentitiesRoot(
uint256 id
) external view returns(bytes32){

return _idMultiIdentitiesRootBinding[id];
}

/**
* @notice
* @dev verify the userIDs binding
* @param id nft id
* @param multiIdentitiesRoot msg hash to veriry
* @param userIDs userIDs for check
* @param signature ECDSA signature
*/
function verifyIdentitiesBinding(
uint256 id,address nftOwnerAddress,string[] memory userIDs,bytes32 multiIdentitiesRoot, bytes calldata signature
) external view returns (bool){

//nft owner check
require(ownerOf(id) == nftOwnerAddress,"nft owner is not correct");

//user id length check
uint256 userIDLen = userIDs.length;
require(userIDLen > 0,"userID cannot be empty");


for(uint i = 0 ;i < userIDLen ;i ++){
_verifyUserID(userIDs[i]);
}

// bool isVerified = false;
bytes4 sigResult = isValidSignature(id,multiIdentitiesRoot,signature);
if(sigResult == BADVALUE){
return false;
}else{
return true;
}
}

function _verifyUserID(string memory userID) internal view{

require(bytes(userID).length > 0,"userID can not be empty");

//first part(encryption algorithm or did) check
string memory strSplit = ":";
bool found;
StrSlice left;
StrSlice right = userID.toSlice();
(found, left, right) = right.splitOnce(strSplit.toSlice());
require(found,"the first part delimiter does not exist");
require(bytes(left.toString()).length > 0,"the first part does not exist");

//second part(Organization Information) check
(found, left, right) = right.splitOnce(strSplit.toSlice());
require(found,"the second part delimiter does not exist");
require(bytes(left.toString()).length > 0,"the second part does not exist");

//id hash check
require(bytes(right.toString()).length == 64,"id hash length is not correct");

}

}

21 changes: 21 additions & 0 deletions assets/eip-XXXX/contracts/interfaces/IERC6066.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.17;

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);
}
Loading

0 comments on commit 3ee8f74

Please sign in to comment.