区块链(六)windows 以太坊私有链创建代币

写在之前, 由于不慎装的版本比较高,且初学对solidity也不熟,网上的教程现成的合约基用钱包本都未编译通过。

geth 版本:1.8.12

钱包mist版本:0.11.1

需要熟悉旧知识的童鞋往前翻

=================================================================

创建新币合约

我们要创建的第一个合约是一个代币合约。以太坊生态系统中的代币可以代表任何可以交易的东西:币(coin)、积分、黄金证券、欠条(IOU)等。因为所有的代币都以标准化的方式实现一些基本的特性,这样意味着你自己创建的代币将于以太坊钱包、使用相同标准的任何其它客户端或者合约相兼容。

点击红框中的Contract(合约),看到如下界面。


将红框中原有的代码删除,将下面的代码粘贴到里面。

pragma solidity ^0.4.24;

/**

* @title SafeMath

* @dev Math operations with safety checks that throw on error

  防止整数溢出问题

*/

library SafeMath {

  function mul(uint256 a, uint256 b) internal pure returns (uint256) {

    uint256 c = a * b;

    assert(a == 0 || c / a == b);

    return c;

  }

  function div(uint256 a, uint256 b) internal pure returns (uint256) {

    // assert(b > 0); // Solidity automatically throws when dividing by 0

    uint256 c = a / b;

    // assert(a == b * c + a % b); // There is no case in which this doesn't hold

    return c;

  }

  function sub(uint256 a, uint256 b) internal pure returns (uint256) {

    assert(b <= a);

    return a - b;

  }

  function add(uint256 a, uint256 b) internal pure returns (uint256) {

    uint256 c = a + b;

    assert(c >= a);

    return c;

  }

}

contract StandardToken {

//使用SafeMath

    using SafeMath for uint256;


    //代币名称

    string public name;

    //代币缩写

    string public symbol;

//代币小数位数(一个代币可以分为多少份)

    uint8 public  decimals;

//代币总数

uint256 public totalSupply;


//交易的发起方(谁调用这个方法,谁就是交易的发起方)把_value数量的代币发送到_to账户

    function transfer(address _to, uint256 _value) public returns (bool success);

    //从_from账户里转出_value数量的代币到_to账户

    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);

//交易的发起方把_value数量的代币的使用权交给_spender,然后_spender才能调用transferFrom方法把我账户里的钱转给另外一个人

    function approve(address _spender, uint256 _value) public returns (bool success);

//查询_spender目前还有多少_owner账户代币的使用权

    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 Owned {

    // modifier(条件),表示必须是权力所有者才能do something,类似administrator的意思

    modifier onlyOwner() {

        require(msg.sender == owner);

        _;//do something

    }

//权力所有者

    address public owner;

//合约创建的时候执行,执行合约的人是第一个owner

    constructor() public {

        owner = msg.sender;

    }

//新的owner,初始为空地址,类似null

    address newOwner=0x0;

//更换owner成功的事件

    event OwnerUpdate(address _prevOwner, address _newOwner);

    //现任owner把所有权交给新的owner(需要新的owner调用acceptOwnership方法才会生效)

    function changeOwner(address _newOwner) public onlyOwner {

        require(_newOwner != owner);

        newOwner = _newOwner;

    }

    //新的owner接受所有权,权力交替正式生效

    function acceptOwnership() public{

        require(msg.sender == newOwner);

        emit OwnerUpdate(owner, newOwner);

        owner = newOwner;

        newOwner = 0x0;

    }

}

//代币的控制合约

contract Controlled is Owned{

//创世vip

    constructor() public {

      setExclude(msg.sender,true);

    }

    // 控制代币是否可以交易,true代表可以(exclude里的账户不受此限制,具体实现在下面的transferAllowed里)

    bool public transferEnabled = true;

    // 是否启用账户锁定功能,true代表启用

    bool lockFlag=true;

// 锁定的账户集合,address账户,bool是否被锁,true:被锁定,当lockFlag=true时,恭喜,你转不了账了,哈哈

    mapping(address => bool) locked;

// 拥有特权用户,不受transferEnabled和lockFlag的限制,vip啊,bool为true代表vip有效

    mapping(address => bool) exclude;

//设置transferEnabled值

    function enableTransfer(bool _enable) public onlyOwner returns (bool success){

        transferEnabled=_enable;

return true;

    }

//设置lockFlag值

    function disableLock(bool _enable) public onlyOwner returns (bool success){

        lockFlag=_enable;

        return true;

    }

// 把_addr加到锁定账户里,拉黑名单。。。

    function addLock(address _addr) public onlyOwner returns (bool success){

        require(_addr!=msg.sender);

        locked[_addr]=true;

        return true;

    }

//设置vip用户

    function setExclude(address _addr,bool _enable) public onlyOwner returns (bool success){

        exclude[_addr]=_enable;

        return true;

    }

//解锁_addr用户

    function removeLock(address _addr) public onlyOwner returns (bool success){

        locked[_addr]=false;

        return true;

    }

//控制合约 核心实现

    modifier transferAllowed(address _addr) {

        if (!exclude[_addr]) {

            require(transferEnabled,"transfer is not enabeled now!");

            if(lockFlag){

                require(!locked[_addr],"you are locked!");

            }

        }

        _;

    }

}

//代币 天天币

contract TtToken is StandardToken,Controlled {

//账户集合

mapping (address => uint256) public balanceOf;

mapping (address => mapping (address => uint256)) internal allowed;

constructor() public {

        totalSupply = 1000000000;//10亿

        name = "TT Token";

        symbol = "TT";

        decimals = 0;

        balanceOf[msg.sender] = totalSupply;

    }

    function transfer(address _to, uint256 _value) public transferAllowed(msg.sender) returns (bool success) {

require(_to != address(0));

require(_value <= balanceOf[msg.sender]);

        balanceOf[msg.sender] = balanceOf[msg.sender].sub(_value);

        balanceOf[_to] = balanceOf[_to].add(_value);

        emit Transfer(msg.sender, _to, _value);

        return true;

    }

    function transferFrom(address _from, address _to, uint256 _value) public transferAllowed(_from) returns (bool success) {

require(_to != address(0));

        require(_value <= balanceOf[_from]);

        require(_value <= allowed[_from][msg.sender]);

        balanceOf[_from] = balanceOf[_from].sub(_value);

        balanceOf[_to] = balanceOf[_to].add(_value);

        allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);

        emit Transfer(_from, _to, _value);

        return true;

    }

    function approve(address _spender, uint256 _value) public returns (bool success) {

        allowed[msg.sender][_spender] = _value;

        emit Approval(msg.sender, _spender, _value);

        return true;

    }

    function allowance(address _owner, address _spender) public view returns (uint256 remaining) {

      return allowed[_owner][_spender];

    }

}


然后,在右边更改系数【已经硬编码】,定制自己的货币。supply: 货币总量 100万,name: 货币名字 天天币,symbol:货币符号 TT,decimals 0:货币单位精确到小数点后几位。

SELECT FEE(选择费用),左右拖动横轴选择支付多少手续费(这里就需要用到前面购买到的以太币了),越靠近右边,费用越高,完成合约的速度越快。例如,我选择了0.016131个以太币,大约需要30秒完成合约。完成后,点击DEPLOY(部署)。自动转到如下界面,输入密码(即创建账户时设置的 密码),点击SEND TRANSACTION(发送交易)


然后,会跳转到钱包主界面,你会看到下面红色方框中的信息,大约需要3-4分钟的确认时间,完成12个确认就可以了。

确认完毕,然后再进入CONTRACTS(合约)页面,你将看到刚才创建的货币,例如下图中的TTCoin。


点击创建的货币,转到以下界面,复制红色方框中的合约地址,下面的步骤中要用到


再次回到CONTRACTS(合约)页面,点击WATCH TOKEN(查看代币)。


弹出如下界面,将刚才复制的地址粘贴到红色方框中,会看到货币的名字、符号等信息。点击OK。


完成以后,在合约页面就可以看到新创建的货币了。


发送新创建的新货币


跳转到如下确认界面,输入密码(即创建账户时设置的密码)。点击SEND TRANSACTION(发送交易)

回到WALLETS(钱包)界面,会看到刚刚发出的记录信息。

收款者需要将新创建的币的添加到WATCH Token中才可以看到收到的币。收款者进入CONTRACT(合约)页面,点击WATCH TOKEN,然后add token。发送者将创建的新币的合约地址通过聊天工具发给收款者。

收款者在WALLETS(钱包)页面将看到收到的币。下图显示收到了100个TTCoin。


上图是2转了2次,所以200TT

另外,跨节点转账也是支持的,to里输入其他节点不同的账号即可。

写在后面

写这篇教程,或者说我自己搭建的时候,搜索了很多资料,总结出一个经验,官方文档或者Github上,都会给出最基本,最简单的操作方法,结合网友们的文章看,更容易搭建起来。

在搭建过程中,你会更加具体的感受到区块链的工作方式,我觉得还是很有助于理解以太坊或其它基于区块链技术的项目。

另外说一下,

本人也是区块链新手,一边学习,一边把学习的过程记录下来向大家分享,中间走了非常多的弯路,

耗费了大量时间, 文章主要是把自己的学习经验分享出来,一个是自己可以巩固,另外可以帮助大家,避免大家和我一样走很多弯路.

后边基本会议linux 为主要输出来记录学习过程。

参考:

https://blog.csdn.net/hantangduhey/article/details/80714656

https://ethfans.org/topics/118

https://www.jianshu.com/p/879669da11e6?from=singlemessage

https://blog.csdn.net/zs345048102/article/details/80770321

https://blog.csdn.net/JAVA_HHHH/article/details/79771752


===========================代码介绍======================

1.代码介绍

遵守ERC20协议

具体代码体现:contract StandardToken

ERC20协议的github地址:https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md

遵守协议就是统一状态变量的名称和方法的名称,大家看代码里StandardToken合约里就是了,可能会觉得奇怪,官方文档里明明写的是像这种方法

functionname() view returns (string name)

你的代码里咋没写呢?因为我定义了 string public name,而public的公共变量name,会自动生成一个返回name的name()的方法,所以我不用重复写function name()了,其它几个变量也是一样的

引入SafeMath,防止整数溢出漏洞(SMT,BEC)

具体代码实现:library SafeMath

官方介绍地址:https://ethereumdev.io/safemath-protect-overflows/

设置一个控制合约

具体代码体现:contract Controlled

作用:

1.有突发情况,可以暂停所有人的转账

2.设置黑名单功能,可以冻结黑名单帐户,让它无法转账

3.也可以设置vip帐户,不受前面两个的控制

管理员

具体代码体现:contract Owned

既然有控制合约,各种转账控制,那么谁来设置这个东西,如果人人都有权限,那就乱套了,所以需要一个唯一管理员;管理员也可以把这个权力禅让给一个新的管理员

具体实现代币功能

具体代码体现:contract LiSaoToken

功能点,通俗的讲就是 :

1.自己转账给他人(transfer)

2.自己帮别人转账给另外一个人(transferFrom)

3.我委托你帮我管理我的代币,使用权给你,但是币还在我这(approve)

4.查看一下我还有多少币委托你在管理(allowance)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容