智能合约开发初探
智能合约
上一篇讲了如何在本地搭建以太坊本地私链,这次就聊聊如何在自己搭建的私链上部署合约以及运行合约。本地搭建合约的好处在于,一方面可以自定义挖矿难度以及控制挖矿情况,另一方面实际上是可以对部署的合约进行断点调试,熟悉合约执行的每一步,观察存储的数据情况。
主流协议
由于有了openzeppelin的存在,写合约容易了很多,只需要选择好相应的协议,直接复用其实现就好,真可谓无脑发币和 NFT,难怪近期的 NFT 项目越来越多。
ERC20
最为使用最广泛的 token 合约,仅需几行代码就可以快速发币,以下就是最基础的发币代码。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
constructor(uint256 initialSupply) ERC20("MyToken", "MTK") {
_mint(msg.sender, initialSupply);
}
}
OpenZeppelin 的 ERC20 协议以包含了以下接口:
- totalSupply:规定了代币的总量,外部可以通过调用这个函数来获得代币总量是多少
- balanceOf:获取某地址的代币余额
- transfer:调用 transfer 函数将自己的 token 转账给_to 地址,_value 为转账个数 *approve:批准_spender 账户从自己的账户转移_value 个 token。可以分多次转移
- transferFrom:用于第三方(_spender)从被授权的账户转账到目标账户
- allowance:返回_spender 还能提取 token 的个数
属实非常贴心,看上去只需要确定名字,就可以上手。而这里的 allowance 概念有点意思,他是允许第三方从账上划转 token,借这个功能就可以做一个 swap。另外要注意的一点是,不要直接往代币合约地址直接转账(transfer)。透过合约代码也可以发现,ERC20 在链上维护了一个 address<->Balance 的 Map 结构,记录了每个地址的余额情况。
ERC721
最近炒得很火的 NFT 基本上都是基于 ERC721 协议实现的,ERC721 和 ERC20 不同的点在于,每一个 token 都是非同质的,即独一无二的,因此在链上的储存信息是不同的,ERC721 记录的虽然也是维护了一个 Map 结构,但这里是维护 token<->address 的信息,记录每个 token 的 owner。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyToken is ERC721, Ownable {
constructor() ERC721("MyToken", "MTK") {}
function safeMint(address to, uint256 tokenId) public onlyOwner {
_safeMint(to, tokenId);
}
}
最关键的部分即mint
操作,mint
完成了创建出一个 NFT 给对应的 address。上述只是一个简单的例子,ERC721 有很多扩展,常规的 NFT 都是使用ERC721URIStorage
储存 NFT 的baseURI
,在这里储存了每个 NFT 不同的 metadata。这一块可以后面细细讲解。
开发工具
在常规的开发中,remix 算是比较好用的 Web IDE,更适合部署合约并调试合约,之前也试用过Black-IDE,从编辑效果上还是 VS Code 会更加的好用。部署合约的工具可以选择使用 Truffle 或 HardHat。Truffle 里有 box 这种概念,能够提供一些常规的模板。VS Code 一定要装一下 Tabnine 和 Copilot,由于合约大部分代码都是相似的,利用自动补全,基本上可以无脑写出很多想要的代码= =。
Remix
remix 使用在线的更方便部署到 JVM 中进行模拟测试,另一方面,使用Inject Web3
的方式直接吊起 Metamask 进行操作授权。
另一方面,可以在 VS Code 可以装ethereum-remix插件,也可以做到类似 Web IDE 的效果。
Truffle
Truffle 算是一个开发合约的脚手架,通过这个工具可以初始化一个合约项目,结合 VS Code 上的Truffle插件,可以快速的部署在本地私链或公链。
truffle 还有一个工具非常好用——truffle dashboard,通过这种方式可以在浏览器里吊起 Metamask 进行支付授权。可以参考以下的配置truffle-config.js
,development 是本地私链的基本配置,需要使用下面的 dashboard 配置,从体验上可以认为是一个类似 Remix Inject Web3 的工具,通过这种方式,避免需要解锁钱包。
module.exports = {
// Uncommenting the defaults below
// provides for an easier quick-start with Ganache.
// You can also follow this format for other networks.
// See details at: https://trufflesuite.com/docs/truffle/reference/configuration
// on how to specify configuration options!
//
networks: {
development: {
host: "127.0.0.1",
port: 8545,
network_id: "*",
},
"truffle-dashboard": {
url: "http://localhost:24012/rpc", // where truffle dashboard run
network_id: "77895176",
},
},
};
部署合约
刚才介绍了很多合约的背景知识和一些工具的使用,现在就可以尝试去部署一个
合约
。部署合约的方式有多种,可以通过 remix 也可以通过 truffle 的方式,另外也可以通过truffle migration
的方式,后者更像是多个合约的部署。
- 通过 truffle for VS code 部署单个合约
- 通过 remix for VS Code 部署单个合约
这里使用了 dashboard 而不是直接的 development 地址进行部署,在http://localhost:24012/
就能看到
部署操作发起的请求。
合约交互
部署完合约就可以进行交互了,可以使用 VS Code 里的
remix 进行交互,也可以使用 Web IDE 进行交互,
还有一种方法是使用web3.py
或web3.js
进行应用层的调用。这里就暂时先不展开了,之后会进行一些案例的分析。