以太坊智能合约之批量转币

一直想写这篇教程来着,由于你会发现网络上不多有关于批量转币的详尽的教程,一些提供该工具的网站也并不会将其智能合约代码开源出来。虽然最终咱们会发现原来这个批量转币的智能合约原来就这么几行代码就够啦,可是整个流程不明因此的话,给你这个合约代码我相信你也是用不了的,所以对于新手来讲想要写出这个功能多少仍是有不小的难度的。html

批量转币其实也属于 空投的一种,所谓空投,笔者的理解是利用程序或者人工的方式,将代币发放至目标帐户。

注意:这里所说的代币均指代的是 ERC20 Token,对于更新的代币例如 ERC721 Token 等,因为自己就优化了这方面,所以不须要咱们这样折腾。编程

用途

咱们为何须要批量转币这样的智能合约呢?数组

  1. 大大节约转币的资金成本。很明显,若是咱们人工一次次的进行转币操做,那么转个几百次所须要的 gas 费用会让你吃一惊。可是使用这个批量转币的智能合约,通常来讲,两百次左右能够一次性操做完,那么也就是两百次转币费只须要支付一次转币费便可。
  2. 大大节约转币的人工成本。和支付费用成本相似,让你手工转个几百次估计怕是要疯掉了。
  3. 有足够的需求。前面也讲到,新的 ERC721 Token 等不须要咱们这样折腾,可是目前 ERC20 Token 几乎是绝大多数代币的模板,所以需求足够大,也就是应用场景足够大。

前置知识点

  1. 合约调用合约
  2. 受权转帐方法

合约调用合约

要在智能合约中调用其余合约,就须要了解抽象合约的概念,具体细节能够看这里安全

以本文所要讲的转币合约为例,咱们要在合约中调用 ERC20 Token 的 transferFrom 方法,那么咱们首先要先建立一个 ERC20 Token 的抽象合约,代码以下:网络

/**
 * @dev ERC20 Token abstract constract.
 */
contract ERC20Token {
    function transferFrom(address, address, uint256) public returns (bool);
}

由于咱们只须要用到代币的 transferFrom 方法,所以咱们只须要声明该方法便可,注意是没有函数体的空方法。编程语言

那么咱们在批量转币的合约中如何进行调用呢?和大多数面向对象的编程语言同样,咱们只须要建立这个代币合约,而后调用这个代币合约实例的受权转帐方法便可,代码以下:函数

/**
    * @dev calls the ERC20 token's transferFrom function
    * @param _token address The address of ERC20 token.
    * @param _dsts address The addresses which be air dropped.
    * @param _values uint256 The token values that each address will receive.
    */
function transfer(address _token, address[] _dsts, uint256[] _values) 
    public
    payable
{
    ERC20Token token = ERC20Token(_token);
    for (uint256 i = 0; i < _dsts.length; i++) {
        token.transferFrom(msg.sender, _dsts[i], _values[i]);
    }
}

咱们的批量转币代码是否是很是简单~能够看到,咱们首先建立了 ERC20 Token 的合约实例,而后循环要转币的地址列表,每次遍历中调用目标 ERC20 Token 的 transferFrom 方法便可。工具

这个函数能够作的更好:对于代码边际判断,咱们能够判断一下 _token 以及 _dsts 是否均为合法帐户,或者判断一下 _values 是否均为合法正数值,又或者比较一下 _dsts 和 _values 的数组长度是否相等(健壮的代码必定是边际安全的)。。。是否还能完善的更好一些?固然是能够的,好比咱们增长一个 Event 事件供调用者监听以便作出相应处理。。。

受权转帐方法

那么是否是上面的这些代码就足够了呢?对于批量转币合约来讲核心代码就是这些。区块链

可是!有个前提!优化

咱们在使用这个合约转币前,须要受权给这个合约必定的代币数额受权给这个合约必定的代币数额受权给这个合约必定的代币数额

这里就引出了受权转帐的概念,仍是以批量转币为例:

首先咱们须要明确,假如你拥有 1000 个 SIM 代币,那么这些代币就独属于你,没人能拿走(别给我瞎扯什么被盗啊之类的状况,讲例子的时候咱们纯真些。。。)那么若是你啥也不作,想要让转币合约可以转走你的 SIM 代币,显然这是不可能的,由于是你拥有这些代币,而不是转币合约拥有。

因此此时你就须要把本身的 SIM 代币受权给转币合约,至于受权多少看你要转多少。一旦你完成受权操做,那么转币合约就有权利将你的代币进行转帐操做了(等下,我能够以后忽然改主意取消受权吗?能够,你再次受权一次,数目为零便可。)

案例

笔者以前花了点时间作了一个 Web 页面,将批量转币的功能作在了上面,下面咱们简单的看下整个流程,配合示例图会更加清晰 :)

获取代币信息

第一步主要是获取用户须要批量转帐的代币信息,经过用户填写的代币合约地址,而后获取到基本的代币信息。

填写转币数量和帐户

第二步主要是获取用户转币的数目和帐户信息,而后须要让用户受权相应数目的代币给咱们的转币合约。

确认并空投

第三步主要是让用户确认信息,并开始空投。

这是批量转 ERC20 代币的交易记录:
Ropsten Transaction 0x630b868e41ecfbd97273371ed33242439230355d9110095b814ae3029b88d829

扩展

这里笔者给新手们留个做业,若是我想要批量转 ETH 怎么办?若是直接使用上面的代码可很差使哦,可是思路是一毛同样的,并且代码上会更简洁~

附上一个批量转 ETH 的交易记录:
Ropsten Transaction 0x4fcfc6245d7ffecfae7c02eb2f983f203806b83b5a1cf2fc0450a61d7c226401

哦,你们可能还会看到另一种批量转币的合约代码的写法,代码以下:

bytes4 id = bytes4(keccak256("transferFrom(address,address,uint256)"));
token_address.call(id, msg.sender, _dsts[i], _valus[i]);

这在低版本的 Solidity 中是能够正常运行的,由于本质上和上面讲的是同样的,但在高版本中废弃了该用法,所以笔者在尝试高版本中使用会出现每次批量转币的最后一次老是会失败。因此推荐的作法是经过抽象合约的方式进行调用其余合约的方法。

最后,但愿你们在区块链的世界中玩的开心~

相关文章
相关标签/搜索