本文基于moac公链,使用moac网页版钱包发行ERC-20 token。
环境:
公链:MOAC-pangu0.8.2。
节点版本:MOAC-pangu0.8.2-windows.exe。
操作系统:Windows 10家庭版。
一、安装并启动moac本地节点
1.1 安装moac节点请参考文档《MOAC Windows版系统安装教程》:
https://mp.weixin.qq.com/s/6ZnFYM6BJGZcjuVfu64Aog
1.2 启动moac节点
打开命令终端(cmd),转到墨客当前目录,在命令行中执行:
D:\moacPangu0.8.2-win>moac --rpc --rpccorsdomain "http://wallet.moac.io
"
备注:
--rpc 启动RPC服务,本机访问节点
--rpccorsdomain 启动RPC服务,非本机访问节点
"http://wallet.moac.io
" moac在线钱包网址,会自动连接到本机启动的moac节点并显示已有账号,如果本机节点没有启动,会显示以下提示信息。
启动正常,会显示以下账号信息。确保其中一个账号有足够的moac以进行智能合约部署。
二、编写并编译智能合约
环境:
公链:MOAC-pangu0.8.2。
节点版本:MOAC-pangu0.8.2-windows.exe。
操作系统:Windows 10家庭版。
一、安装并启动moac本地节点
1.1 安装moac节点请参考文档《MOAC Windows版系统安装教程》:
https://mp.weixin.qq.com/s/6ZnFYM6BJGZcjuVfu64Aog
1.2 启动moac节点
打开命令终端(cmd),转到墨客当前目录,在命令行中执行:
D:\moacPangu0.8.2-win>moac --rpc --rpccorsdomain "http://wallet.moac.io
"
备注:
--rpc 启动RPC服务,本机访问节点
--rpccorsdomain 启动RPC服务,非本机访问节点
"http://wallet.moac.io
" moac在线钱包网址,会自动连接到本机启动的moac节点并显示已有账号,如果本机节点没有启动,会显示以下提示信息。
启动正常,会显示以下账号信息。确保其中一个账号有足够的moac以进行智能合约部署。
二、编写并编译智能合约
2.1 以下为基于erc-20编写的一个代币合约
本文实际测试代码TestToken20.sol附在文章末尾。
注意:该代码为测试实例使用,非标准部署智能合约代码。
2.2 编译、部署合约
在网页钱包点击“CONTRACTS”
点击“DEPLOY NEW CONTRACT”
选择一个有moac余额的账号
把自己编写的智能合约代码放进代码区“Solidity contract source code”,该代码会自动进行编译,如果编译通过,右侧会显示"Select contract to deploy"。
如果编译没有通过,则不会显示相应内容。
本文实际测试代码TestToken20.sol附在文章末尾。
注意:该代码为测试实例使用,非标准部署智能合约代码。
2.2 编译、部署合约
在网页钱包点击“CONTRACTS”
点击“DEPLOY NEW CONTRACT”
选择一个有moac余额的账号
把自己编写的智能合约代码放进代码区“Solidity contract source code”,该代码会自动进行编译,如果编译通过,右侧会显示"Select contract to deploy"。
如果编译没有通过,则不会显示相应内容。
在“Select contract to deploy”下拉框选择相应的token类型,本例为“Token Demo”,下面会自动弹出参数输入框,主要包括四项:
1、initial Amount - 256 bits unsigned integer
//token发行总量,本例为"10000"
2、token Name - String
//token名称,本例为"KongFuZi Token"
3、decimal Units - 8 bits unsigned integer
//token最小单位是小数点后第几位
4、token Symbol - String
//token简称,本例为"KFZT"
在选择gas费用后,点击"DEPLOY"部署合约
此时会显示发布合约确认界面。
如果提示需要解锁(发送代币的)账户,
进入moac命令行界面,输入命令:
>personal.unlockAccount(mc.accounts[0], "passwd", 300)
共有三个参数:
第一个参数表示解锁的账户,
第二个参数是该账户的密码,
第三个参数是解锁时间,本例为300秒,300秒后会重新锁住账户;
如果解锁时间设为0,表示一直解锁,此时账号有风险,慎用。
为了隐藏密码,可以输入命令:
>personal.unlockAccount(mc.accounts[0])
回车后提示输入密码,此时密码不显示出来,该命令默认将账户解锁5分钟。
成功解锁会返回true。
此时会显示发布合约确认界面。
注意:Data里必须有数据,否则不能正常部署
点击“OK”,开始部署合约,界面下方会显示当前部署合约的进度条
1、initial Amount - 256 bits unsigned integer
//token发行总量,本例为"10000"
2、token Name - String
//token名称,本例为"KongFuZi Token"
3、decimal Units - 8 bits unsigned integer
//token最小单位是小数点后第几位
4、token Symbol - String
//token简称,本例为"KFZT"
在选择gas费用后,点击"DEPLOY"部署合约
此时会显示发布合约确认界面。
如果提示需要解锁(发送代币的)账户,
进入moac命令行界面,输入命令:
>personal.unlockAccount(mc.accounts[0], "passwd", 300)
共有三个参数:
第一个参数表示解锁的账户,
第二个参数是该账户的密码,
第三个参数是解锁时间,本例为300秒,300秒后会重新锁住账户;
如果解锁时间设为0,表示一直解锁,此时账号有风险,慎用。
为了隐藏密码,可以输入命令:
>personal.unlockAccount(mc.accounts[0])
回车后提示输入密码,此时密码不显示出来,该命令默认将账户解锁5分钟。
成功解锁会返回true。
此时会显示发布合约确认界面。
注意:Data里必须有数据,否则不能正常部署
点击“OK”,开始部署合约,界面下方会显示当前部署合约的进度条
点击成功部署的合约,可以看到基本内容,包括合约地址hash、被写入的区块号等。
登录moac区块链0.8.2版的浏览器:http://explorer.moac.io
。
在搜索栏输入合约地址,可以搜索到该合约的相应内容
点击发布该合约的账号地址,即上图的"from",可以看到该账号下的所有合约部署情况。
至此,可以确认合约部署成功。
三、token的交易
3.1 查看合约状态
点击部署完毕的合约进度条上的“Test Token (管理页面)”,进入合约管理界面。
管理界面的上半部分显示基本信息,顶部是合约地址,右边有通用功能按钮。主要包括:接收墨客和token、浏览器查看、拷贝地址、二维码和显示接口。
点击“浏览器查看”,会跳转到区块浏览器并自动显示合约查询结果界面。
点击“显示接口”,跳出如下界面,显示“合约JSON接口”。提示如果有其他人需要管理或操作这个智能合约,则需要把接口内容连同合约地址一并发送给他。
管理界面的下半部分显示合约自身功能。
其中左边显示合约的读操作,本例中主要包括name,发行总量等。
右边为对合约的写操作,除非有自己定义的功能,对于erc-20合约不经常用到。
登录moac区块链0.8.2版的浏览器:http://explorer.moac.io
。
在搜索栏输入合约地址,可以搜索到该合约的相应内容
点击发布该合约的账号地址,即上图的"from",可以看到该账号下的所有合约部署情况。
至此,可以确认合约部署成功。
三、token的交易
3.1 查看合约状态
点击部署完毕的合约进度条上的“Test Token (管理页面)”,进入合约管理界面。
管理界面的上半部分显示基本信息,顶部是合约地址,右边有通用功能按钮。主要包括:接收墨客和token、浏览器查看、拷贝地址、二维码和显示接口。
点击“浏览器查看”,会跳转到区块浏览器并自动显示合约查询结果界面。
点击“显示接口”,跳出如下界面,显示“合约JSON接口”。提示如果有其他人需要管理或操作这个智能合约,则需要把接口内容连同合约地址一并发送给他。
管理界面的下半部分显示合约自身功能。
其中左边显示合约的读操作,本例中主要包括name,发行总量等。
右边为对合约的写操作,除非有自己定义的功能,对于erc-20合约不经常用到。
3.2 查看token
点击进入钱包的“CONTRACT”界面,会自动在查看合约(WATCH CONTRACT)和查看通证(WATCH TOKEN)显示所有本节点部署的合约和token。点击均可以进入相应管理和查看界面。
在账户界面,也能看到每个账户拥有的token情况。
进入发行该智能合约的主账户MAIN ACCOUNT,会显示token信息,及该账户拥有的token余额等。
3.3 交易
从钱包里拥有KFZT token的主账户,点击“SEND”进入发送交易界面。
填入要接收的账户(“TO”)、选择要发的代币名称(“KongFuZi Token”)、填入要交易的token数量(“AMOUNT”),点击“SEND”
显示发送信息界面
此处如果提示需要解锁账户,参考前面的unlockAccount命令。
交易成功后会看到FROM账号token数量减少
而TO账号相应token数量增加
注意:moac区块链浏览器:http://explorer.moac.io
。查看erc20代币的时候,可以看到合约创建情况,发送token交易成功后能看到from_address与合约地址的交易,但是看不到合约地址与to_address的交易,正在完善中。网页版钱包能看到token交易的完整过程。
点击进入钱包的“CONTRACT”界面,会自动在查看合约(WATCH CONTRACT)和查看通证(WATCH TOKEN)显示所有本节点部署的合约和token。点击均可以进入相应管理和查看界面。
在账户界面,也能看到每个账户拥有的token情况。
进入发行该智能合约的主账户MAIN ACCOUNT,会显示token信息,及该账户拥有的token余额等。
3.3 交易
从钱包里拥有KFZT token的主账户,点击“SEND”进入发送交易界面。
填入要接收的账户(“TO”)、选择要发的代币名称(“KongFuZi Token”)、填入要交易的token数量(“AMOUNT”),点击“SEND”
显示发送信息界面
此处如果提示需要解锁账户,参考前面的unlockAccount命令。
交易成功后会看到FROM账号token数量减少
而TO账号相应token数量增加
注意:moac区块链浏览器:http://explorer.moac.io
。查看erc20代币的时候,可以看到合约创建情况,发送token交易成功后能看到from_address与合约地址的交易,但是看不到合约地址与to_address的交易,正在完善中。网页版钱包能看到token交易的完整过程。
附件:
本文所用合约代码TestToken20.sol。
注意:该代码为测试实例使用,非通用智能合约代码。
pragma solidity ^0.4.16;
contract Token{
function balanceOf(address _owner) public constant returns (uint256 balance);
function transfer(address _to, uint256 _value) public returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
function approve(address _spender, uint256 _value) public returns (bool success);
function allowance(address _owner, address _spender) public constant returns (uint256 remaining);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
contract TokenDemo is Token {
uint256 public totalSupply; //发行总量
string public name; //名称,例如"My test token"
uint8 public decimals; //返回token使用的小数点后几位。比如如果设置为3,就是支持0.001表示.
string public symbol; //token简称,like MTT
function TokenDemo(uint256 initialAmount, string tokenName, uint8 decimalUnits, string tokenSymbol) public {
totalSupply = initialAmount * 10 ** uint256(decimalUnits); // 设置初始总量
balances[msg.sender] = totalSupply; // 初始token数量全部给予合约的创建者
name = tokenName;
decimals = decimalUnits;
symbol = tokenSymbol;
}
function transfer(address _to, uint256 _value) public returns (bool success) {
//默认totalSupply 不会超过最大值 (2^256 - 1).
//如果随着时间的推移将会有新的token生成,则可以用下面这句避免溢出的异常
require(balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]);
require(_to != 0x0);
balances[msg.sender] -= _value; //从消息发送者账户中减去token数量_value
balances[_to] += _value; //往接收账户增加token数量_value
Transfer(msg.sender, _to, _value); //触发转币交易事件
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value);
balances[_to] += _value; //接收账户增加token数量_value
balances[_from] -= _value; //支出账户_from减去token数量_value
allowed[_from][msg.sender] -= _value; //消息发送者可以从账户_from中转出的数量减少_value
Transfer(_from, _to, _value); //触发转币交易事件
return true;
}
function balanceOf(address _owner) public constant returns (uint256 balance) {
return balances[_owner];
}
function approve(address _spender, uint256 _value) public returns (bool success)
{
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender) public constant returns (uint256 remaining) {
return allowed[_owner][_spender]; //允许_spender从_owner中转出的token数,也就是授权
}
mapping (address => uint256) balances;
mapping (address => mapping (address => uint256)) allowed;
}
代码不做过多解释,参考注释。
本文所用合约代码TestToken20.sol。
注意:该代码为测试实例使用,非通用智能合约代码。
pragma solidity ^0.4.16;
contract Token{
function balanceOf(address _owner) public constant returns (uint256 balance);
function transfer(address _to, uint256 _value) public returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
function approve(address _spender, uint256 _value) public returns (bool success);
function allowance(address _owner, address _spender) public constant returns (uint256 remaining);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
contract TokenDemo is Token {
uint256 public totalSupply; //发行总量
string public name; //名称,例如"My test token"
uint8 public decimals; //返回token使用的小数点后几位。比如如果设置为3,就是支持0.001表示.
string public symbol; //token简称,like MTT
function TokenDemo(uint256 initialAmount, string tokenName, uint8 decimalUnits, string tokenSymbol) public {
totalSupply = initialAmount * 10 ** uint256(decimalUnits); // 设置初始总量
balances[msg.sender] = totalSupply; // 初始token数量全部给予合约的创建者
name = tokenName;
decimals = decimalUnits;
symbol = tokenSymbol;
}
function transfer(address _to, uint256 _value) public returns (bool success) {
//默认totalSupply 不会超过最大值 (2^256 - 1).
//如果随着时间的推移将会有新的token生成,则可以用下面这句避免溢出的异常
require(balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]);
require(_to != 0x0);
balances[msg.sender] -= _value; //从消息发送者账户中减去token数量_value
balances[_to] += _value; //往接收账户增加token数量_value
Transfer(msg.sender, _to, _value); //触发转币交易事件
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value);
balances[_to] += _value; //接收账户增加token数量_value
balances[_from] -= _value; //支出账户_from减去token数量_value
allowed[_from][msg.sender] -= _value; //消息发送者可以从账户_from中转出的数量减少_value
Transfer(_from, _to, _value); //触发转币交易事件
return true;
}
function balanceOf(address _owner) public constant returns (uint256 balance) {
return balances[_owner];
}
function approve(address _spender, uint256 _value) public returns (bool success)
{
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender) public constant returns (uint256 remaining) {
return allowed[_owner][_spender]; //允许_spender从_owner中转出的token数,也就是授权
}
mapping (address => uint256) balances;
mapping (address => mapping (address => uint256)) allowed;
}
代码不做过多解释,参考注释。