简体中文
back

如何搭建ERC20代币批量转账接口

作者: 太壹科技 发布于: 2020-08-06 17:35:41

BTC或许是加密数字货币之王,但ETH也有着自己最友善的头衔——最受欢迎数字代币平台。ETH作为一个公共区块链平台,具备着开源的智能合约功能,许多的代币发行通过ETH进行,而代币常见的是ETH上一个遵守着ERC20规范的智能合约。



假如一个ETH智能合约能够实现下面的接口,那此智能合约就是一个ERC20代币。

 

// ----------------------------------------------------------------------------

// ERC Token Standard #20 Interface

// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md

// ----------------------------------------------------------------------------

contract ERC20Interface {

    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);

}

 

显而易见的是,ERC20规范里仅仅存在点对点转账的transfer和transferFrom,现实情况下可能存在要向1000-10000个地址转账的情况,那我们就要生成上万个transfer交易,不得不考虑这样的效率太低了

 

因此许多ERC20代币都能够实现批量转账的接口。

例如一则爆出漏洞的BEC(https://etherscan.io/address/0xc5d105e63711398af9bbff092d4b6769c82f793d#code)实现了batchTransfer函数。

 

SMT(https://etherscan.io/address/0x55f93985431fc9304077687a35a1ba103dc1e081#code)也实现了allocateTokens函数。

 

上述这些能够实现一笔ETH交易完成对多个账户的代币转账或初始化的场景

 

文章中提及了一种完成一对多转账的方法,这个方法被称之为transferMultiple

 

第一步文中里默认已用SafeMath库

 

然后,transferMultiple

transferMultiple完成了从msg.sender向count个_tos地址转账的场景同时_tos[i]得到_values[i]的代币。

 

首先,进行对于1个for循环前置检查,从而保证每个_tos地址都非0地址,另外还需要计算转账的总额,并将其录入到total变量。在运算操作时,为避免溢出,可以采用SafeMath库,值得注意的是,每一次都要当前计算出来的总额total和上一笔总额total_prev进行对比从而保证total大于等于total_prev,双重校验不会整数溢出避免导致出现转账故障的情况

 

其次,对于2个for循环采用修改内部变量,但不调用transfer方法原因在于之前已经做了前置检查,倘若再调用transfer函数的话,程序会执行额外的没有必要的前置检查,这样gas增加消耗。

 

function transferMultiple(address[] _tos, uint256[] _values, uint count)  payable public returns (bool success) {

        uint256 total = 0;

        uint256 total_prev = 0;

        uint i = 0;

 

        for(i=0;i<count;i++){ require(_tos[i]="" !="address(0));" total_prev="total;" total="SafeMath.add(total," _values[i]);="" require(total="">= total_prev);

        }

 

        require(total <= balanceOf(msg.sender);

 

        for(i=0;i<=count-1;i++){

            balances[msg.sender] = SafeMath.sub(balances[msg.sender], _values[i]);

            balances[_tos[i]] = SafeMath.add(balances[_tos[i]], _values[i]);

            Transfer(msg.sender, _tos[i], _values[i]);

            //上面的3可改为下1行,它的优点在于无需假设用户剩余资产存储在类型为mapping的balances这个变量中,它的劣势是会额外增加一些没有必要的前置检查,导致额外消耗gas

            //transfer(_tos[i], _values[i]);

        }

 

        return true;

    }

此时,相信各位比较在意的是,用transferMultiple一次完成110000转账能否成功?

测试可以显示140转账的情况下,消耗的gas大致在130万上下如果ETH一个区块的gas上限大为800万,那么,1完成1240转账就将区块的gas上限占满了。假如出现单次转账的收款对象数量太多的情况也会出现超出区块gas上限而致使双方交易无法完成的结果基于以上的问题,在遇到优盾钱包这个开放平台后,我果断放弃了之前的研究,通过API直接对接交易所,免节点同步,便捷又省心。

 

太壹科技邀您试用

了解开设交易所及其他业务和相关运营的全部信息

请录入您的联系电话和您的称呼

我们的服务专家会在第一时间与您取得联系,请务必留意

在线客服

在线客服

申请试用

申请试用