系统公告:Tronapi PRO 已正式发布。更低费率,更高安全性!详情请访问:https://doc.tronapi.com

USDT.TRC20 批量转账的实现方案

Tronapi官方 原创
2021-02-04 16:53:22

数字货币支付系统,会涉及到一个“批量提现”的功能。

用户提交的提现申请数据如下:

    
    {
        coin: "USDT.TRC20",
        withdrawals: [{
            "amount": "44",
            "address": "TBbwsgwD2QGKmZjExupKNo2JCvNAjbjeVC"
        }, {
            "amount": "56",
            "address": "TPKY9KxTfsP6TSxibSrJv5yuzs8UZkioDu"
        }]
    }
    

接收到上述数据之后,需要从系统的资金账户,一次性批量向多个地址进行转账操作。

理论上,可以搞一个循环,然后一条一条的发,但这样做的话,一是你消耗的手续费用会让你大吃一惊,二是操作的基数上去了,异常的概率也会大幅上升。

那有没有批量一次性的方法,可以解决这个问题呢?

答案就是:在智能合约中,调用另外一个实现有批量转币功能的合约。实现效果如下:

交易详情链接:https://shasta.tronscan.io/#/transaction/585f469c4661a076250118787d294d68c987eb95d806d5c912443893f24ffab5

下面介绍一下实现步骤。

首先,我们需要实现一个批量转币的合约,合约代码如下:

    
    pragma solidity ^0.4.16;

    import './TRC20.sol';

    contract Multiplexer {

        // 批量转 TRX
        function sendTrx(address[] _to, uint256[] _value) payable returns (bool _success) {
            assert(_to.length == _value.length);
            assert(_to.length <= 255);
            uint256 beforeValue = msg.value;
            uint256 afterValue = 0;
            for (uint8 i = 0; i < _to.length; i++) {
                afterValue = afterValue + _value[i];
                assert(_to[i].send(_value[i]));
            }
            uint256 remainingValue = beforeValue - afterValue;
            if (remainingValue > 0) {
                assert(msg.sender.send(remainingValue));
            }
            return true;
        }

        // 批量转 Token
        function sendToken(address _tokenAddress, address[] _to, uint256[] _value) returns (bool _success) {
            assert(_to.length == _value.length);
            assert(_to.length <= 255);
            TRC20 token = TRC20(_tokenAddress);
            for (uint8 i = 0; i < _to.length; i++) {
                assert(token.transferFrom(msg.sender, _to[i], _value[i]) == true);
            }
            return true;
        }
    }
    

上述合约实现了两个方法,一个是批量转 TRX,一个是批量转 Token(如 USDT.TRC20)。看代码是不是非常简单?其实内部还是用了一个循环。注意,在 sendToken 方法中,有引用并调用一个 TRC20 的“抽象合约”(关于抽象合约,可阅读:https://docs.soliditylang.org/en/v0.4.24/contracts.html#abstract-contracts)。因为是抽象合约,而且我们只用到它的 transferFrom 方法,因此,它的完整代码如下:

    
    pragma solidity ^0.4.16;

    contract TRC20 {
        function transferFrom( address from, address to, uint value) returns (bool ok);
    }
    

将上述批量转币的合约进行部署,得到合约地址。

 在使用这个批量转币合约之前,还需要做一件事,就是授权这个合约一定的资产数额。在批量提现的场景,就是累计提现的金额。怎么做呢?很简单,就是调用授权合约的 approve 方法,示例代码如下:

    
    // 空投合约的合约地址
    const multiContractAddress = "TG9rv435qUKmPaT8fPbb9jBhhS3sEZ6XxP";

    // 授权
    await usdtContractInstance.approve(
        multiContractAddress, // 
        10000, // 这里是批量转的累计金额
    ).send();
    

最后的最后,还需要确保授权合约,有一定数量的 TRX 余额,用于批量转账的手续费用(虽然只需要支付一次的转币费)^_^

更多详情可访问:https://github.com/GG4mida/tronpay-contract-airdrop