独立于ERC20-Token合约的批量转账合约示例
以太坊智能合约部署上线后,就无法修改了,不少遵循ERC20标准的Token合约已经上线交易,由于这类合约在开发的时候,没有编写批量转账函数,在需要进行大量转账的情况下(比如发工资),就得一笔一笔的执行转账交易。若遇见以太坊网络拥堵,转账手续费就变得很昂贵,若很多ERC20-Token都在执行一笔笔的交易,这又会反过来加剧以太坊的拥堵,形成了恶性循环。若有一个批量转账函数一次性处理多笔交易(比如150笔),就能大幅降低手续费成本,又不至于给整个以太坊网络添堵。
值得庆幸的是ERC20-Token都有一个标准的approve函数和一个标准的transferFrom函数,利用这两个函数可以做到批量转账:
function approve(address _spender, uint256 _value) public returns (bool success) {
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
uint256 allowance = allowed[_from][msg.sender];
require(balances[_from] >= _value && allowance >= _value && balances[_to] + _value > balances[_to]);
require(balances[_from] >= _value && allowance >= _value);
balances[_to] += _value;
balances[_from] -= _value;
if (allowance < MAX_UINT256) { allowed[_from][msg.sender] -= _value; }
Transfer(_from, _to, _value);
return true;
}
可以举个简单的例子说明这两个函数的典型用法:XX-Token的某一账户Alice可以调用approve这个函数授权Bob支配自己的账户(相当于Alice开了张一定额度的支票给Bob),然后Bob就可以调用transferFrom去转账消费Alice的XX-Token了。
若Bob不是一个普通账户,而是另一个合约账户呢?
利用approve开支票这个功能,可以部署一个独立于XX-Token的外部合约Airdrop,在该合约里循环调用XX-Token的transferFrom函数,实现批量转账。这时Alice只要先发送一笔交易调用XX-Toke合约的approve函数,给Airdrop合约账户(合约地址)开一张支票,允许其消费一定额度的XX-Token,然后Alice就可以仅仅发一笔交易(含有数组类型的参数,长度最好不要超过150),就可触发Airdrop的batch函数进行循环批量转账了,Airdrop合约代码如下:
pragma solidity ^0.4.0;
contract Airdrop {
//tokenAddr Token合约地址;toAddr 接收者地址集合;value 接收价值集合
function batch(address tokenAddr, address []toAddr, uint256 []value) returns (bool){
require(toAddr.length == value.length && toAddr.length >= 1);
bytes4 fID= bytes4(keccak256("transferFrom(address,address,uint256)"));
for(uint256i = 0 ; i < toAddr.length; i++){
if(!tokenAddr.call(fID, msg.sender, toAddr[i], value[i])) { revert(); }
}
}
}