ETH$3,420
Tools/airdrop

Airdrop tool

Batch-send an ERC-20 to hundreds of wallets from one approval, with a contract that never holds your tokens.

HoodAirdrop sends an ERC-20 to hundreds of wallets from one approval and one transaction. It is 94 lines long, has no owner, holds no state, and never touches a balance that is not yours.

#Why it is safe

The entire safety argument is one design choice: each recipient is paid by its own transferFrom(msg.sender, recipient, amount). Tokens go straight from you to them and never pass through the contract.

  • The only allowance it can spend is the one you granted it, on the token you granted it for.
  • Nothing accumulates in it. There is no balance to rescue, nothing to sweep, and therefore no admin, no pause, and no upgrade path — none of those functions exist.
  • A mid-batch failure unwinds the whole batch. One bad row means the transaction reverts and nobody was paid; you fix the list and resend.
  • Fee-on-transfer tokens work unchanged. Balances are never pooled, so each recipient simply nets the token’s own fee and there is no internal accounting to throw off.
Reentrancy is unguarded on purpose
There is no state to corrupt, and a hostile token re-entering airdrop can only spend the caller’s own allowance against the caller’s own balance — something it could already do by calling the token directly. A guard here would cost every user gas to prevent nothing.

#The two calls

solidity
/// Per-recipient amounts. Caller must have approved at least the sum.
function airdrop(address token, address[] calldata recipients, uint256[] calldata amounts)
    external returns (uint256 total);

/// Same amount to everyone — half the calldata for the common case.
function airdropEqual(address token, address[] calldata recipients, uint256 amount)
    external returns (uint256 total);

event Airdropped(address indexed token, address indexed sender,
                 uint256 recipients, uint256 totalAmount);

Zero addresses and zero amounts revert with the offending index (ZeroRecipient(i), ZeroAmount(i)) — a zero row is a broken CSV, not an intent, and failing loudly with a position beats silently skipping it.

#Batching and gas

Batch size
Bounded only by the block gas limit. The app chunks at 300 recipients per transaction (~5.5–6M gas to fresh addresses).
Approval
An infinite approval is meaningfully cheaper: OpenZeppelin — and most ERC-20s — skip the allowance storage write when the allowance is type(uint256).max, and that saving repeats on every recipient.
Per-recipient events
None from this contract — the token’s own Transfer events already carry the detail. Airdropped is the indexable “a drop happened” row.

#Why a retry cannot double-pay

good to know
A long drop is several transactions, and the risky moment is a wallet that crashes after broadcasting but before recording. The app resolves this against the chain, not against local state: it reads the Airdropped events already emitted by your address for that token and resumes from the first batch that has none. Approval is also for the exact total rather than infinite when a drop is chunked, so even a pathological double-send runs out of allowance instead of running out of your balance.

#Practical notes

  • Deduplicate your list before sending. The contract will happily pay the same address twice if you list it twice — that is your CSV, not a bug.
  • Amounts are raw base units. An 18-decimal token means 1 token is 1000000000000000000; getting this wrong is the single most common airdrop mistake.
  • Sending to a token’s own address, to the zero address, or to a contract that cannot hold tokens is not prevented beyond the zero check. Check your list.
  • This works with any ERC-20, not just hood.dev launches — including LP tokens and tokens you did not deploy.

#Deployment

HoodAirdrop
Batch ERC-20 sender. Stateless and ownerless — it never holds a balance.

Verified on Blockscout — the source is short enough that reading it end to end takes a couple of minutes, which is the recommended way to trust it. See also Interfaces for the full ABI surface.

chain 4663·on-chain values read 2026-07-29·Blockscout