Batch-sending ERC-20 tokens
When sending a lot of tokens, or airdropping them, it costs a lot of gas.
Batching multiple token-sends into a single transaction can be a good way to reduce the overall transaction fees.
Batching will reduce the overall gas spend of the transaction, measured in gas (this is just a number, no magic). A blank transaction always costs 21000 gas. Token transfers cost around 60000 gas. (The gas price is a seperate concept that says how much you are willing to pay per unit of gas.)
When sending a token, you call the token contract’s
transfer method. If successful, it emits a
Transfer() event. This costs gas, and there is no way around that.
Even when batching N token transfers, you’ll need to call
transfer N-amount of times and emit N-amount of
Transfer() events. However, with batching, the transaction overhead can be removed.
The gas price of doing a
transfer is typically around 60K, where the TX overhead consists of around 21K. Batching n transactions will therefore save us
21K * (n-1) gas.
This is good news. However, there is no way to directly batch-send tokens in a normal wallet. You will need a smart contract wallet to do it.
We can use a Gnosis Safe to batch send tokens.
To test this, I sent a bunch of token transfers in a batch, and then seperately.
Cost per transfer
OP-token on Optimism (single transfer)
57K gas (tx)
OP-token on Optimism (5 transfers)
224K gas (tx)
OP-token on Optimism (10 transfers)
380K gas (tx)
OP-token on Optimism (20 transfers)
693K gas (tx)
ARB-token on Arbitrum (single transfer)
668K gas (tx)
ARB-token on Arbitrum (5 transfers)
2.1M gas (tx)
ARB-token on Arbitrum (10 transfers)
ARB-token on Arbitrum (20 transfers)
4.7M gas (tx)
The gas amount vary based on the ERC-20 contract implementation and the chain.
We see that batching gives significant gas improvements.
For the OP-token, the numbers were the same when doing the same experiments over again, whereas for ARB, the numbers varied slightly (~5%). My guess is that this has to do with something in the contract implementation or the Arbitrum chain.
Initiating these transfers can be done through the UI with the CSV airdrop tool, but also programatically (no difference in outcome).
When doing the tests, I made sure to always send tokens to brand new (non-existing) addresses, as sometimes subsequent transfers to the same address have lower gas costs.
There are some hard limits. Transferring to an existing address will always cost 5K, and to a new address 20K (for the SSTORE operation) so they are floors even if you could amortise the rest of the function cost over hundreds of transfers. - jgm-orinoco on reddit
If you are making your own token, you can add some methods to the contract to squeeze out even more gas savings on batched transfers.
The obvious saving with batching is the
21000base gas cost for the transaction, so batching n transactions saves
21000(n-1)gas. If the batch transfer function is part of the token contract code then savings could be reduced further by
5000(n-1)by only updating the sender's balance once. - jgm-orinoco on reddit
By adding a method like
batchSend, you make batching possible natively. You’ll save
5000 gas per transfer, but you also remove the need of using a seperate smart contract to do the
Batch-sending ERC-20 tokens is a highly efficient method for reducing gas costs and optimizing transactions.
But you’ll need to weigh the complexities of having the gnosis deployed. Sometimes, the easiest is the best, even if it costs more gas.