以太坊区块链ERC-721协议的实现(NFT代币标准)

1. 什么是ERC-721标准

ERC-721是以太坊区块链上用于NFT(非同质化代币)的一个标准,是一种其他开发人员都遵守的模板或者格式,用于创建代表数字资产的独特代币,并且每个ERC-721代币都是独一无二的。使用统一的标准可以使合约代码变得更简单,复用性更强。ERC-721的出现促进了NFT的创建,并在GameFi、Defi、NFTfi等项目中都有广泛的应用。

2. ERC-721接口

每个代币其实都是由智能合约或者一段代码生成的,ERC-721代币是由程序员使用例如solidity编程语言在智能合约中使用ERC-721提供的相同模板来生成。除此之外,开发人员还可以对代币进行额外的定制,例如代币的名字,代币的拥有者等特征,还可以将代币与其他的智能合约进行交互。

2.1 ERC-721接口中可以调用的函数方法

1.balanceOf(返回某个用户拥有NFT的数量)

  • 返回的数量可能是动态变化的,因为地址的 NFT 持有量可以随着时间和交易而改变

传入的参数为要查询的用户地址。返回值为NFT的数量

function balanceOf(address _owner) external view returns (uint256)

2.ownerOf(返回某个NFT所有者的用户地址,传入的参数为代币的唯一ID) 

  • 如果给定的 NFT 标识符不存在或已被销毁,那么调用 ownerOf() 方法将会抛出异常或返回一个特殊的无效地址。
  • 应用程序可以根据 NFT 的标识符查询该 NFT 的当前所有者地址。这个地址可以用于进一步的操作,比如展示 NFT 的所有者信息、验证所有权或执行与所有者相关的交易。

传入的参数为NFT的tokenID。返回值为用户的地址。

function ownerOf(uint256 _tokenId) external view returns (address);

 3.safetTransferFrom(将NFT安全地从A账户转移资产到B账户)

  • 如果调用者没有足够的权限或没有拥有要转移的 NFT,调用此方法将会失败。
  • 如果_to是零地址,则会引发异常。
  • 如果_tokenId不是有效的NFT,则会引发异常。
  • 如果接收方是一个智能合约,它必须实现 ERC721Receiver 接口来处理接收到的 NFT。

传入的参数分别为代币的拥有者,代币的接收者,代币的Id,想要携带的数据信息)

function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;

  4.safetTransferFrom(将NFT从A账户转移资产到B账户)

与safeTransferFrom的区别是,代币拥有者有责任确保接收方能成功接收到代币,不然会永久丢失

function transferFrom(address _from, address _to, uint256 _tokenId) external payable;

 5.approve(为某个NFT批准一个用户地址)

  • 零地址表示没有批准的地址。
  • 除非 msg.sender 是当前NFT的所有者或被当前所有者授权的用户,否则会引发异常。

接收的参数分别为想要批准的用户地址,想要被批准的代币ID

function approve(address _approved, uint256 _tokenId) external payable;

 6.setApprovalForAll(授权或撤销第三方管理员管理msg.sender的所有资产)

  • 合约必须允许一个资产所有者可以有多个管理员

接收的参数分别为想要授权的管理员的地址,想要授权还是撤销

function setApprovalForAll(address _operator, bool _approved) external;

 7.getApproved(用于获取某个NFT授权的用户地址)

接收的参数为想要进行查询的代币ID,返回的值为用户地址,如果没有授权用户则返回0地址

function getApproved(uint256 _tokenId) external view returns (address);

8.isApprovedForAll(查询一个用户地址是否是另一个用户地址授权的管理员)

接收的参数分别为拥有NFT的用户地址,查询授权管理员的地址。返回值为布尔值

function isApprovedForAll(address _owner, address _operator) external view returns (bool);

 2.2 ERC-721接口中提供的事件

1.Transfer(当任何NFT的所有权发生变化时触发此事件包括NFT的创建和销毁)

  • 在任何转移时,如果该 NFT 有授权地址,则授权地址会被重置为无。
  • 在合约创建期间,可以创建和分配任意数量的 NFT 而不触发 Transfer事件。
  • 通过监听 Transfer 事件,应用程序可以跟踪 NFT 的所有权变化,执行相应的逻辑操作,例如更新用户的资产列表、展示所有权变更的历史记录等。

接收的参数分别为转移前的用户地址,转移后的用户地址,代币的ID

event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);

2.Approval(一个地址授权另一个地址管理自己的某个NFT 时触发)

  • 通过监听 Approval 事件,应用程序可以跟踪 NFT 的授权操作,执行相应的逻辑操作,例如更新授权列表、限制对 NFT 的操作权限等。
  • NFT 的所有者可以授权其他地址代表自己进行特定的操作,例如交易、出租或展示。

接收的参数分别为代币拥有者的地址,想要授权的地址,代币的ID

event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);

3.ApprovalForAll(当一个地址授权另一个地址管理其所有的 NFT 时触发)

  • 通过监听 ApprovalForAll 事件,应用程序可以跟踪全局授权操作,执行相应的逻辑操作,例如更新授权列表、限制对所有 NFT 的操作权限等。
  • NFT 的所有者可以一次性授权一个地址来管理自己所有的 NFT,而不需要逐个进行授权操作。
  • 这在某些场景下非常有用,例如允许一个市场合约代表用户管理其所有的 NFT。

接收的参数分别为代币拥有者的地址,想要授权的地址,想要授权还是撤销授权。

event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

 

3.ERC721TokenReceiver接口

ERC721TokenReceiver是以太坊区块链生态系统中定义的一个接口。它是ERC721标准的一部分。在ERC721标准合约中调用safeTransferFrom进行资产转移时,如果接收者是一个合约,它必须实现ERC721TokenReceiver接口中的 onERC721Received 方法。

3.1 ERC721TokenReceiver接口中可以调用的方法

onERC721Received(用于接收 ERC721 代币)

  • 该方法在一个合约接收到 ERC721 代币时被调用。当一个 ERC721 代币被转移到实现了 ERC721Receiver 接口的合约时,ERC721 合约会调用目标合约的 onERC721Received 方法。
  • 实现 onERC721Received 方法的合约可以在接收代币时执行自定义的逻辑或验证。例如,合约可以检查附加数据,验证转移的合法性,更新合约的内部状态,或触发其他操作。

接收的参数分别为执行转移操作的地址,代币的拥有者,代币的Id,携带的数据信息。返回一个四字节的数,表示接收合约是否成功处理了代币的转移。如果返回值等于bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))则表示接收成功

function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes _data) external returns(bytes4)

4. ERC721MetaData接口

ERC721Metadata 是 ERC721 标准的一个附加接口,用于提供有关NFT的元数据信息。它定义了获取 NFT 元数据的方法,包括名称、符号和 URI,这是一个可选的接口。

4.1 ERC721MetaData接口中提供的方法

1.name(用于返回NFT的名称)

  • 该方法是只读的(view),不会修改合约的状态。
  • NFT 的名称是由合约开发者定义的,用于标识和描述特定的 NFT 集合或项目。

返回一个字符串,为该NFT代币的名称

function name() external view returns (string _name);

2.symbol(用于返回NFT的符号)

  • 该方法是只读的(view),不会修改合约的状态。
  • NFT 的符号是由合约开发者定义的,通常是一个简短的字符串,用于表示该 NFT 的标识符。
  • 符号的作用是提供一个简洁的标识符,用于在用户界面、交易所或其他应用程序中显示和识别特定的 NFT。

返回值为一个字符串,表示 NFT 的符号

function symbol() external view returns (string _symbol);

3.tokenURI(返回与给定的 tokenId 相关联的元数据 URI)

  • 该方法是只读的(view),不会修改合约的状态。
  • 元数据 URI 是一个指向包含有关 NFT 详细信息的 JSON 文件的链接。这些详细信息可以包括 NFT 的名称、描述、图像链接、创作者信息等。
  • 通过访问该 URI,应用程序和用户可以获取有关 NFT 的更多信息,以便进行展示、验证或其他操作。

返回值为一个字符串,表示与该 NFT 相关联的元数据 URI

function tokenURI(uint256 _tokenId) external view returns (string);

5. ERC721Enumerable接口

ERC721Enumerable 是一个 ERC721 标准的扩展接口,它为非同质化代币(NFT)合约提供了枚举功能,允许查询和遍历合约中的 NFT。这是一个可选的接口

1.totalSupply(用于返回合约中当前存在的 NFT 的总数量)

  • 该方法是只读的(view),不会修改合约的状态。
  • 如果 totalSupply() 返回值为 100,那么意味着合约中当前存在 100 个不同的 NFT。
  • 该方法对于实现 NFT 集合的展示页面、搜索功能或其他需要了解合约中 NFT 总数量的场景非常有用。

返回值为一个无符号整数(uint256),表示合约中当前存在的 NFT 的总数量

function totalSupply() external view returns (uint256);

2.tokenByIndex(用于按索引查询合约中指定位置NFT的 tokenId) 

  • 索引位置范围应在合约中存在的 NFT 总数量范围内,即从 0 到 totalSupply() - 1
  • 应用程序可以根据索引位置获取合约中特定位置的 NFT 的标识符,从而可以进行进一步的操作,例如展示特定索引位置的 NFT 的详细信息、执行特定索引位置的 NFT 的交易等。

接收的参数为要查询的 NFT 在合约中的索引位置,返回值为NFT的tokenID

function tokenByIndex(uint256 _index) external view returns (uint256);

 3.tokenOfOwnerByIndex(用于按索引查询指定用户地址拥有NFT的tokenId)

  • 索引位置范围应在指定地址(owner)拥有的 NFT 数量范围内,即从 0 到 balanceOf(owner) - 1
  • 应用程序可以根据拥有者地址和索引位置获取该地址拥有的特定索引位置的 NFT 的标识符

传入的参数为查询用户的地址,NFT的索引值。返回值为NFT的tokenID

function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);

6.ERC-165标准

ERC-165 标准的主要用途是提供一种通用的接口查询机制,使合约能够声明并检测自己是否实现了特定的接口。每个符合ERC-721标准的合约不仅要实现ERC-721的接口,还要实现ERC-165的接口。

6.1 ERC-165接口中提供的方法

supportsInterface(用于查询合约是否支持特定的接口)

  • 合约实现了 ERC-165 接口后,其他合约或外部实体可以调用 supportsInterface 方法并传入一个接口标识符。
  • 接口标识符是一个 4 字节的哈希值,用于唯一标识一个接口。它由接口名称的前 4 个字节的 keccak-256 哈希值组成。
  • 例如,如果要查询 ERC-721 标准是否被合约支持,可以使用 0x80ac58cd 作为接口标识符。

接收的参数为一个 4 字节的标识符,用于表示要查询的接口。返回一个布尔值

function supportsInterface(bytes4 interfaceID) external view returns (bool);

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ERC721以太坊上面的一个智能合约标准,它定义了非同质化代币NFT)的标准接口,使得开发者能够创建和交易独特的数字资产,如游戏道具、收藏品等。 要实现ERC721标准,需要编写智能合约代码,可以使用Solidity语言来实现。以下是一个简单的ERC721智能合约实现: ``` pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; contract MyNFT is ERC721 { using Counters for Counters.Counter; Counters.Counter private _tokenIds; constructor() ERC721("MyNFT", "NFT") {} function mintNFT(address recipient, string memory tokenURI) public returns (uint256) { _tokenIds.increment(); uint256 newItemId = _tokenIds.current(); _mint(recipient, newItemId); _setTokenURI(newItemId, tokenURI); return newItemId; } } ``` 上述代码实现了一个简单的ERC721智能合约,包含了一个名为`MyNFT`的合约,继承自`ERC721`,并实现了`mintNFT`函数用于创建NFT。 接下来,需要搭建一个NFT交易所,可以使用Web3.js和React.js来实现。以下是一个简单的NFT交易所前端代码实现: ``` import React, { useState, useEffect } from "react"; import Web3 from "web3"; import MyNFT from "./contracts/MyNFT.json"; const web3 = new Web3(Web3.givenProvider || "http://localhost:8545"); function App() { const [account, setAccount] = useState(""); const [nfts, setNFTs] = useState([]); useEffect(() => { async function loadBlockchainData() { const accounts = await web3.eth.getAccounts(); setAccount(accounts[0]); const networkId = await web3.eth.net.getId(); const deployedNetwork = MyNFT.networks[networkId]; const myNFT = new web3.eth.Contract( MyNFT.abi, deployedNetwork && deployedNetwork.address ); const totalSupply = await myNFT.methods.totalSupply().call(); const nftPromises = []; for (let i = 1; i <= totalSupply; i++) { nftPromises.push(myNFT.methods.tokenURI(i).call()); } const nftURIs = await Promise.all(nftPromises); setNFTs(nftURIs); } loadBlockchainData(); }, []); async function mintNFT() { const myNFT = new web3.eth.Contract(MyNFT.abi, MyNFT.networks[5777].address); await myNFT.methods .mintNFT(account, "https://example.com/my-nft.json") .send({ from: account }); setNFTs([...nfts, "https://example.com/my-nft.json"]); } return ( <div className="App"> <h1>My NFTs</h1> <p>Account: {account}</p> <button onClick={mintNFT}>Mint NFT</button> <ul> {nfts.map((nft) => ( <li> <a href={nft}>{nft}</a> </li> ))} </ul> </div> ); } export default App; ``` 上述代码实现了一个简单的NFT交易所前端,包含了一个名为`App`的React组件,用于显示用户的NFT和创建新的NFT。在`loadBlockchainData`函数中,使用Web3.js和智能合约ABI来获取用户账户和NFT列表。在`mintNFT`函数中,使用Web3.js和智能合约ABI来创建新的NFT,并更新NFT列表。 最后,需要将智能合约部署到以太坊网络上,可以使用Remix或Truffle等工具进行部署。部署成功后,将智能合约地址更新到前端代码中即可。 以上是一个简单的ERC721标准实现NFT交易所搭建过程,具体实现过程可能会因为实际应用场景的不同而略有差异,需要根据实际情况进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值