专栏首页Netkiller以太坊·代币开发详解
原创

以太坊·代币开发详解

本文节选自《Netkiller Blockchain 手札》

Netkiller Blockchain 手札

本文作者最近在找工作,有意向致电 13113668890

Mr. Neo Chan, 陈景峯(BG7NYT)

中国广东省深圳市龙华新区民治街道溪山美地 518131 +86 13113668890 <netkiller@msn.com>

文档始创于2018-02-10

版权 © 2018 Netkiller(Neo Chan). All rights reserved.

版权声明

转载请与作者联系,转载时请务必标明文章原始出处和作者信息及本声明。

http://www.netkiller.cnhttp://netkiller.github.iohttp://netkiller.sourceforge.net

http://www.netkiller.cn

http://netkiller.github.io

http://netkiller.sourceforge.net

微信订阅号 netkiller-ebook (微信扫描二维码)QQ:13721218 请注明“读者”QQ群:128659835 请注明“读者”

微信订阅号 netkiller-ebook (微信扫描二维码)

QQ:13721218 请注明“读者”

QQ群:128659835 请注明“读者”

http://www.netkiller.cn

http://netkiller.github.io

http://netkiller.sourceforge.net

微信订阅号 netkiller-ebook (微信扫描二维码)

QQ:13721218 请注明“读者”

QQ群:128659835 请注明“读者”

$Data$

内容摘要

这一部关于区块链开发及运维的电子书。

为什么会写区块链电子书?因为2018年是区块链年。

这本电子书是否会出版(纸质图书)? 不会,因为互联网技术更迭太快,纸质书籍的内容无法实时更新,一本书动辄百元,很快就成为垃圾,你会发现目前市面的上区块链书籍至少是一年前写的,内容已经过时,很多例子无法正确运行。所以我不会出版,电子书的内容会追逐技术发展,及时跟进软件版本的升级,做到内容最新,至少是主流。

这本电子书与其他区块链书籍有什么不同?市面上大部分区块链书籍都是用2/3去讲区块链原理,只要不到 1/3 的干货,干货不够理论来凑,通篇将理论或是大谈特谈区块链行业,这些内容更多是头脑风暴,展望区块链,均无法落地实施。本书与那些书籍完全不同,不讲理论和原理,面向应用落地,注重例子,均是干货。

电子书更新频率?每天都会有新内容加入,更新频率最迟不会超过一周,更新内容请关注 https://github.com/netkiller/netkiller.github.io/commits/master

本文采用碎片化写作,原文会不定期更新,请尽量阅读原文。

http://www.netkiller.cn/blockchain/index.html

9.4. 创建代币

https://ethereum.org/token

9.4.1. 合约文件

pragma solidity ^0.4.16;

interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; }

contract TokenERC20 {
    // Public variables of the token
    string public name;
    string public symbol;
    uint8 public decimals = 18;
    // 18 decimals is the strongly suggested default, avoid changing it
    uint256 public totalSupply;

    // This creates an array with all balances
    mapping (address => uint256) public balanceOf;
    mapping (address => mapping (address => uint256)) public allowance;

    // This generates a public event on the blockchain that will notify clients
    event Transfer(address indexed from, address indexed to, uint256 value);

    // This notifies clients about the amount burnt
    event Burn(address indexed from, uint256 value);

    /**
     * Constrctor function
     *
     * Initializes contract with initial supply tokens to the creator of the contract
     */
    function TokenERC20(
        uint256 initialSupply,
        string tokenName,
        string tokenSymbol
    ) public {
        totalSupply = initialSupply * 10 ** uint256(decimals);  // Update total supply with the decimal amount
        balanceOf[msg.sender] = totalSupply;                // Give the creator all initial tokens
        name = tokenName;                                   // Set the name for display purposes
        symbol = tokenSymbol;                               // Set the symbol for display purposes
    }

    /**
     * Internal transfer, only can be called by this contract
     */
    function _transfer(address _from, address _to, uint _value) internal {
        // Prevent transfer to 0x0 address. Use burn() instead
        require(_to != 0x0);
        // Check if the sender has enough
        require(balanceOf[_from] >= _value);
        // Check for overflows
        require(balanceOf[_to] + _value > balanceOf[_to]);
        // Save this for an assertion in the future
        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);
        // Asserts are used to use static analysis to find bugs in your code. They should never fail
        assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
    }

    /**
     * Transfer tokens
     *
     * Send `_value` tokens to `_to` from your account
     *
     * @param _to The address of the recipient
     * @param _value the amount to send
     */
    function transfer(address _to, uint256 _value) public {
        _transfer(msg.sender, _to, _value);
    }

    /**
     * Transfer tokens from other address
     *
     * Send `_value` tokens to `_to` on behalf of `_from`
     *
     * @param _from The address of the sender
     * @param _to The address of the recipient
     * @param _value the amount to send
     */
    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;
    }

    /**
     * Set allowance for other address
     *
     * Allows `_spender` to spend no more than `_value` tokens on your behalf
     *
     * @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;
    }

    /**
     * Set allowance for other address and notify
     *
     * Allows `_spender` to spend no more than `_value` tokens on your behalf, and then ping the contract about it
     *
     * @param _spender The address authorized to spend
     * @param _value the max amount they can spend
     * @param _extraData some extra information to send to the approved contract
     */
    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;
        }
    }

    /**
     * Destroy tokens
     *
     * Remove `_value` tokens from the system irreversibly
     *
     * @param _value the amount of money to burn
     */
    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;
    }

    /**
     * Destroy tokens from other account
     *
     * 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;
    }
}

9.4.2. 部署合约

启动 Ethereum Wallet,点击 CONTRACTS 按钮,进入合约管理界面

点击 DEPLOY NEW CONTRACT 按钮,部署一个新合约

复制粘贴合约文件到 SOLIDITY CONTRACT SOURCE CODE 下方

SELECT CONTRACT TO DEPLOY 列表选择 “Token ERC 20”

Initial supply 是初始发行货币量

Token name 是代币名称

Token symbol 是代币符号

拉动滚动调,找到下方 “DEPLOY”按钮,点击该按钮。

输入账号密码,并点击“SEND TRANSACTION” 按钮。

ERC20代币创建完成

9.4.3. 代币转账

进入钱包可以看到当前账号的以太币数量,在下方还能看到 ERC20 代币。

点击 SEND 按钮

填写 TO 地址 和 代币 500 个,点击 SEND 按钮

进入目标账号查看余额。

至此我们完成了,代币合约部署,实现了账号对账号的转账。下面我们来讲述如何开发。

以太币开发是指,使用程序实现代币的转账,因为我们不可能使用钱包手工转账。让代币落地就需要在程序中完成。

通常程序部署在WEB服务器,例如这样的场景,用户在网站上注册开户,赠送一定量的代币奖励。

这时我们就需要使用WEB3.js(Node) 或者WEB3J (Java API )完成网站或者手机APP访问以太坊,完成代币转账。

6.10.4. ERC20 Example

通过Web3操作代币转账

fs = require('fs');
const Web3 = require('web3');
const web3 = new Web3('http://localhost:8545');
web3.version
const abi = fs.readFileSync('output/TokenERC20.abi', 'utf-8');

const contractAddress = "0x05A97632C197a0496bc939C4e666c2E03Cb95DD4";
const toAddress = "0x2C687bfF93677D69bd20808a36E4BC2999B4767C";

var coinbase;

web3.eth.getCoinbase().then(function (address){
  coinbase = address;
  console.log(address);
});

const contract = new web3.eth.Contract(JSON.parse(abi), contractAddress, { from: coinbase , gas: 100000});

contract.methods.balanceOf('0x5c18a33DF2cc41a1bedDC91133b8422e89f041B7').call().then(console.log).catch(console.error);
contract.methods.balanceOf('0x2C687bfF93677D69bd20808a36E4BC2999B4767C').call().then(console.log).catch(console.error);

web3.eth.personal.unlockAccount(coinbase, "Netkiller").then(console.log);
contract.methods.transfer('0x2C687bfF93677D69bd20808a36E4BC2999B4767C', 100).send().then(console.log).catch(console.error);

contract.methods.balanceOf('0x2C687bfF93677D69bd20808a36E4BC2999B4767C').call().then(console.log).catch(console.error);

上面的代码可是纯干货,你在网上看到最多的例子就是钱包完成合约,没有人提供web3代码完成同样的操作。我也翻遍了了网上找不到资料,这是我辛苦琢磨出来的,有不明白之处去我的QQ群里讨论把。

以上例子均使用最新版本

geth 1.8.1

web3.js 1.0.0-beta30

solc Version: 0.4.20

如果上面资料对你有用,打赏地址:http://www.netkiller.cn/home/donations.html

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 游戏领域区块链探索

    中国广东省深圳市龙华新区民治街道溪山美地 518131 +86 13113668890 <netkiller@msn.com>

    netkiller old
  • How Badoo saved one million dollars switching to PHP7

    How Badoo saved one million dollars switching to PHP7 By Badoo on 14 Mar 2016 - ...

    netkiller old
  • DevOps Tools

    DevOps Tools OS Software Configure Managment Install Ubuntu $ cd /usr/local/src/...

    netkiller old
  • 快速学习-ERC20 代币合约

    cwl_java
  • Ultimate Facebook Messenger for Business Guide (Updated: Feb 2019)

    Ultimate Facebook Messenger for Business Guide (Updated: Feb 2019)

    Spanz
  • How to add Facebook’s Customer Chat Plugin to your website

    Do you need a live chat plugin on your website? It would be great if your web vi...

    Spanz
  • CRM呼叫中心里对于inbound电子邮件的自动化处理

    版权声明:本文为博主汪子熙原创文章,未经博主允许不得转载。 https://jerry.blog....

    Jerry Wang
  • c3p0,DBPC,Druid三大连接池的区别/性能【面试+工作】

    奋斗蒙
  • 大公司都有哪些开源项目之豆瓣

    豆瓣 DouBan https://github.com/douban 1.分布式计算框架 DPark DPark 是 Spark 的 Python 克隆,是一...

    逸鹏
  • bind9的初步使用(2)

    比如我的windows 10的ip地址是192.168.1.230。那么我们可以添加如下内容到/etc/bind/named.conf.options文件中。

    魔王卷子

扫码关注云+社区

领取腾讯云代金券