首页 > 资讯 > Solidity学习代码示例
路安  

Solidity学习代码示例

摘要:如果学习了我之前的Solidity学习代码示例的一系列文章,那么我们对Solidity编写以太坊智能合约已经非常熟悉了。上一篇文章《Solidity学习代码示例-ERC20示例》中,我们已经掌握了如何区块链的以太坊链发行ERC20代币,也从每一个代码块具体学习了其用意。接下来,让我们开始学习ERC7

如果学习了我之前的Solidity学习代码示例的一系列文章,那么我们对Solidity编写以太坊智能合约已经非常熟悉了。上一篇文章《Solidity学习代码示例-ERC20示例》中,我们已经掌握了如何区块链的以太坊链发行ERC20代币,也从每一个代码块具体学习了其用意。接下来,让我们开始学习ERC721,也就是我们常说的NFT。话不多说,让我们开始学习如何发布自己的NFT,并且从代码层面去学习每个代码块的用意。

我们打开https://remix.ethereum.org/以太坊智能合约在线编辑器,创建一个文件ERC721.sol,将代码放进文件中。

然后,我们来到编译到界面,可以自行打开自动编译或者手动编译到选择项。

编译通过之后,我们开始在本地测试网络部署我们的合约。

部署完成之后,我们就能看到我们部署的合约地址,以及合约的全部方法。

根据上面的步骤,我们就已经将合约进行编译,并且部署到了这款在线合约编辑器给我们提供的本地测试网络上。当然了,如果我们想把合约部署到以太坊真实的网络上,我们只需要切换下网络,连接下我们的浏览器插件钱包进行操作就可以了。

在这份ERC721的代码中,我们实现的功能是任何人都可以调用合约的mint方法铸造自己的NFT,每个NFT的id都是唯一的。接下来,我们仔细分析讲解下源代码。

ERC721.sol

// SPDX-License-Identifier: MITpragma solidity ^0.8.12;import '@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol';import '@openzeppelin/contracts/access/Ownable.sol';import '@openzeppelin/contracts/utils/Counters.sol';contract MyNFT is ERC721Enumerable,Ownable {using Counters for Counters.Counter;using Strings for uint256;Counters.Counter private _tokenIdTracker;event Mint(address indexed from, address indexed to, uint256 indexed tokenId);uint256 private _currentTokenId = 0;string private constant _baseTokenURI = "https://ipfs.io/ipfs/QmXgMRpwoEtuhksEJ7LD9ySLzAvAM5tqs1q6rGZ38Qg1Kf/";string public baseExtension = ".json";constructor(string memory name,string memory symbol) ERC721(name, symbol) {require(bytes(name).length != 0 bytes(symbol).length != 0,"name and symbol can't be empty");}function tokenURI(uint256 tokenId) public view override returns (string memory) {return string(abi.encodePacked(_baseTokenURI, tokenId.toString(),baseExtension));}function mint() external {// tokenId的从1开始计数uint256 _tokenId = _tokenIdTracker.current()+1;_mint(msg.sender, _tokenId);_tokenIdTracker.increment();emit Mint(address(0), msg.sender, _tokenId);}}

import '@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol';

import '@openzeppelin/contracts/access/Ownable.sol';

import '@openzeppelin/contracts/utils/Counters.sol';

发行代币就必须遵循它的EIP协议,之前的ERC20代币遵循的就是EIP20的协议。而Openzeppelin是用于开发安全的智能合约库,其代码经过社区的审查并有着坚实的社区基础,实现了标准的代币的接口,我们可以放心的使用import功能来讲其导入到我们的代码中。所以,在这里,我们跟ERC20代码相似,也导入其代码的接口文件。

contract MyNFT is ERC721Enumerable,Ownable {}

使用is将我们需要用到的文件方法继承到这份主合约中,这样,我们就能使用来自继承到合约的所有方法了。

using Counters for Counters.Counter;

using Strings for uint256;

Counters.Counter private _tokenIdTracker;

由于Counter.sol是一个library库合约,所以这里要使用using来使用这个库合约。具体的使用方式是 using 库函数(来自库A)附加到任何类型(B)。

在下面的代码中,我们会用到这个uint类型的tokenId转换成string类型,所以,我们还得使用 using Strings for uint256 这个方法。

_tokenIdTracker变量直接使用库合约的Counter方法来做其类型声明。

event Mint(address indexed from, address indexed to, uint256 indexed tokenId);

我们声明了一个Mint事件,在执行mint方法的时候,可以返回具体的数据信息。注意的是这里使用了indexed,意思是过滤的意思。

uint256 private _currentTokenId = 0;

这里我们声明当前的tokenId到角标是从0开始。

string private constant _baseTokenURI = "https://ipfs.io/ipfs/QmXgMRpwoEtuhksEJ7LD9ySLzAvAM5tqs1q6rGZ38Qg1Kf/";

string public baseExtension = ".json";

每个NFT都是一张图片,又或者是视频。那么这些图片或者视频是不会通过合约放在链上来存储的。考虑到数据存储在链上是需要消耗gas费,是需要成本的,因此,我们通常将这些图片或者视频的数据放在链下来存储。而通常我们的存储方式是借助现有的分布式存储工具ipfs或者pinata,又或者是其它的分布式存储工具。

在我的这串代码块中,我使用的是ipfs分布式存储。在ipfs中,我预先将所有的图片存储在ipfs文件夹中,然后按照尾缀 .json 的格式存储。在命名上按照阿拉伯数字1开始依次递增命名。通常我们的做法是在代码的逻辑中让我们的tokenId从1开始计数,而不从0开始,这在合约部署成本上是有考虑的,从1开始计数会使得我们的合约部署成本可以减少些。在 .json 文件中,我们可以存储我们自己想要存储的元数据内容。比如我们的NFT是加密朋克类型的,那么我们的 .json 文件的元数据内容可以是关于这类型加密朋克NFT的长相,性别,以及微小外貌细节上的区别,以及图片的路径等。

元数据,也就是NFT的一些属性信息。

constructor(

string memory name,

string memory symbol

) ERC721(name, symbol) {

require(bytes(name).length != 0 bytes(symbol).length != 0,"name and symbol can't be empty");

在构造器中,我们使用了ERC721协议里的构造函数,参数传入我们NFT的名称和symbol。

function tokenURI(uint256 tokenId) public view override returns (string memory) {

return string(abi.encodePacked(_baseTokenURI, tokenId.toString(),baseExtension));

查询tokenId的URI,使用abi.encodePacked方法将我们在代码中写好的URL跟我们的tokenId拼接起来。这样,我们通过tokenId就能查询到我们相应的代币的元数据了。

function mint() external {

// tokenId的从1开始计数

uint256 _tokenId = _tokenIdTracker.current()+1;

_mint(msg.sender, _tokenId);

_tokenIdTracker.increment();

emit Mint(address(0), msg.sender, _tokenId);

这个铸造等方法是我们的核心方法,通过触发mint方法,我们可以得到我们的tokenId,每触发一次,tokenId递增,这也就是我们常说的无限量版NFT,没有最大总量的限制,想要多少就铸造多少。在这个方法的逻辑上,我们也可以进行修改成我们需要的逻辑。比如说,每个用户限购多少,当总量达到一定数量时不可再mint等等。

当然了,除了我们自己写的方法,我们还可以使用来自继承合约ERC721Enumerable中的方法。它同样包含与ERC20相似的接口,如approve,transferFrom,balanceOf方法等。我们使用智能合约在线编辑器,将我们的合约部署起来后,我们可以将方法都尝试一遍。铸造,转让,查询,功能很完善。

至此,我们就学会了如何去部署NFT了。ERC721属于非同质化代币,不同于ERC20这种同质化代币。非同质化代币的每个代币它们的图片信息可能是一样的,但是它们唯一的区别在于它们有唯一的合约地址,唯一的tokenId,通过这种方式来去区别它们。

学会了今天这篇文章,我们就能发现,市面上的代币在技术上的实现是非常简单的,而为什么价值会这么高,这跟炒作,营销,以及知名度就挂上钩了。任何产品,只要炒得够热,大家认可得多,价值就高。但是我们作为技术开发者,我们就能清楚其中一二。以后,我们更希望的是将技术改造我们的生活,服务于我们的生活,而不是拿来炒作。

好了,我们的合约编程之旅到此就画个句号了。接下来,我们开始学习了解下,在编写合约的过程中,我们需要注意什么,我们需要知道的是什么,下一篇文章,带大家再从代码之外来更深认识一下这门合约编程语言区别于其它传统的接口编程语言的奥秘。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

来源:

Tags:
免责声明
世链财经作为开放的信息发布平台,所有资讯仅代表作者个人观点,与世链财经无关。如文章、图片、音频或视频出现侵权、违规及其他不当言论,请提供相关材料,发送到:2785592653@qq.com。
风险提示:本站所提供的资讯不代表任何投资暗示。投资有风险,入市须谨慎。
世链粉丝群:提供最新热点新闻,空投糖果、红包等福利,微信:juu3644。