# NFT的原理和ERC721合约解读

By [Xoen](https://paragraph.com/@xoenxie) · 2022-04-23

---

hi，我是Xoen，一个区块链小白，我对WEB3世界充满了好奇，就像达芬奇一样。

进入币圈后，无论是谁，多多少少都会持有一些小图片对吧，这些小图片就是NFT，也就是非同质化代币，为什么叫非同质化呢，就是它没办法像同质化代币，可以把1个拆成10个0.1。随着接触NFT越来越久，我就越来越好奇它的原理。

也正是因为有一定的标准，OpenSea才能正确的显示我们NFT图片，以及NFT的属性。我们先来看个例子，比如说无聊猴：

![](https://storage.googleapis.com/papyrus_images/d658cd8b53b24905f9486c9265c060db02783c15820a5628130426c6b5aa850c.png)

可以看出，一个NFT的展示分为几个部分，一是图片（其实它也可以是视频）二是属性（Properties），三是详细信息（Details）。其实这几部分数据也可以称作为NFT的元数据，它也是有一定标准，有兴趣的可以[点击这里了解详细](https://docs.opensea.io/docs/metadata-standards)。

点击Details下的TokenID后面的数字，一般会跳转到一个链接，这个链接就是该NFT的tokenURI，它指向的就是NFT元数据的存储地址。OpenSea会根据这个地址拿到元数据，然后在页面上呈现。

我们看无聊猴5465和7029的URI：

![](https://storage.googleapis.com/papyrus_images/9d9f263d1f221b6e74bf77d4febbd55b31a3147d3dd4a4cb0477353b0153cb2f.png)

![](https://storage.googleapis.com/papyrus_images/aa093f4e5d2befb95eec8cdbcb00eb3dbf84c9d4b3cca92b9ed62fe879ecce3c.png)

你可以发现除了后面tokenId之外，其他都一样。所以一般NFT他的URI都是由一个基础的前缀和tokenId来组成一个唯一的tokenURI。

因此我们发现，其实对于一个NFT，大部分数据都在链下，而链上只是存储了一个唯一ID，再通过这个tokenId组成一个链接来索引到NFT的元数据。而NFT的图片和元数据其实是放在中心化托管服务器上，也有的是放在ipfs上。当然也有例外的，比如说，CyberBrokers据说是fully on chain的，这个等有空了好好研究一下。分析完NFT原理了，那我们就再来看看大名鼎鼎的ERC721标准合约里到底有哪些内容呢。

官方链接在这里：

[https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC721](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC721)

**截图里的代码只是包含了其中一部分内容。**

**IERC721是标准接口，如果不使用官方的ERC721，也可以自己实现：**

![IERC721](https://storage.googleapis.com/papyrus_images/32aff5166740b6441f996b21ee8b191fa59872ece6814f94846d97bb32c06e52.png)

IERC721

**再看看官方的ERC721实现：**

![ERC721-P1](https://storage.googleapis.com/papyrus_images/83b5386a5902087d32688fccb13e43a33f6e66468750c3cc1f8e3b232e3d721c.png)

ERC721-P1

![ERC721-P2](https://storage.googleapis.com/papyrus_images/a4fa6c6b038bec78dd4741c1d6806664c7831fe0dee065a24ceb2afb012b93b3.png)

ERC721-P2

![ERC721-P3](https://storage.googleapis.com/papyrus_images/6dd6a27ec370aed2238e3522a13a9d4f65169c54e3b70ae157dca076852eb5ff.png)

ERC721-P3

![ERC721-P4](https://storage.googleapis.com/papyrus_images/aad4c7851fed43afa42b993cd2f5ee924dc3eef6545a4ca92653a44124d57a50.png)

ERC721-P4

![ERC721-P5](https://storage.googleapis.com/papyrus_images/412ca1b785ab84c7b0e43cc766307c829cedd070739968f03048ad019d627786.png)

ERC721-P5

个人总结：ERC721包含了所有基础的功能，拥有者可以发送tokenId给其他人，但是其他人要转移别人的tokenId，需要通过**approve**和**setApprovalForAll**获得权限之后才能转移他人tokenId。看完了标准代码，我们再看看，如果我们自己要发一个NFT要怎么做呢？

找一个示例，来看看无聊猴的合约代码（删除了一些无关代码）其实还是很简单的：

![](https://storage.googleapis.com/papyrus_images/8d99ac6e6d99f8d66fa779f21fd2514d7403e80d58b6af9e47b6edcc1868e841.png)

在OpenZeppelin合约库里其实还有很多针对ERC721的扩展合约，大家有兴趣可以自己去github上看看。一定能收获不少。还有就是不同的项目，可能都集成了ERC721，但是还有一些自己的实现，大家也可以通过OpenSea来找到他们的合约代码看看。

今天又是大太阳天，希望大家都能买到喜欢的NFT，并赚到钱~~~~~

---

*Originally published on [Xoen](https://paragraph.com/@xoenxie/nft-erc721)*
