【端午企划】简易开发NFT 专案的三步骤| 智能合约开发计划#8
三个步骤:写程式→ 编译程式码→ 发布智能合约
不管如何,要开发NFT 专案一定要有这三个步骤:撰写程式码→ 编译程式码→ 在区块链上发布智能合约。
前面的文章中我们已经成功上传了NFT 的Metadata,以及NFT 的图片至IPFS 了,再来就可以拿这个IPFS 的网址开始写NFT 专案的程式码啦!
这次开发是使用「Remix」 ,它是一个用来开发Solidity 智能合约程式语言的线上编辑环境,我们所有的程式开发与部属程式码到区块链上都会透过Remix 来进行操作,这样可以舍去非常多在自己电脑上安装环境的事情,大幅降低开发智能合约的门槛,也能让一些新手读者在真正去实作的时候更容易有「第一次动手写程式打造一项产品」的体验。
但除了Solidity 语言以及Remix 开发环境以外,这次还要介绍一个很重要的智能合约函式库叫做「OpenZeppelin」,透过这套工具将大大加速开发所需的时间,而且这个函式库对于资安的部分一直都有在进化,比起我们自己撰写程式码会更加安全。
OpenZeppelin
OpenzZeppelin 本身是一间公司,它们的主要业务大概是提供工具让开发者更方便开发与管理智能合约以及提供智能合约程式码资安方面的审计,在官网上可以看到一些它们参与过很有名的专案开发或协助审计,例如Brave 浏览器、Compound 借贷平台,官方网站网址是: https://openzeppelin.com/
他们提供了一套开源又相对安全的智能合约开发函式库供智能合约开发者使用,翻译成白话就是他们打造了一个工具箱,并且开放让所有人能够随意领取这个免费的工具箱,领取了工具箱就可以用里面的工具去打造自己的产品,使用OpenZeppelin 的工具箱做为专案开发的根基,我们想要打造车子时就不再需要从轮子开始造起了,是不是佛心公司。
至于他们这包工具箱的完整程式码网址是: https://github.com/OpenZeppelin/openzeppelin-contracts/
这包超大包家庭号原始码大致上可以分为下列几种功用:
1. Access control: 谁拥有这个智能合约或是整个系统,且可以对其进行操作。
2. Token: 铸造自己的代币和NFT,目前看起来总共提供五种标准,包含代币标准(ERC-20、ERC-777), NFT 标准(ERC-721、ERC-1155)以及NFT 的税收标准(ERC-2981),直接使用的话那些官方文件规定的接口都已经打造完成,我们不用额外再处理了。
3. Gas Station Network: 让用户在跟我们的智能合约互动时,可以不需要自己付费。
4. Utilities: 一些通用的工具,例如能够避免溢位的数学变数、数位签章验证、无须信任机制的支付系统等。
要使用OpenZeppelin 的工具蛮容易的不用下载下来,在Remix 上直接import 要使用的工具即可,底下的程式码会介绍到。
Remix 的初始设定
打开Remix 进行开发,网址: https://remix.ethereum.org/
至于浏览器的部分,会需要使用有安装Metamask 钱包或是其他钱包扩充套件的浏览器,如果你的Metamask 安装在Chrome 上的话就用Chrome 开发吧,因为后续当我们要将智能合约发至测试网时,就需要它里面的测试币来支付链上手续费。
第一次打开,它或许会跳出小视窗显示”Help us to improve Remix”,就看你要不要同意了,意思是当程式发生一些例外状况时,会将当下这个状况回报给以太坊基金会的开发者,帮助他们发现问题进而优化系统。
就像使用一般档案总管那样,我们先点开contracts的资料夹,并点选上方折一角的纸张icon,在contracts资料夹中建立一个新的.sol档,例如abcd.sol、NFT1155.sol,.sol就是solidity程式语言的副档名。
使用OpenZeppelin 快速开发第一个NFT 程式专案
由于这次要发行的是ERC-1155 协议的NFT,我会将档名命名为Basic-1155.sol ,你也可以取个自己喜欢的名字,但是副档名必须是.sol。
第一个NFT 专案会先写一段最简单的程式码,汇入OpenZeppelin,再尝试在本机端编译、发布智能合约,确定可以发布就表示成功了。
Basic-1155.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; contract Basic_1155 is ERC1155 { constructor() ERC1155("ipfs://QmdnBQrQa6KXVeeNr7fpc9uxQLtcCyknjcWqLXtoG1ahTK") {} }
第一行最开始我们需要给一个”SPDX”许可标示符号,这个符号的意思就是这个程式码要不要开源授权给他人使用,开源的程度就与不同的许可有关系,”// SPDX-License-Identifier: MIT”代表MIT开源许可;”// SPDX-License-Identifier: unlicensing”代表不开源,想要使用其他不同许可可以去SPDX看看详细内容。
第二行pragma solidity 就是指定solidity的版本,在这篇文章中我们设定版本号是0.8.x,编译器会使用当下最新的Solidity 0.8.14 版本,由于Solidity 仍是一个更新非常频繁的程式语言,若未来当你看到这篇文章,已经有更新版本的Solidity,而你执行发现程式码有点问题,不妨试着将版本降回0.8.14 再执行看看。
接着第三行import 的意思是要汇入OpenZeppelin 的工具箱ERC1155.sol,这样我们底下的程式码都可以使用它了。
下面的contract 就是主角智能合约了,Basic_1155 是我自己命名的名称,is ERC1155 就是使用到OpenZeppelin 开发好的ERC1155,contract 内constructor 的用途是初次部属智能合约时,会先执行的地方,而且只能被执行一次,所以在我的理解中,constructor是一种设定程式初始参数的概念,后面需要填上一个NFT 所需的URI 栏位,也就是放上前一篇文章中我们发布在IPFS 的.json 档对应到的IPFS 网址,还记得上一篇文章的最后面我做了一张图:
也就是说,当NFT 的显示器在尝试显示这张NFT 的样貌时会先透过我们这边设定的URI 网址连到IPFS 上面的.json 档,并在解析.json 档底下的Metadata 时,找到image 栏位,再透过image 栏位里面的IPFS 网址去连结到真正的图片将NFT 完整地显示出来。
编译与发布智能合约
程式写完就需要编译并发布智能合约到区块链上,我们在【新年企划】人生第一颗发财币| 智能合约开发计划#2时花了不少篇幅解释编译与发布的动作以及细微的设定,这边就简单带过,几个要注意的地方我用红色圈圈框起来了。
最左边的第一张图是编译,选好COMPILER 的版本将要编译的.sol 档编译,看到变成绿色勾勾就可以了。
中间第二张图是发布,要先将ENVIRONMENT 切换成「Injected Web3」,并将Metamask 切换成这次使用的Rinkeby 测试网路,底下CONTRACT 记得换成要发布的合约,如果是用我的程式码,这里应该要选择「Basic_1155」,由于这次我们使用了OpenZeppelin ,选择会比较多不要选错了,接着按Deploy 钱包就会跳出来要求你确认交易,确认交易之后因为要上传任何东西到区块链都需要花点时间,等一下就能看到第三张图了。
就算是发布在测试网路,只要在区块链上动作都是需要支付瓦斯费的,如果还没有ETH 要先领取免费的Rinkeby ETH,网址是: https://faucets.chain.link/rinkeby
如果你做到最右边的第三张图有看到这些东西,就表示你已经成功完成并发布第一个NFT 的专案了,哦不过它现在什么事情都做不到,也还没有可以铸造NFT 的功能,我们继续来改写它吧。
可以被拥有的智能合约(Owner and ownable)
这些我们在区块链上创造的代币或NFT 数位资产,就像是现实生活中的钞票、硬币、不动产,非常直觉都是可以被拥有视作是个人的独立资产。而智能合约本身也可以被归属于某个人的钱包哦!
智能合约就像是一台路边的自动贩卖机一样,需要输入什么数据(投钱、选择商品按钮),将会产生什么结果(掉出饮料),程式码编写会使得这台自动贩卖机的功能不同,除了这些相似之处,智能合约与自动贩卖机一样可以被人拥有,只有拥有者才具有权限进行一些参数设定或修改,可以被拥有的智能合约被称作「Ownable」拥有者被称作「Owner」。
那我们就直接改写刚刚的Basic-1155.sol,增加Ownable 让智能合约能够被拥有,并增加一个function 函式命名为setURI,让智能合约的拥有者能够设定新的网址。
Ownable-1155.sol
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract Ownable_1155 is ERC1155, Ownable { constructor() ERC1155("ipfs://QmdnBQrQa6KXVeeNr7fpc9uxQLtcCyknjcWqLXtoG1ahTK") {} function setURI(string memory newuri) public onlyOwner { _setURI(newuri); } }
这边使用OpenZeppelin 提供的Ownable 工具,所以需要在前面加上一行import 将工具汇入。
第二个要修改的地方是在contract 的右边,重新将原本的Basic_1155 改名成Ownable_1155 避免自己混淆,并加入「, Ownable」,表示这个合约要同时继承OpenZeppelin 开发好的ERC1155 与Ownable。
function setURI 中有个newuri,就是未来当呼叫智能合约的setURI 函式时,需要代入一个网址参数,这个网址参数将会被设定成NFT 的新网址,所以同一个NFT 在设定后可能会有不同的图片外观。
setURI 函式还必须设定为只有智能合约拥有者能够更动,否则路边随便一个路人都能来设定我们NFT 的网址会很不妙,设定的方式也很简单,直接在function 的右边加上onlyOwner 就可以了。
_setURI 则是我们从OpenZeppelin 汇入ERC1155 的接口,呼叫它并丢给它一串网址就能够重新设定NFT 的网址了。
测试与认识Ownable
程式改完就跟前面一样,重新编译跟发布新的智能合约,在这里我们要来实际测试什么叫做「可以被拥有的智能合约」,经过一番探索一定会更懂一些。
发布成功之后,点开这个OWNABLE_1155 的智能合约就会看到超多东西,橘色方块是需要放到区块链上执行的交易,需要付瓦斯费的,蓝色则是可以直接获取对应资料的方块,这次我们写了一个setURI 的函式,让它是onlyOwner,这表示只有合约的拥有人才能使用setURI 的函式,我们现在就试试看吧!
先用一次蓝色按钮「uri」,再按下「call」的按钮去使用它,运作的结果会是下方的ipfs 网址,这个网址就是我们最初在建立ERC1155 时,给定的网址。
接着换用上面橘色按钮「setURI」,在「newuri」栏位随便打上另外一个网址,这个网址会是这个NFT 的新样貌,接着按下「transact」把这笔交易放上链。
过一下子等到交易上链之后,我们再查一次蓝色按钮「uri」,就发现网址已经被改成刚刚输入的新网址了。
这只能知道我们写的setURI 可以正常运作啊!那怎么证明只有智能合约的拥有人才能使用setURI 的函式呢?
这时候就要回到Metamask 去切换成另一个不同的钱包,重新与Remix 连结,这时候再用新钱包去尝试使用setURI 这个函式就会出现以下错误,错误的内容就是打算使用「setURI」这个函式的钱包地址不是这个智能合约的拥有者,所以无法使用。
了解Ownable 大概的运作原理后,未来在开发程式时就会变得更灵活,我们可以自行设计哪些函式是给使用者使用的,哪些函式是我们自己才能使用的,不过毕竟区块链讲求的是去中心化的概念,当我们的专案使用越多onlyOwner 的东西,就表示专案项目的负责人能够私自更动的东西越多,进而可能让用户开始对专案产生是否过度中心化的疑虑。
最后再补充一个我觉得蛮重要的东西, Ownable 之中还有一个「renounceOwnership」的函式,它的功用是释放所有智能合约的拥有者角色,只有合约的拥有者才能执行,执行以后这个智能合约就不再有拥有者了,那些使用到onlyOwner 的函式就没有人能够更动它了,所以如果专案的设定确定都正确未来也不会更动了,可以使用renounceOwnership 来让你的专案更加去中心化。
结语
你可能会发现做到现在连个NFT 的影子都没有,到底在搞什么… 但考量到篇幅问题,我想把NFT 的生产铸造这个最重要的部分放到下一篇文章中,这篇文章主要专注在如何使用名为「OpenZeppelin」的工具箱,以及撰写完程式码后的一些基本编译及发布智能合约的部分。
总之祝大家端午佳节安康,先前填过领取NFT 表单的读者们我会尽快将端午节NFT 发送出去,到时候就会在Polygon 上看到资产了哦!
本文完整程式码连结: https://github.com/ITechNote/DragonBoatNFT
延伸阅读
智能合约开发计划目录列表: https://itechnote.co/sc/
上一篇: 【端午企划】原来NFT 也有客制化的规格标准| 智能合约开发计划#7
最后,谢谢你在百忙之中愿意抽空来花时间来看我的文章,如果还喜欢这些内容的话希望能获得你的追踪及小额赞助支持,让我更有继续写下去的动力,EVM 兼容钱包地址为0xae1dd06d57f582999a9c50b86ba913eecd7155ce。
也欢迎点此连结在其他平台找到我。
下次见噜o((>ω< ))o~
原文连结ITechNote 科技随笔
喜欢我的作品吗?别忘了给予支持与赞赏,让我知道在创作的路上有你陪伴,一起延续这份热忱!
- 来自作者
- 相关推荐