Bulk Withdrawal ERC20 Tokens
Overview
The ERC20 Bulk Withdrawal enables you to send multiple token transfers to different addresses in a single transaction. This functionality utilizes a special batcher contract to combine multiple token transfers, reducing gas costs and simplifying transaction management compared to sending multiple individual token transfers.
Key benefits:
- Lower gas costs: Consolidate multiple transfers into a single on-chain transaction
- Simplified transaction management: Single approval workflow for multiple transfers
- Supported on multiple EVM chains: Available on Ethereum, Polygon, Arbitrum, Optimism, and other EVM-compatible networks
Technical Details
When using the bulk withdrawal feature:
- Your transaction is processed through a batcher contract specific to your network.
- The contract calls
batchTransferFromto send tokens to multiple recipients. - The batcher contract uses the ERC20
transferFrommethod to move tokens from your wallet to the recipients. - The transaction appears on-chain as a single contract interaction.
- Each recipient receives their tokens directly from your wallet.
Limitations
- All transfers in a batch must use the same token type.
- Maximum batch size varies by network (typically around 100 recipients per transaction).
- Batch transfers are not supported for CryptoPunks and other non-standard ERC20 tokens.
Prerequisites
- Get Started
- Create Wallets
- Deposit Assets
- Enable Bulk Withdrawals of ERC20 Tokens
- Have sufficient balance of the native coin to cover gas fees.
1. Build a Bulk Withdrawal Transaction
To create a bulk withdrawal transaction, you'll provide multiple recipients in your transaction request, each specifying the recipient address and amount.
async function buildBulkTokenWithdrawal() {
const walletInstance = await bitgo
.coin('opeth')
.wallets()
.get({ id: '<YOUR_WALLET_ID>' });
// Build a transaction with multiple recipients
const buildResult = await walletInstance.prebuildTransaction({
recipients: [
{
address: '0x1111111111111111111111111111111111111111',
amount: '100000000'
},
{
address: '0x2222222222222222222222222222222222222222',
amount: '200000000'
},
{
address: '0x3333333333333333333333333333333333333333',
amount: '300000000'
}
],
tokenName: 'opeth:usdc'
});
return buildResult;
}POST /api/v2/{coin}/wallet/{walletId}/tx/build
{
"recipients": [
{
"address": "0x1111111111111111111111111111111111111111",
"amount": "100000000"
},
{
"address": "0x2222222222222222222222222222222222222222",
"amount": "200000000"
},
{
"address": "0x3333333333333333333333333333333333333333",
"amount": "300000000"
}
],
"tokenName": "opeth:usdc"
}In a bulk withdrawal transaction, the recipients array is consolidated into a single transaction that interacts with the batcher contract. The batcher contract then distributes the tokens to each recipient address according to the specified amounts.
2. Sign and Send Transaction
After building the transaction, sign it and send it to BitGo for processing. The transaction signing process follows the standard pattern for your wallet type.
async function sendBulkTokenWithdrawal() {
const walletInstance = await bitgo
.coin('opeth')
.wallets()
.get({ id: '<YOUR_WALLET_ID>' });
// Build, sign and send in one operation
const result = await walletInstance.sendMany({
recipients: [
{
address: '0x1111111111111111111111111111111111111111',
amount: '100000000'
},
{
address: '0x2222222222222222222222222222222222222222',
amount: '200000000'
},
{
address: '0x3333333333333333333333333333333333333333',
amount: '300000000'
}
],
tokenName: 'opeth:usdc',
walletPassphrase: 'VerySecurePassword1234',
});
return result;
}Step Result
The response includes the transaction details and the status of the transaction:
{
"transfer": {
"coin": "opeth:usdc",
"id": "63727a81cdbc820007b27caa7b76016d",
"wallet": "63726fde0a3c94000758f2790536041d",
"txid": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"height": 0,
"date": "2023-11-14T17:27:29.128Z",
"type": "send",
"value": "-600000000",
"valueString": "-600000000",
"baseValueString": "-600000000",
"baseValueWithoutFeesString": "-600000000",
"feeString": "0",
"payGoFee": 0,
"payGoFeeString": "0",
"state": "signed",
"instant": false
},
"txid": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"status": "signed"
}See Also
Updated about 1 hour ago