龙空技术网

ERC20代币批量转账实现和解析(一)

热衷python和前端 296

前言:

如今你们对“ubuntu创建tap”大概比较注重,朋友们都想要剖析一些“ubuntu创建tap”的相关知识。那么小编同时在网摘上网罗了一些关于“ubuntu创建tap””的相关知识,希望朋友们能喜欢,我们一起来了解一下吧!

如果你对区块链和ERC20代币没有概念,请先阅读入门知识

以太坊是什么区块链技术-智能合约-以太坊

批量转账,指的是在一笔 ETH 交易中转多笔代币到不同的账户,一般用于 ERC20 代币项目启动时对用户进行空投。

批量空投的好处主要有两个,一是省 GAS 费,但事实上省得不多;二是省时间,这是最主要目的。以太坊是以交易为粒度打包,如果转账只能单对单,即使一次发起多笔单对单的交易,等待这些交易被打包的时间也非常漫长,而且还有笔数上限限制。将多笔转账放到同一个交易中,被打包确认的速度就会非常快。一般 ERC20 代币项目启动时都会大撒币,空投地址动辄都是几万几十万,批量空投接口对效率会有上百倍的提升。

文章主要内容

在本机部署ETH私有链在ETH私有链上发布ERC20代币三种批量转账方式的原理三种批量转账方式的实现如何解析批量转账

由于文章较长,所以这里分为两篇,本篇主要讲前两个部署环境的部分,熟悉部署的同学可以跳过本章

在本机部署ETH私有链

本机默认是在Mac OS X上进行安装,别的系统的安装可以在github上查看Ethereum Installation Instructions

geth安装

推荐使用Homebrew进行安装,简单快捷

brew 是 Mac 下的包管理工具,和Ubuntu里的apt-get类似

brew tap ethereum/ethereumbrew install ethereum复制代码

创建私有链

首先新建一个文件目录,例如ethprivate

要搭建私有链必须有一个创世区块,创世区块的信息写在一个json文件中,例如genesis.json文件,在ethprivate/genesis.json中写入下面的内容

{ "config": { "chainID": 1024, "homesteadBlock": 0, "eip155Block": 0, "eip158Block": 0 }, "alloc": {}, "coinbase": "0x0000000000000000000000000000000000000000", "difficulty": "0x400", "extraData": "0x", "gasLimit": "0x84c060", "nonce": "0xdeadbeefdeadbeef", "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "timestamp": "0x00"}复制代码

这里将gasLimit设置大一点,防止后面部署合约的时候报Error: exceeds block gas limit undefined的错误信息,这是因为合约所需的gas超过了区块的最大gas

创建好创世区块后,我们需要利用该创世区块去初始化区块链,需要新建一个data0目录存放区块信息

接着在主目录下,执行初始化区块链的命令

geth --datadir data0 init genesis.json复制代码

看到如下信息则表明初始化成功

启动私有链

geth --datadir 'data0' --identity 'my_block' --port '30304' console 2>>eth_output.log复制代码

参数含义

–identity:指定节点 ID;–rpc:表示开启 HTTP-RPC 服务;–rpcport:指定 HTTP-RPC 服务监听端口号(默认为 8545);–datadir:指定区块链数据的存储位置;–port:指定和其他节点连接所用的端口号(默认为 30303);–networkid: 指定私有链网络号;–nodiscover:关闭节点发现机制,防止加入有同样初始配置的陌生节点。复制代码

看到下面的信息表示私有链成功启动

创建账户

现在刚启动还没有任何账户

我们利用personal创建账户

personal.newAccount()复制代码

Passphrase 就是密码,连续输入两次密码便可以创建一个账户

除了personal,geth命令行中还包含了另外的对象

eth:包含一些跟操作区块链相关的方法net:包含以下查看p2p网络状态的方法admin:包含一些与管理节点相关的方法miner:包含启动&停止挖矿的一些方法personal:主要包含一些管理账户的方法txpool:包含一些查看交易内存池的方法web3:包含了以上对象,还包含一些单位换算的方法复制代码

按照这中方式可以多创建几个账户,在后面使用

挖矿

我们刚开始还没有进行挖矿,所以eth.accounts[0]中的余额为0

eth.getBalance(eth.accounts[0])复制代码

挖矿所得的ETH会默认存在eth.accounts[0]的账户当中

通过miner.start()来启动挖矿,利用miner.stop()停止挖矿

miner.start()会返回null,推荐使用tail -f eth_output.log查看日志,这样就可以看到挖矿的信息

现在我们查看账户的余额就不在是0了

每挖到一个区块会奖励5个以太币,日志中可以看到到目前为止挖到了5个区块,那么就应该是20个以太币,可是查看的余额却不是这样,这是因为这里默认的单位是Wei,有关单位可以去移步以太币(Ether)单位

可以利用下面的命令转换单位

这里只做简单的介绍,其余的命令大家有感兴趣的可以自行查找

在ETH私有链上发布ERC20代币

ERC20是Fabian Vogelsteller在2015年末提出的以太坊改进建议,它是许多流行的合约都在遵循的标准。

ERC20使通证智能合约的行为非常类似于传统的加密货币,例如在不同账户之间发送和接收、查看通证总供应量或者查看某个地址可用的通证余额​,就像比特币或以太币一样。这类似于用以太坊钱包 发送和接收以太币、查看流通中的以太币总量、查看特定钱包的货币余额等。

ERC20规定了一些标准的接口

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 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 transfer(address to, uint tokens) public returns (bool success); function approve(address spender, 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);}复制代码

简单的介绍一下,更加详细的介绍可以在github查看

name : 代币名称symbol: 代币符号decimals: 代币小数点位数,代币的最小单位totalSupply() : 发行代币总量。balanceOf(): 查看对应账号的代币余额。transfer(): 实现代币交易,用于给用户发送代币(从我们的账户里)transferFrom(): 实现代币用户之间的交易allowance(): 控制代币的交易,如可交易账号及资产approve(): 允许用户可花费的代币数复制代码

在ETH私有链上发布ERC20代币

ERC20是Fabian Vogelsteller在2015年末提出的以太坊改进建议,它是许多流行的合约都在遵循的标准。

ERC20使通证智能合约的行为非常类似于传统的加密货币,例如在不同账户之间发送和接收、查看通证总供应量或者查看某个地址可用的通证余额​,就像比特币或以太币一样。这类似于用以太坊钱包 发送和接收以太币、查看流通中的以太币总量、查看特定钱包的货币余额等。

ERC20规定了一些标准的接口

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 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 transfer(address to, uint tokens) public returns (bool success); function approve(address spender, 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);}复制代码

简单的介绍一下,更加详细的介绍可以在github查看

name : 代币名称symbol: 代币符号decimals: 代币小数点位数,代币的最小单位totalSupply() : 发行代币总量。balanceOf(): 查看对应账号的代币余额。transfer(): 实现代币交易,用于给用户发送代币(从我们的账户里)transferFrom(): 实现代币用户之间的交易allowance(): 控制代币的交易,如可交易账号及资产approve(): 允许用户可花费的代币数复制代码

编写合约代码

先编写一个符合ERC20标准的代码

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; // 18 是建议的默认值 uint256 public totalSupply; 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); balanceOf[msg.sender] = totalSupply; name = tokenName; symbol = tokenSymbol; } function _transfer(address _from, address _to, uint _value) internal { require(_to != 0x0); require(balanceOf[_from] >= _value); require(balanceOf[_to] + _value > balanceOf[_to]); uint previousBalances = balanceOf[_from] + balanceOf[_to]; balanceOf[_from] -= _value; balanceOf[_to] += _value; Transfer(_from, _to, _value); assert(balanceOf[_from] + balanceOf[_to] == previousBalances); } function transfer(address _to, uint256 _value) public { _transfer(msg.sender, _to, _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; } function approve(address _spender, uint256 _value) public returns (bool success) { allowance[msg.sender][_spender] = _value; return true; } 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; } } function burn(uint256 _value) public returns (bool success) { require(balanceOf[msg.sender] >= _value); balanceOf[msg.sender] -= _value; totalSupply -= _value; Burn(msg.sender, _value); return true; } function burnFrom(address _from, uint256 _value) public returns (bool success) { require(balanceOf[_from] >= _value); require(_value <= allowance[_from][msg.sender]); balanceOf[_from] -= _value; allowance[_from][msg.sender] -= _value; totalSupply -= _value; Burn(_from, _value); return true; }}复制代码

然后把这段代码拷贝到Solidity,点击旁边的Details获取部署代码

然后在弹出层中复制WEB3DEPLOY中的代码到编辑器中

修改代码如图中所示

然后将代码复制到geth命令行中,按回车。然后执行miner.start(),如果出现以下信息则表明代币部署成功

如果出现Error: authentication needed: password or unlock undefined错误,是因为账户没有被解锁,执行personal.unlockAccount(eth.accounts[0])然后输入密码解锁账户

接着我们在命令行中输入tokenerc20则可以看到返回的接口信息

address,表示合约地址

可以利用balanceOf函数查看地址的代币余额

至此,合约部署完毕

下一篇文章说说ERC20空投合约的三种实现方式

这里有本人写的适合新手的小项目,有意戳-->8个适合新手的Python小项目(本人所写)

(8个小项目需要付费,一杯水的价钱)

本文章是由热衷python和前端原创发布,如需转载请注明出处

欢迎大家关注头条号:热衷python和前端

如果有需要源码的同学就留言或者私聊我吧

标签: #ubuntu创建tap