美文网首页
基于以太坊发布属于自己的数字货币(代币)完整版

基于以太坊发布属于自己的数字货币(代币)完整版

作者: 逗逗的小目标 | 来源:发表于2018-10-31 17:10 被阅读0次

    基于以太坊发布属于自己的数字货币(代币)完整版

    (参考资料来源于网络以及各种摸索,其中各种坑)

    本文单纯从技术角度详细介绍如何基于以太坊ERC20创建代币的流程(此案例是部署的eth主网,非测试案例)

    写在前面

    本文所讲的代币是使用以太坊智能合约创建,阅读本文前,你应该对以太坊、智能合约有所了解,如果你还不了解,建议你先看以太坊是什么。

    代币Token

    如果不那么追求精确的定义,代币就是数字货币,比特币、以太币就是一个代币。

    利用以太坊的智能合约可以轻松编写出属于自己的代币,代币可以代表任何可以交易的东西,如:积分、财产、证书等等。

    因此不管是出于商业,还是学习很多人想创建一个自己的代币,先贴一个图看看创建的代币是什么样子。

    以我自己发布的BliBli币 Bcoin为例

    访问地址 :  https://etherscan.io/token/0x73c8da697fe5e145f6269c4c852e59a7328f9371

     今天我们就来详细讲一讲怎样创建一个这样的代币。

    ERC20 Token

    ERC20和代币一同出现, ERC20是以太坊定义的一个代币标准。是一种发行代币合约必须要遵守的协议,该协议规定了几个参数——发行货币的名称,简称,发行量,要支持的函数等,只有支持了该协议才会被以太坊所认同。

    erc20标准代码如下

    // https://github.com/ethereum/EIPs/issues/20

      contract ERC20 {

          function totalSupply() constant returns (uint totalSupply);

          function balanceOf(address _owner) constant returns (uint balance);

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

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

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

          function allowance(address _owner, address _spender) constant returns (uint remaining);

          event Transfer(address indexed _from, address indexed _to, uint _value);

          event Approval(address indexed _owner, address indexed _spender, uint _value);

        }

    totalSupply:  代表的是代币发行总量    totalSupply():该方法可以返回代币的总数量

    name:  发行代币的名称                       dicimals:  发行代币以后,代币交易的最小单位

    balanceOf(): 该方法返回的是输入钱包地址后,该钱包的代币余额

    tansferFrom() :从一个地址向另一个地址发送余额

    approve(): 允许_spender从你的账户转出_value余额

    allowance(): 允许_spender从你的账户转出_value的余额,调用多次会覆盖可用量。某些DEX功能需要此功能

    event Transfer():  token转移完成后出发

    event Approval():  approve(address _spender, uint256 _value)调用后触发

    编写代币合约:

    pragma solidity ^0.4.12;

    contract IMigrationContract {

        function migrate(address addr, uint256 nas) returns (bool success);

    }

    /* 灵感来自于NAS  coin*/

    contract SafeMath {

        function safeAdd(uint256 x, uint256 y) internal returns(uint256) {

            uint256 z = x + y;

            assert((z >= x) && (z >= y));

            return z;

        }

        function safeSubtract(uint256 x, uint256 y) internal returns(uint256) {

            assert(x >= y);

            uint256 z = x - y;

            return z;

        }

        function safeMult(uint256 x, uint256 y) internal returns(uint256) {

            uint256 z = x * y;

            assert((x == 0)||(z/x == y));

            return z;

        }

    }

    contract Token {

        uint256 public totalSupply;

        function balanceOf(address _owner) constant returns (uint256 balance);

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

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

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

        function allowance(address _owner, address _spender) constant returns (uint256 remaining);

        event Transfer(address indexed _from, address indexed _to, uint256 _value);

        event Approval(address indexed _owner, address indexed _spender, uint256 _value);

    }

    /*  ERC 20 token */

    contract StandardToken is Token {

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

            if (balances[msg.sender] >= _value && _value > 0) {

                balances[msg.sender] -= _value;

                balances[_to] += _value;

                Transfer(msg.sender, _to, _value);

                return true;

            } else {

                return false;

            }

        }

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

            if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {

                balances[_to] += _value;

                balances[_from] -= _value;

                allowed[_from][msg.sender] -= _value;

                Transfer(_from, _to, _value);

                return true;

            } else {

                return false;

            }

        }

        function balanceOf(address _owner) constant returns (uint256 balance) {

            return balances[_owner];

        }

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

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

            Approval(msg.sender, _spender, _value);

            return true;

        }

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

            return allowed[_owner][_spender];

        }

        mapping (address => uint256) balances;

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

    }

    contract BliBliToken is StandardToken, SafeMath {

        // metadata

        string  public constant name = "BliBli";

        string  public constant symbol = "BCoin";

        uint256 public constant decimals = 18;

        string  public version = "1.0";

        // contracts

        address public ethFundDeposit;          // ETH存放地址

        address public newContractAddr;        // token更新地址

        // crowdsale parameters

        bool    public isFunding;                // 状态切换到true

        uint256 public fundingStartBlock;

        uint256 public fundingStopBlock;

        uint256 public currentSupply;          // 正在售卖中的tokens数量

        uint256 public tokenRaised = 0;        // 总的售卖数量token

        uint256 public tokenMigrated = 0;    // 总的已经交易的 token

        uint256 public tokenExchangeRate = 625;            // 625 BILIBILI 兑换 1 ETH

        // events

        event AllocateToken(address indexed _to, uint256 _value);  // 分配的私有交易token;

        event IssueToken(address indexed _to, uint256 _value);      // 公开发行售卖的token;

        event IncreaseSupply(uint256 _value);

        event DecreaseSupply(uint256 _value);

        event Migrate(address indexed _to, uint256 _value);

        // 转换

        function formatDecimals(uint256 _value) internal returns (uint256 ) {

            return _value * 10 ** decimals;

        }

        // constructor

        function BliBliToken(

            address _ethFundDeposit,

            uint256 _currentSupply)

        {

            ethFundDeposit = _ethFundDeposit;

            isFunding = false;                          //通过控制预CrowdS ale状态

            fundingStartBlock = 0;

            fundingStopBlock = 0;

            currentSupply = formatDecimals(_currentSupply);

            totalSupply = formatDecimals(10000000);

            balances[msg.sender] = totalSupply;

            if(currentSupply > totalSupply) throw;

        }

        modifier isOwner()  { require(msg.sender == ethFundDeposit); _; }

        ///  设置token汇率

        function setTokenExchangeRate(uint256 _tokenExchangeRate) isOwner external {

            if (_tokenExchangeRate == 0) throw;

            if (_tokenExchangeRate == tokenExchangeRate) throw;

            tokenExchangeRate = _tokenExchangeRate;

        }

        /// @dev 超发token处理

        function increaseSupply (uint256 _value) isOwner external {

            uint256 value = formatDecimals(_value);

            if (value + currentSupply > totalSupply) throw;

            currentSupply = safeAdd(currentSupply, value);

            IncreaseSupply(value);

        }

        /// @dev 被盗token处理

        function decreaseSupply (uint256 _value) isOwner external {

            uint256 value = formatDecimals(_value);

            if (value + tokenRaised > currentSupply) throw;

            currentSupply = safeSubtract(currentSupply, value);

            DecreaseSupply(value);

        }

        ///  启动区块检测 异常的处理

        function startFunding (uint256 _fundingStartBlock, uint256 _fundingStopBlock) isOwner external {

            if (isFunding) throw;

            if (_fundingStartBlock >= _fundingStopBlock) throw;

            if (block.number >= _fundingStartBlock) throw;

            fundingStartBlock = _fundingStartBlock;

            fundingStopBlock = _fundingStopBlock;

            isFunding = true;

        }

        ///  关闭区块异常处理

        function stopFunding() isOwner external {

            if (!isFunding) throw;

            isFunding = false;

        }

        /// 开发了一个新的合同来接收token(或者更新token)

        function setMigrateContract(address _newContractAddr) isOwner external {

            if (_newContractAddr == newContractAddr) throw;

            newContractAddr = _newContractAddr;

        }

        /// 设置新的所有者地址

        function changeOwner(address _newFundDeposit) isOwner() external {

            if (_newFundDeposit == address(0x0)) throw;

            ethFundDeposit = _newFundDeposit;

        }

        ///转移token到新的合约

        function migrate() external {

            if(isFunding) throw;

            if(newContractAddr == address(0x0)) throw;

            uint256 tokens = balances[msg.sender];

            if (tokens == 0) throw;

            balances[msg.sender] = 0;

            tokenMigrated = safeAdd(tokenMigrated, tokens);

            IMigrationContract newContract = IMigrationContract(newContractAddr);

            if (!newContract.migrate(msg.sender, tokens)) throw;

            Migrate(msg.sender, tokens);              // log it

        }

        /// 转账ETH 到BILIBILI团队

        function transferETH() isOwner external {

            if (this.balance == 0) throw;

            if (!ethFundDeposit.send(this.balance)) throw;

        }

        ///  将BILIBILI token分配到预处理地址。

        function allocateToken (address _addr, uint256 _eth) isOwner external {

            if (_eth == 0) throw;

            if (_addr == address(0x0)) throw;

            uint256 tokens = safeMult(formatDecimals(_eth), tokenExchangeRate);

            if (tokens + tokenRaised > currentSupply) throw;

            tokenRaised = safeAdd(tokenRaised, tokens);

            balances[_addr] += tokens;

            AllocateToken(_addr, tokens);  // 记录token日志

        }

        /// 购买token

        function () payable {

            if (!isFunding) throw;

            if (msg.value == 0) throw;

            if (block.number < fundingStartBlock) throw;

            if (block.number > fundingStopBlock) throw;

            uint256 tokens = safeMult(msg.value, tokenExchangeRate);

            if (tokens + tokenRaised > currentSupply) throw;

            tokenRaised = safeAdd(tokenRaised, tokens);

            balances[msg.sender] += tokens;

            IssueToken(msg.sender, tokens);  //记录日志

        }

    }

    以上的代币合约,是参考以太坊已经ICO过,并且产生价值的代币合约参考而来,完整比且功能强大,此合约创建的代币,具有“交易”,“转账”,“异常检测”,“更改代币持有人”,“设置汇率”,“被盗处理”,“超发代币”等功能。

    (解释下:在以太坊的世界中,硬通货就是ETH-以太币,相当于现实世界中的黄金,我们发布的代币,就相当于各国发行的需要 与黄金挂钩兑换比率的货币,国家对货币拥有控制权,只要合约功能进行扩展,创造代币的人也会对代币拥有控制权。)

    (对于挖矿的误解:不少小哥哥小姐姐认为挖矿就是挖币,其实挖矿是挖区块,区块是干嘛的,是用来打包交易的,是存储数据的,代币是不用挖的,当你挖到了区块,代币是给你的奖励,在发行量一定的情况下,代币会越来越少,所以挖到区块的奖励会变少。那奖励少了为什么还要挖矿呢,因为你的任何一笔交易都需要记录,一个区块的大小也就几M,存储不了那么多交易信息,所以要持续挖区块来记录你的交易,同时交易的手续费,会奖励给挖出区块的人。)

    部署合约:

    部署合约有多种方式      1 geth 编译代码 ---部署合约

                                         2 用ethereum wallet钱包部署合约

                                        3 最简单直观的部署合约方式:  MetaMask和Remix Solidity IDE 部署合约

       我们按照 MetaMask和Remix Solidity IDE 来进行部署合约。

     1: 创建钱包帐号。MetaMask是钱包的一种,在chrome浏览器中,安装MetaMask插件即可,安装完成后,右上角会出现一个“狐狸头”的标志,点击该标志,打开钱包,第一步,创建账户,(创建账户只需要输入面密码即可,名称创建后可以随便改,该账户就是一个hash值,如何给自己创建的账户冲以太币,可以上https://otcbtc.com/sign_up网站,按照操作买以太币,然后转账到自己创建的账户)创建成功后,记住密码还有产生的几个随机单词(一定要记录下来)。如下:

       2:打开 Remix Solidity IDE 访问地址: http://remix.ethereum.org/#optimize=false&version=soljson-v0.4.21+commit.dfe3193c.js   界面如下 

    3:  拷贝“编写代币合约”后边的代码到Remix Solidity IDE中按照如下编译

    4: create 发布  如下

    5 create后,产生hash值,拷贝hash值,在钱包中添加token

    OK,如上所示,第一个属于你的真正意义上的去中心化数字货币就诞生了。正式网络和测试网络部署方法一样,不需要买eth就是了。

    如果是测试网络,如何获得ETH?   进入 https://gitter.im/kovan-testnet/faucet  下方直接发送你的账户地址(hash值)即可,一般五分钟到账,会得到五个测试网络用的ETH币。

    6(如果部署的是eth主网,非测试网,执行该步骤,测试网络可以不理会)

    发布了代币以后,如果以后进行ico,那么需要发布源码公开。步骤如下

       ①  拷贝部署成功的合约地址(hash),到  https://etherscan.io/   右上角搜索hash

       ②  按照如下图进行verify AND publish

               打开如下页面第一步

             打开如下页面第二部

              打开如下页面第三部

      ok  现在的代币就比较完整了,差ico了

    代币转账:

       1  metamask钱包转账:  如下

       输入地址和代币数量

    2  网页钱包转账:  如下  https://www.myetherwallet.com/#send-transaction

        登录账户:

      转账交易

    ---------------------

    作者:JAVA_HHHH

    来源:CSDN

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

    版权声明:本文为博主原创文章,转载请附上博文链接!

    相关文章

      网友评论

          本文标题:基于以太坊发布属于自己的数字货币(代币)完整版

          本文链接:https://www.haomeiwen.com/subject/yjnatqtx.html