My dev blog where I dive deep into TypeScript, Postgres, Data science, Infrastructure, Ethereum, and more...

Batch-sending ERC-20 tokens

10th Jan 2024

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

Why does batching make transactions cheaper?

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.

Use a Gnosis Safe to batch send tokens

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.

Gas cost
Cost per transfer
Savings
OP-token on Optimism (single transfer)
57K gas (tx)
57K
OP-token on Optimism (5 transfers)
224K gas (tx)
45K
21% reduction
OP-token on Optimism (10 transfers)
380K gas (tx)
38K
33% reduction
OP-token on Optimism (20 transfers)
693K gas (tx)
35K
39% reduction
ARB-token on Arbitrum (single transfer)
668K gas (tx)
668K
ARB-token on Arbitrum (5 transfers)
2.1M gas (tx)
420K
37% reduction
ARB-token on Arbitrum (10 transfers)
2.8M gas (tx, tx)
280K
58% reduction
ARB-token on Arbitrum (20 transfers)
4.7M gas (tx)
234K
65% reduction

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

Extra optimizations with your own token

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 21000 base 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 batching.

Conclusion

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.


Tools