第一次发币成功之后,写的这篇文章。
参考链接:https://yq.aliyun.com/articles/568701
此文章是我按照参考链接的步骤做的,但是其中遇到的一些问题,在我的文章中做了补充。并做了一些错别字的修改。
现在默认代币合约已经编写完毕,因为合约目前我也不会写。等以后学会了再考虑出相关博客。此教程比较初级,因为我也刚入门,但是经过我的验证,确实发币成功。
完成代币合约编写后,可以将合约发布到Etherscan的测试链上(公链需要购买ether,而且速度较慢,建议开发在测试上进行),合约部署方式如下:
先贴上我的代币合约代码:
pragma solidity ^0.4.19; interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; } contract TC { string public name; string public symbol; uint8 public decimals = 18; // decimals 可以有的小数点个数,最小的代币单位。18 是建议的默认值 uint256 public totalSupply; // 用mapping保存每个地址对应的余额 mapping (address => uint256) public balanceOf; // 存储对账号的控制 mapping (address => mapping (address => uint256)) public allowance; // 事件,用来通知客户端交易发生 event Transfer(address indexed from, address indexed to, uint256 value); // 事件,用来通知客户端代币被消费 event Burn(address indexed from, uint256 value); /** * 初始化构造 */ function TC(uint256 initialSupply, string tokenName, string tokenSymbol) public { totalSupply = initialSupply * 10 ** uint256(decimals); // 供应的份额,份额跟最小的代币单位有关,份额 = 币数 * 10 ** decimals。 balanceOf[msg.sender] = totalSupply; // 创建者拥有所有的代币 name = tokenName; // 代币名称 symbol = tokenSymbol; // 代币符号 } /** * 代币交易转移的内部实现 */ function _transfer(address _from, address _to, uint _value) internal { // 确保目标地址不为0x0,因为0x0地址代表销毁 require(_to != 0x0); // 检查发送者余额 require(balanceOf[_from] >= _value); // 确保转移为正数个 require(balanceOf[_to] + _value > balanceOf[_to]); // 以下用来检查交易, uint previousBalances = balanceOf[_from] + balanceOf[_to]; // Subtract from the sender balanceOf[_from] -= _value; // Add the same to the recipient balanceOf[_to] += _value; Transfer(_from, _to, _value); // 用assert来检查代码逻辑。 assert(balanceOf[_from] + balanceOf[_to] == previousBalances); } /** * 代币交易转移 * 从自己(创建交易者)账号发送`_value`个代币到 `_to`账号 * * @param _to 接收者地址 * @param _value 转移数额 */ function transfer(address _to, uint256 _value) public { _transfer(msg.sender, _to, _value); } /** * 账号之间代币交易转移 * @param _from 发送者地址 * @param _to 接收者地址 * @param _value 转移数额 */ function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { require(_value <= allowance[_from][msg.sender]); // Check allowance allowance[_from][msg.sender] -= _value; _transfer(_from, _to, _value); return true; } /** * 设置某个地址(合约)可以创建交易者名义花费的代币数。 * * 允许发送者`_spender` 花费不多于 `_value` 个代币 * * @param _spender The address authorized to spend * @param _value the max amount they can spend */ function approve(address _spender, uint256 _value) public returns (bool success) { allowance[msg.sender][_spender] = _value; return true; } /** * 设置允许一个地址(合约)以我(创建交易者)的名义可最多花费的代币数。 * * @param _spender 被授权的地址(合约) * @param _value 最大可花费代币数 * @param _extraData 发送给合约的附加数据 */ function approveAndCall(address _spender, uint256 _value, bytes _extraData) public returns (bool success) { tokenRecipient spender = tokenRecipient(_spender); if (approve(_spender, _value)) { // 通知合约 spender.receiveApproval(msg.sender, _value, this, _extraData); return true; } } /** * 销毁我(创建交易者)账户中指定个代币 */ function burn(uint256 _value) public returns (bool success) { require(balanceOf[msg.sender] >= _value); // Check if the sender has enough balanceOf[msg.sender] -= _value; // Subtract from the sender totalSupply -= _value; // Updates totalSupply Burn(msg.sender, _value); return true; } /** * 销毁用户账户中指定个代币 * * Remove `_value` tokens from the system irreversibly on behalf of `_from`. * * @param _from the address of the sender * @param _value the amount of money to burn */ function burnFrom(address _from, uint256 _value) public returns (bool success) { require(balanceOf[_from] >= _value); // Check if the targeted balance is enough require(_value <= allowance[_from][msg.sender]); // Check allowance balanceOf[_from] -= _value; // Subtract from the targeted balance allowance[_from][msg.sender] -= _value; // Subtract from the sender's allowance totalSupply -= _value; // Update totalSupply Burn(_from, _value); return true; } }
打开remix浏览器:
打开后样子如下:
点击新建按钮,将编辑好的合约复制到IDE中:
复制完成后,IDE的左边会自动校验你的合约的编写是否准确,有错误会提示,警告可以忽略。
在这里,我遇到一个报错:(如果没遇到这个错误,可跳过这部分)
mock compiler: source not found截图如下:
原因:编译器版本选择错误,经过如下操作可以解决这个报错:
setting --> Select new compiler version --> 选择一个大于你在合约首行声明的版本
选择后过一会儿,编译成功,然后报错消失,出现的是一些警告,可以忽略。
现在就可以发布了,但是发布需要以太坊,插入MetaMask讲解,顺便获取测试链的以太坊:
MetaMask使用(这个插件的安装,如果能翻墙,那么直接到谷歌商店里安装,如果不能,那么就百度搜索“谷歌浏览器插件”,然后会出来很多可以下载插件的网站,下载好之后想办法安装好插件,安装插件的方式如果不会,就百度吧)
由于我们是在以太坊测试链上发行合约,还是需要ether的,只不过可以免费获得,为了发行合约,我们需要测试链账户,下面我们将插入使用MetaMaskchrome插件来链接创建账户:
安装好后,在浏览器右上角会出现图标,点击图标,一直点击到下图,填写你的密码,进入后就创建好了一个MetaMask钱包,MetaMask会为用户创建12个英文助记词,一定要保存好这些助记词,一定要保存好这些助记词,一定要保存好这些助记词,在其他钱包导入这个新创建的账户的时候有可能需要这些助记词。具体细节可以参考这篇文章。
创建好后,会给你默认一个账号:
由于我们是要基于以太坊测试链发行代币,所以我们选择测试链:
此时,我们发现我们的账户中没有ether,依次按照如下步骤获取:
这时候会打开网页,点击图标(建议点一两次就ok,每次会给你的账户放1个ether,部署合约1个就已经搓搓有余。)(我在操作的时候,就没有成功打开点击BUY之后的页面,应该是因为没有翻墙,然后我是让同事给我的地址打了一些以太坊)。
一会你就会发现你们账户有金额;
准备工作终于做完了,现在我们开始部署代币合约,这时候点击IDE右侧横栏中的run,按照1到3确认信息,并在4中编写你要发行的代币的信息,依次是100000000,"GaoTeB","GTB"(发行总量,发行币全称,发行币简称),4步确认不误后点击create按钮发布代币合约带测试链中。(我操作的时候,图中5的按钮变成了deploy)
点击后,会弹出对话框:(这里是测试链,所以可以不用关注手续费的问题,但是在正式链上,一定要关注一下GasPrice,如果手续费过低没有旷工帮你打包,就尴尬了,同事之前发币的时候遇到过,然后过了十几个小时之后发币失败,手续费又退回来了,虽然不会损失以太坊,但是很耽误时间,这一点大家需要注意一下。)
点击submit后,如果不报错,此时,会出现你的合约信息:
点击合约会打开页面,你可以看到正在创建中:
过一会,你就会看到(上面的页面,得刷新才能看到成功没,我第一次的时候,没刷新,看着那个圈转了一个小时...):
那么你就基本已经发行成功你的代币了!
怎么在我们的账户下看呢?
下面我们使用MetaMask工具查看,依次点击:
将刚才打开的页面中的信息填入MetaMask中,
这时候,我们就能看到啦:
下面我们来转账一回试试:
代币交易
MetaMask插件没有提供代币交易功能,同时考虑到很多人并没有以太坊钱包或是被以太坊钱包网络同步问题折磨,今天我用网页钱包来讲解代币交易。
初次进入会有一些列的确认信息,一顿点击,来到这个页面,选择与MetaMask同一个网络链(以太坊测试链):
然后按下图点击:
点击链接后,这个页面就会和你的MetaMask链接上,你会发现你的账户信息就会出现在页面上。
此时,你的Token信息并没有出现在这里,需要你手动添加:
点击添加,将你的Token信息填入这里:
此时,你会发现:
然后开始代币交易,我们尝试转账给别的账户,填写好信息后依次点击:
此时,你将会发现,你的账户的Token已经减少了。