Web 3 学习笔记 3 | Fungible Token 同质化代币合约开发学习
免责声明
本文所述行为仅限于技术设计和本地模拟部署,不涉及链上操作。所有内容仅供学习和研究之用,读者在进行相关操作时,请遵循所在地区的法律法规,确保操作合法合规。
在之前的学习中,我们了解了同质化代币是 Web3 应用中的重要一部分,今天我们将学习如何使用 Solidity 开发并构建一个简单的同质化代币合约。
构建合约
首先是代币合约骨架的构建,以下是构建合约所需要的几个重要步骤:
指定合约使用的编译器版本和对合约名称进行定义
定义一个变量来表示代币的发行者
定义一个构造函数,帮助我们完成合约的初始化
创建合约
首先,我们需要在代码中指定合约的编译器版本,这样可以确保后续代码能够正确编译。以下是指定版本的示例:
pragma solidity 0.8.17;
这里我们选择了 0.8.17 版本的编译器。值得注意的是,版本号只能是 0.8.17,或者使用 ^0.8.17
表示版本需大于等于 0.8.17,但小于 0.9.0。
指定版本之后,我们创建合约:
pragma solidity 0.8.17;
contract NxToken { }
定义代币发行者
对于代币合约,我们通常需要一个发行者,使用 address
来表示合约的归属人。我们可以在合约中定义一个私有变量 owner
:
pragma solidity 0.8.17;
contract NxToken {
address private owner;
}
发行者就是合约的部署者,使用 Solidity 的全局变量 msg.sender
来获取部署者地址。我们将在构造函数中初始化 owner
。
pragma solidity 0.8.17;
contract NxToken {
address private owner;
constructor() {
owner = msg.sender;
}
}
定义重要变量
在完成合约框架后,接下来需要完善合约的数据结构。首先,我们定义 balances
映射,跟踪每个用户地址对应的代币余额。我们可以使用 mapping
来存储用户地址和代币余额:
pragma solidity 0.8.17;
contract NxToken {
address private owner;
mapping (address => uint256) private balances;
constructor() {
owner = msg.sender;
}
}
为了简化计算,我们还可以定义一个变量 totalSupply
,用于存储已发行代币的总量:
pragma solidity 0.8.17;
contract NxToken {
address private owner;
mapping (address => uint256) private balances;
uint256 public totalSupply;
constructor() {
owner = msg.sender;
}
}
代币铸造
我们将实现代币合约的第一个功能:铸造代币。首先定义 mint
函数,该函数接受两个参数:接收代币的地址 recipient
和铸造的代币数额 amount
。
pragma solidity 0.8.17;
contract NxToken {
address private owner;
mapping (address => uint256) private balances;
uint256 public totalSupply;
constructor() {
owner = msg.sender;
}
function mint(address recipient, uint256 amount) public { }
}
在铸造代币之前,我们需要检查函数调用者是否为代币发行者,确保只有发行者可以铸造代币:
pragma solidity 0.8.17;
contract NxToken {
address private owner;
mapping (address => uint256) private balances;
uint256 public totalSupply;
constructor() {
owner = msg.sender;
}
function mint(address recipient, uint256 amount) public {
require(msg.sender == owner, "Only the owner can mint tokens");
}
}
铸造代币时,我们需要指定接收代币的账户地址和代币数量,并更新相关的余额和总供应量:
pragma solidity 0.8.17;
contract NxToken {
address private owner;
mapping (address => uint256) private balances;
uint256 public totalSupply;
constructor() {
owner = msg.sender;
}
function mint(address recipient, uint256 amount) public {
require(msg.sender == owner, "Only the owner can mint tokens");
balances[recipient] += amount;
totalSupply += amount;
}
}
完善功能
查询余额
为了让用户能够查看自己或其他地址的余额,我们需要实现 balanceOf
函数。
pragma solidity 0.8.17;
contract NxToken {
address private owner;
mapping (address => uint256) private balances;
uint256 public totalSupply;
constructor() {
owner = msg.sender;
}
function mint(address recipient, uint256 amount) public {
require(msg.sender == owner, "Only the owner can mint tokens");
balances[recipient] += amount;
totalSupply += amount;
}
function balanceOf(address account) public view returns (uint256) {
return balances[account];
}
}
实现转账
转账功能是代币系统中非常关键的一部分。转账过程包括以下几个步骤:
检查转账者的余额是否足够;
获取转账者和接收者的余额;
更新转账者的余额;
更新接收者的余额。
实现 transfer
函数如下:
function transfer(address recipient, uint256 amount) public returns (bool) {
require(amount <= balances[msg.sender], "Not enough balance.");
balances[msg.sender] -= amount;
balances[recipient] += amount;
return true;
}
编译和部署
最终,得到完整的合约内容如下:
pragma solidity 0.8.17;
contract NxToken {
mapping (address => uint256) private balances;
uint256 public totalSupply;
address private owner;
constructor() {
owner = msg.sender;
}
function mint(address recipient, uint256 amount) public {
require(msg.sender == owner, "Only the owner can mint tokens");
balances[recipient] += amount;
totalSupply += amount;
}
function balanceOf(address account) public view returns (uint256) {
return balances[account];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
require(amount <= balances[msg.sender], "Not enough balance.");
balances[msg.sender] -= amount;
balances[recipient] += amount;
return true;
}
}
我们可以尝试在在线 IDE 中进行编译运行
如下图所示,我们创建一个 .sol
文件,并将代码复制粘贴过来
然后在旁边的 Solidity Complier 中,选取合适的编译器版本,点击编译
在 DEPLOY 页面中选择 Remix VM,然后点击 Deploy,就可以在虚拟环境中进行部署,可以看到,我们用来部署的虚拟地址的账户余额不再是一开始的 100,因为每次链上的行为都需要支付 gas 费才能在链上持久化,此处只是模拟的效果
窗口下方可以对每个函数模拟调用,并实时获得结果,如图所示:
总结
我们学习了如何使用 Solidity 创建一个简单的同质化代币合约。我们从基础的合约结构开始,逐步实现了代币的铸造、余额查询以及转账功能。在实际操作中,我们使用了 mapping
来存储每个地址的代币余额,并且通过构造函数和权限控制确保了合约的安全性。
希望这篇分享能为你带来启发!如果你有任何问题或建议,欢迎在评论区留言,与我共同交流探讨。