本文目标php
经过逐步的指导和截图举证,一步步带领一个技术小白完成一个数字货币(通证,代币,TOKEN)的发布演示和上线交易。git
环境前置条件github
参考开发实战|3步教你在以太坊上开一家宠物店(附流程+代码),已在本地WIDOWS环境完成MetaMask轻钱包客户端的安装和配置;做者建议最好遵循从头开始的课程学习顺序。不过若是你想半途插入实操学习,问题也不大,遇到障碍时反向找对应文章的指导内容便可完成。json
(识别下图二维码可回看视频)浏览器
技术收获安全
从本实践中,你能够学习到:微信
ERC20 Token的定义和实践网络
使用Remix Solidity IDE编写智能合约和编译调试app
使用MetaMask完成钱包帐户查看函数
使用网页钱包完成代币交易演示
定义
ERC20合约是在2015年11月在EIP(https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md)上提出的一个合约标准,代币定义的一个标准。
Token表明数字资产,具备价值,可是并非都符合特定的规范。
基于ERC20的货币更容易互换,而且可以在Dapps上相同的工做。
新的标准可让token更兼容,容许其余功能,包括投票标记化。操做更像一个投票操做,Token的持有人能够彻底控制资产,遵照ERC20的token能够跟踪任何人在任什么时候间拥有多少token。基于eth合约的子货币,因此容易实施。
ERC20 Token接口说明
方法
注意:调用者必须处理返回false的returns (bool success).调用者绝对不能假设返回false的状况不存在。
name
返回这个令牌的名字,好比"MyToken".
可选 - 这种方法能够用来提升可用性,但接口和其余契约不能期望这些值存在。
function name() constant returns (string name)
symbol
返回令牌的符号,好比HIX.
可选 - 这种方法能够用来提升可用性,但接口和其余契约不能期望这些值存在。
function symbol() constant returns (string symbol)
decimals
返回token使用的小数点后几位, 好比 8,表示分配token数量为100000000
可选 - 这种方法能够用来提升可用性,但接口和其余契约不能期望这些值存在。
function decimals() constant returns (uint8 decimals)
totalSupply
返回token的总供应量。
function totalSupply() constant returns (uint256 totalSupply)
balanceOf
返回地址是_owner的帐户的帐户余额。
function balanceOf(address _owner) constant returns (uint256 balance)
transfer
转移_value的token数量到的地址_to,而且必须触发Transfer事件。 若是_from账户余额没有足够的令牌来支出,该函数应该被throw。
建立新令牌的令牌合同应该在建立令牌时将_from地址设置为0x0触发传输事件。
注意 0值的传输必须被视为正常传输并触发传输事件。
function transfer(address _to, uint256 _value) returns (bool success)
transferFrom
从地址_from发送数量为_value的token到地址_to,必须触发Transfer事件。
transferFrom方法用于提取工做流,容许合同代您转移token。这能够用于例如容许合约代您转让代币和/或以子货币收取费用。除了_from账户已经经过某种机制故意地受权消息的发送者以外,该函数应该throw。
注意 0值的传输必须被视为正常传输并触发传输事件。
function transferFrom(address _from, address _to, uint256 _value) returns (bool success)
approve
容许_spender屡次取回您的账户,最高达_value金额。 若是再次调用此函数,它将以_value覆盖当前的余量。
注意:为了阻止向量攻击,客户端须要确认以这样的方式建立用户接口,即将它们设置为0,而后将其设置为同一个花费者的另外一个值。虽然合同自己不该该强制执行,容许向后兼容之前部署的合同兼容性。
function approve(address _spender, uint256 _value) returns (bool success)
allowance
返回_spender仍然被容许从_owner提取的金额。
function allowance(address _owner, address _spender) constant returns (uint256 remaining)
Events
Transfer
当token被转移(包括0值),必须被触发。
event Transfer(address indexed _from, address indexed _to, uint256 _value)
Approval
当任何成功调用approve(address _spender, uint256 _value)后,必须被触发。
event Approval(address indexed _owner, address indexed _spender, uint256 _value)
[官网接口说明点击查看],(https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md)
接口文件ERC20Interface.sol以下:
contract ERC20Interface { string public constant name = "Token Name"; string public constant symbol = "SYM"; uint8 public constant decimals = 18; // 18 is the most common number of decimal places // 0.0000000000000000001 个代币 function totalSupply() public constant returns (uint); function balanceOf(address tokenOwner) public constant returns (uint balance); function allowance(address tokenOwner, address spender) public constant returns (uint remaining); function approve(address spender, uint tokens) public returns (bool success); function transfer(address to, uint tokens) public returns (bool success); function transferFrom(address from, address to, uint tokens) public returns (bool success); event Transfer(address indexed from, address indexed to, uint tokens); event Approval(address indexed tokenOwner, address indexed spender, uint tokens); }
合约文件TokenERC20.sol以下:
pragma solidity ^0.4.16; interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; } contract TokenERC20 { 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 TokenERC20(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; } } /** * 销毁建立者帐户中指定个代币 */ 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; } }
函数的功能参考函数的说明描述和代码自解释。
MetaMask钱包联网
前置条件:做者假设学习者已完成MetaMask的安装和配置。尚未完成的,参考开发实战|3步教你在以太坊上开一家宠物店(附流程+代码),安装 MetaMask和配置区块链网络”,在本地WIDOWS环境完成MetaMask轻钱包客户端的安装和配置。
打开MetaMask钱包,点击左上角的“Ropsten Test Network” 链接成功。
链接成功
查看存量的帐号Account 1,其中ETH余额显示为0。
存量帐号Account 1余额为0
点击“Copy Address to Clipboard”,记录Account 1钱包地址为
0xD1F7922e8b78cBEB182250753ade8379d1E09949
点击MetaMask右上角环形头像的菜单“Create Account”, 建立一个新钱包帐号Account 8,
新增帐号成功
记录Account 8的钱包地址为
0x3D7DfB80E71096F2c4Ee63C42C4D849F2CBBE363
点击Account 8的"BUY"按钮,能够从“Ropsten Test Network” 免费获取一些测试ETH。
跳转到BUY ETH页面
点击按钮“ROPSTEN TEST FAUCET”能够看到赠送页面
点击绿色按钮,等待10秒以上,成功的话每次能够获取1个测试ETH。
故障排查
赠送失败
做者操做时,出现错误。从提示看,是因为用户交易拒绝。等10秒后再点击该绿色按钮则未有错误提示了。缘由不明,多是操做频繁致使。
屡次点击,偶尔出错,小编一共从这个测试网站获取了5个测试ETH用于做为发币的GAS燃料。
获取测试ETH
Remix Solidity IDE调试环境介绍
代码编写和编译
咱们以“Hello World”智能合约为例,参考下图可完成编译和语法错误发现。
编译环境使用方法
合约建立
参考附图描述,在配置号MetaMask帐号和网络链接的状况下,确保帐户有虚拟ETH用于合约建立花销。最后点击“Create”按钮能够完成合约建立。点击输出区的网页连接(https://ropsten.etherscan.io/tx/0x9ef5b97580cf5350e9deca8f8472117df3983f1bcd0272b15c490528c811f3f8)能够查看合约的详细状况。
支付合约花销
合约执行
参考附件路径图,点击RUN按钮能够执行一次合约。点击下方的“Say”按钮,能够看到合约输出。在调试输出窗口能够看到“call to hello.say”的运行提示。
合约执行
总结
因此说,没有Ubuntu+Ganache等,直接在WINDOWS环境,也可使用Remix+MetaMask+Ropsten Test Network组合完成一套完整的以太坊测试环境。
编译ERC20智能合约
CHROME浏览器打开Remix Solidity IDE环境(http://remix.ethereum.org/#optimize=false&version=soljson-v0.4.21+commit.dfe3193c.js),打开以前编写的“TokenERC20.sol”智能合约,而后点击右侧的“start to compile”按钮。能够看到,除了一些Warning提示外,智能合约编译成功。
编译操做
运行ERC20智能合约
运行页面
切换到"RUN"页面,Environment选择“Injected Web3”, Account自动更新为MetaMask的Account 8帐号。“Create”按钮前按照发币数量(本次发1个亿),代币名称,代币符号填写为100000000,"ColorBay","CB"。
点击"Create"按钮,会弹出一个交易确认框,设置合理的Gas Price,但要确保Max Transaction Fee不会超过Account 8的ETH总数,点“SUBMIT”按钮。
智能合约部署
部署成功的话,Account8 会产生一条交易记录,显示状态为“Contract Published”,表示部署成功了。
部署成功
说明:有时点击帐号,会出现“Retry with a higher gas price here”的提示,通常状况下再等待10秒看看可否交易成功。万一仍是不成的话,可考虑该Gas Price大点。
部署确认中
MetaMask加载TOKEN
点击Account 8的交易记录(https://ropsten.etherscan.io/tx/0x3dd6f5d88f54dee71c4a3d9f5082e270b01cf3f26e1d3960d2517675745fa80e),能够跳转智能合约部署信息显示页面:
部署成功
获取智能合约地址为0x5eeec41dc08d7caece17c4a349635934637036f1(https://ropsten.etherscan.io/address/0x5eeec41dc08d7caece17c4a349635934637036f1),点击可查看该交易详情。
点击MetaMask的Account 8帐号的TOKENS页面的“ADD TOKEN”按钮,把代币智能合约地址Token Contract Address为0x5eeec41dc08d7caece17c4a349635934637036f1,代币标识符Token Symbol为CB,则能够建立你的代币了。
代币建立成功,一共有1亿个CB币了。此时,点击100000000的代币位置,跳转到代币查询页面(https://ropsten.etherscan.io/token/0x5eeec41dc08d7caece17c4a349635934637036f1), 能够在etherscan网站看到帐户的持币数量了。
1亿
TOKEN信息
截止做者发稿时,以太坊的价格为2559元/个,而你有1亿个CB币,是否是快要走上人生巅峰了呢?哈哈,作个梦而已。真正的区块链应用,要能有生态,能为人类社会创造价值,而不是讲故事,割韭菜!
因为MetaMask插件没有提供代币交易功能,同时考虑到不少人并无以太坊钱包或是被以太坊钱包网络同步问题折磨,今天我用网页钱包(https://www.myetherwallet.com/)来说解代币交易。
1. 进入网页钱包地址 (https://www.myetherwallet.com/#send-transaction)
第一次进入有一些安全提示须要用户确认。
2. 进入以后,按照下图进行设置
网络配置
3,增长自定义代币
填写地址Token Contract 为0x5eeec41dc08d7caece17c4a349635934637036f1和其余信息,点击保存按钮。
增长自定义TOKEN
配置TOKEN合约地址和代币符号
配置成功的界面以下:
【说明】若是不成功,则提示为“Not a valid ERC-20 token CB”,则多是代币信息填写不正确或者右上角的网络选择错误,没有选择“Network Ropston(infura.com)”选项引发。
4.转帐给Account 1
填写Account 1的地址“0xD1F7922e8b78cBEB182250753ade8379d1E09949”到“发送至地址”输入框,
选择CB,不是ETH
转帐确认
交易确认
交易提示
查看帐户余额,Account 8减小800万个CB币,而Account 1则增长了800万个CB币。
Account 8
Account 1
转帐交易成功了!
做为一个古典投资人,用45分钟完成了TOKEN上线和交易,用4个小时整理了这篇文章。学习就是这么简单,只要你对新技术保持饥饿感,高龄开发转型区块链也不是难事!
本文是站在巨人的肩膀上的操做实践,感谢如下文章做者的帮助:
一步步教你建立本身的数字货币(代币)进行ICO(https://blog.csdn.net/xilibi2003/article/details/79131924)
代币标准(https://theethereum.wiki/w/index.php/ERC20_Token_Standard)
Create your own crypto-currency with ethereum
本文来源:简书
做者:笔名辉哥
课程推荐
课程主题:揭开神秘的数字货币交易——2节课创建一个数字货币交易所
识别下图二维码添加微信,回复“006”便可报名。
HiBlock区块链社区更多活动点击**“阅读原文”**查看