简单的代币开发
代币:
如果从名字上简单地理解代币,它就是一种可以替代通用货币,充当交换媒介的东西。它可以是商城积分、游戏币或筹码。但在区块链中,情况并非如此。Tokens或区块链中的Tokens通常是指流通的加密数字权利证明,如比特币、以太坊等数字货币。令牌
从上面的定义,我们可以知道token的三个要素:
综上所述,简而言之,代币的概念大致是基于区块链发行的加密货币或其他类似的东西。通常大多数人或团队在开发区块链项目时都会考虑发行自己的代币。一开始,我们不得不改造比特币的源代码来发行我们自己的加密货币。但是现在通过以太坊平台,我们可以很方便的开发和发行自己的代币,所以本文将介绍如何基于以太坊开发自己的代币。
本文会用到两个工具,Remix和MetaMask,如果你对这两个工具不太了解,可以参考我的另外两篇文章:
首先,我们使用solidity开发了一个最基本功能的“代币”demo,以了解代币最基本的外观。代码如下:
pragma solidity ^0.4.20;
contract SimpleToken {
// 保存每个地址所拥有的代币数量
mapping (address => uint256) public balanceOf;
// 参数为代币的初始供应量或者说发行数量
constructor (uint256 initSupply) public {
// 创建者拥有所有的代币
balanceOf[msg.sender] = initSupply;
* 转移代币
* @param _to 接收方的账户地址
* @param _value 转移的代币数量
function transfer (address _to, uint256 _value) public {
// 发送方的账户余额需大于等于转移的代币数量
require(balanceOf[msg.sender] >= _value);
// 检查有没有发生溢出,因为数量有可能超过uint256可存储的范围
require(balanceOf[_to] + _value >= balanceOf[_to]);
// 减少发送方账户的代币数量
balanceOf[msg.sender] -= _value;
// 增加接收方账户的代币数量
balanceOf[_to] += _value;
}
1. 代码写好后,在remix上部署合约,首先初始化token供应:
2.查看指定账户拥有的代币数量:
3. 将代币转移到另一个账户地址:
4. 此时账户地址中的代币数量只有100:
ERC-20标准简述
上一节我们实现了一个简单的token,但是由于它的简单性,token极其不完善,比如没有token名称、token符号、无法控制token交易等。
因此,以太坊定义了 ERC20。ERC20 是以太坊定义的统一代币标准。该标准描述了我们在实现代币时必须遵守的协议,例如指定代币名称、总量、实现代币交易功能等,只有实现了该协议的代币才能被以太坊钱包支持。
下图是一个实现ERC20协议的代币:
实际上,ERC20 协议定义了一组标准接口。该协议使在以太坊上开发的任何代币都可以被其他应用程序重用,例如钱包到去中心化交易所,如下所示:
contract ERC20Interface {
// 代币名称
string public constant name = "Token Name";
// 代币符号或者说简写
string public constant symbol = "SYM";
// 代币小数点位数,代币的最小单位, 18表示我们可以拥有 0.0000000000000000001单位个代币
uint8 public constant decimals = 18; // 18 is the most common number of decimal places
// 查询代币的发行总量
function totalSupply() public constant returns (uint);
// 查询地址的代币余额
function balanceOf(address tokenOwner) public constant returns (uint balance);
// 查询spender允许从tokenOwner上花费的代币数量
function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
// 实现代币交易,用于从本账户给某个地址转移代币
function transfer(address to, uint tokens) public returns (bool success);
// 允许spender多次从你的账户取款,并且最多可取tokens个,主要用于某些场景下授权委托其他用户从你的账户上花费代币
function approve(address spender, uint tokens) public returns (bool success);
// 实现代币用户之间的交易,从一个地址转移代币到另一个地址
function transferFrom(address from, address to, uint tokens) public returns (bool success);
// 代币交易时触发的事件,即调用transfer方法时触发
event Transfer(address indexed from, address indexed to, uint tokens);
// 允许其他用户从你的账户上花费代币时触发的事件,即调用approve方法时触发
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
ERC-20标准代币的实现
代码显示如下:
pragma solidity ^0.4.20;
// 定义ERC-20标准接口
contract ERC20Interface {
// 代币名称
string public name;
// 代币符号或者说简写
string public symbol;
// 代币小数点位数,代币的最小单位
uint8 public decimals;
// 代币的发行总量
uint public totalSupply;
// 实现代币交易,用于给某个地址转移代币
function transfer(address to, uint tokens) public returns (bool success);
// 实现代币用户之间的交易,从一个地址转移代币到另一个地址
function transferFrom(address from, address to, uint tokens) public returns (bool success);
// 允许spender多次从你的账户取款,并且最多可取tokens个,主要用于某些场景下授权委托其他用户从你的账户上花费代币
function approve(address spender, uint tokens) public returns (bool success);
// 查询spender允许从tokenOwner上花费的代币数量
function allowance(address tokenOwner, address spender) public view returns (uint remaining);
// 代币交易时触发的事件,即调用transfer方法时触发
event Transfer(address indexed from, address indexed to, uint tokens);
// 允许其他用户从你的账户上花费代币时触发的事件,即调用approve方法时触发
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
// 实现ERC-20标准接口
contract ERC20Impl is ERC20Interface {
// 存储每个地址的余额(因为是public的所以会自动生成balanceOf方法)
mapping (address => uint256) public balanceOf;
// 存储每个地址可操作的地址及其可操作的金额
mapping (address => mapping (address => uint256)) internal allowed;
// 初始化属性
constructor() public {
name = "Test Token";
symbol = "TEST";
decimals = 18;
totalSupply = 100000000;
// 初始化该代币的账户会拥有所有的代币
balanceOf[msg.sender] = totalSupply;
function transfer(address to, uint tokens) public returns (bool success) {
// 检验接收者地址是否合法
require(to != address(0));
// 检验发送者账户余额是否足够
require(balanceOf[msg.sender] >= tokens);
// 检验是否会发生溢出
require(balanceOf[to] + tokens >= balanceOf[to]);
// 扣除发送者账户余额
balanceOf[msg.sender] -= tokens;
// 增加接收者账户余额
balanceOf[to] += tokens;
// 触发相应的事件
emit Transfer(msg.sender, to, tokens);
success = true;
function transferFrom(address from, address to, uint tokens) public returns (bool success) {
// 检验地址是否合法
require(to != address(0) && from != address(0));
// 检验发送者账户余额是否足够
require(balanceOf[from] >= tokens);
// 检验操作的金额是否是被允许的
require(allowed[from][msg.sender] = balanceOf[to]);
// 扣除发送者账户余额
balanceOf[from] -= tokens;
// 增加接收者账户余额
balanceOf[to] += tokens;
// 触发相应的事件
emit Transfer(from, to, tokens);
success = true;
function approve(address spender, uint tokens) public returns (bool success) {
allowed[msg.sender][spender] = tokens;
// 触发相应的事件
emit Approval(msg.sender, spender, tokens);
success = true;
function allowance(address tokenOwner, address spender) public view returns (uint remaining) {
return allowed[tokenOwner][spender];
}
将上述代码复制到 Remix 并编译合约代码:
部署合约:
部署成功:
测试 balanceOf 方法:
测试传输方法:
在 Remix 上测试了基本方法后,我们通过 MetaMask 在以太坊测试网络上发行我们的代币。打开MetaMask,选择Ropsten test network,如下:
注意:如果你没有余额,请点击DEPOSIT按钮,然后点击GET ETHER按钮以太坊发行量,你会进入一个网站,在网站上点击request 1 ether from faucet,你可以给你发送一些ether进行测试网络:
然后在 Remix IDE 上刷新它。这时候Remix会自动选择对应的测试网络。注意MetaMask和Remix需要在同一个浏览器上,Environment和Account和MetaMask保持一致,如下:
点击Deploy后,MetaMask会弹出一个交易确认框,点击CONFIRM:
合约部署交易确认后,复制合约地址:
打开Metamask界面,打开菜单(Menu),点击ADD TOKEN:
出现如下对话框,选择Custom Token,然后将合约地址粘贴到:
单击添加令牌:
这时候可以看到我们在MetaMask中创建的token,如下:
接下来我们测试一下代币转账功能,选择我们刚刚部署的代币,点击发送:
填写转账相关信息:
确认转账:
成功后会生成对应的交易记录:
这样,我们就完成了代币的创建和部署(官网和测试网部署方式是一样的),现在可以在Etherscan上查看刚刚发行的代币了:
点击合约地址查看代币详情:
关于发行总量为0的问题
上一节我们已经在以太坊上成功发行了自己的代币,但是很多同学应该也提出了一个问题,为什么代币中发行了代币数量,但发行代币数量还是0?其实这也是新手在开发代币时可能会遇到的一个坑。我们之所以看到总发行量为0,是因为代币总发行量的整数位不是totalSupply的值,而是totalSupply除以10的小数次方。
例如,如果我们将小数设置为 8,那么我们需要将代币的总供应量 (totalSupply) 除以 100000000 以得到它的整数。上节合约代码中设置的decimals值为18,即代币使用的小数位为18,totalSupply的值为1亿。自然计算出来是小于1的小数,还是比较小的小数。MetaMask 只显示小数点后 3 位,因此我们认为发行的代币总量为 0。
既然您知道是什么原因造成的,那么解决它就很容易了。修改合约的constructor token如下:
// 初始化属性
constructor() public {
decimals = 18;
totalSupply = 100000000 * 10 ** uint256(decimals);
name = "Test Token";
symbol = "TEST";
// 初始化该代币的账户会拥有所有的代币
balanceOf[msg.sender] = totalSupply;
}
修改完成后,我们仍然按照上一节所述的流程发行代币并将其添加到 MetaMask 钱包中。这时候token的总发行量应该是我们期望的值,如下:
我们也可以尝试使用代币转账:
转账成功以太坊发行量,正常扣除账户余额:
另一个账户也正常收到了这100个代币:
然后我们去检查令牌详细信息:
极客公园 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:以太坊发行量 如何在以太坊上发行自己的代币
喜欢 (0) |