๐ The Blaze Papers / BLAZE Multisender
๐ธ BLAZE Multisender
Batch-send BLAZE โ or any Sonic ERC-20 token, native S, or any ERC-1155 NFT collection โ to a whole tribe in one transaction. We didn't build the contract that moves the assets; here's exactly who did, and what it does under the hood.
Three choices, every time
๐ฅฑ degen tl;dr
The page always asks you three things, same order every time: what to send (Sonic's native S, an ERC-20 token, or an ERC-1155 NFT collection), how to type your recipients in (a row-by-row editor โ the default โ or paste a block of text), and how to decide the amounts (type each one yourself, split one amount equally, or divide one total across everyone). Mix and match freely โ none of them lock you out of the others.
๐ค the nerd stuff
What to send: native S and ERC-20 share one picker โ BLAZE is the
default and the visually "hero" pick (it's our own token), with USDC/USDT/wS/EURC.e as
verified quick-picks alongside a paste-any-address importer that reads
symbol()/decimals() live.
ERC-1155 gets its own picker,
seeded from the same collection registry the NFT Viewer uses, plus its own importer
that checks supportsInterface(0xd9b67a26) (the ERC-1155 EIP-165 id) before
accepting an address. Picking a preset and importing a custom asset are mutually
exclusive โ selecting one always clears the other.
How to enter recipients: Manual Input is a row editor โ address, amount,
and (for ERC-1155) a Token ID field per row, with a + Add Recipient button
and a per-row remove button. Structured Data is the original paste-a-block textarea
(address amount, or address amount tokenId for ERC-1155),
with a worked example shown above the box.
Values separate on a space, comma or tab;
blank lines and # notes are ignored.
Switching between the two carries your data across in both directions โ nothing typed
gets silently dropped.
How to decide amounts: these live with Manual Input, because they fill in numbers you did not type โ a pasted block already carries its own amounts, so the choice is hidden in Structured Data. Custom Amounts is the default: you type every number yourself.
Equal Amounts fills every row with one "amount per recipient" value. Divide Total takes one grand total and splits it across every recipient using exact BigInt division โ see the remainder note below. Until you press โก Distribute, rows awaiting an amount are counted as recipients but the Send button stays disabled, so a zero can never be signed.
ERC-1155 NFTs โ a third asset kind
๐ฅฑ degen tl;dr
You can now batch-send NFTs from a 1155 collection, not just BLAZE/tokens/S. Amounts here are item counts, not decimals โ "1.5 NFTs" isn't a thing, so the page refuses fractional amounts outright. Each recipient row needs a Token ID, since a collection can hold many different tokens.
Approval works differently too: instead of approving a
specific amount, you approve the whole collection once (setApprovalForAll),
and the page skips that step automatically if you've already approved Scatter before.
๐ค the nerd stuff
Scatter's ERC-1155 function is
scatterERC1155Token(address token, address[] recipients, uint256[] amounts, uint256[] ids) โ
note ids is the last argument, not interleaved with
amounts.
The page reads live approval state with
isApprovedForAll(you, scatterAddress) and only prompts for
setApprovalForAll(scatterAddress, true) when that comes back false โ never
an amount-based approval, because there isn't one for ERC-1155. Balances are checked
per distinct token id in your batch via balanceOf(you, id), and the page
tells you plainly if you don't hold enough of a specific id, rather than letting you
find out from a failed transaction.
Divide Total: exact math, remainder handled honestly
๐ฅฑ degen tl;dr
Split 100 BLAZE three ways and you don't get a clean number โ someone has to eat the remainder. The page never rounds it away or drops it: the leftover smallest unit goes to the first recipient in your list, and the total the page shows always adds back up to exactly what you typed, to the very last decimal.
๐ค the nerd stuff
Divide Total converts your entered total to the asset's base units (BigInt, via
ethers.parseUnits), divides by the recipient count with integer division,
and adds the remainder โ total % n โ to the first recipient's share. For
100 BLAZE (18 decimals) across 3 recipients that's
33.333333333333333334 to the first and
33.333333333333333333 to the other two โ summing back to exactly
100.000000000000000000.
This is plain BigInt arithmetic, never floating-point, so it is exact for every total and every recipient count, not just this example.
One button, not two
๐ฅฑ degen tl;dr
The page used to show separate Approve and Send buttons. Now there's one button that changes its own label depending on where you are: Connect wallet if you're not connected, Approve BLAZE (or whichever asset) if it needs approval first, then Send batch once you're clear to go.
A small "Step 1 of 2 / Step 2 of 2" line above the button always tells you where you stand โ and native S skips straight to Send, since there's nothing to approve.
๐ค the nerd stuff
The button's label, action and disabled state are recomputed from current state on every render โ connection status, the selected asset, the parsed batch, and live allowance/approval โ so it can never show one label while wired to a different action.
After a successful approve, the page re-reads the fresh allowance or approval state and the same button flips itself to Send automatically; sending itself always stays an explicit second click, since that's the step that actually moves your assets.
Both the approve click and the send click independently re-check that your wallet is really on Sonic right before firing โ not just once at connect time โ because a wallet can switch networks between the two clicks.
Who actually built this
๐ฅฑ degen tl;dr
The batch-send engine is Scatter, built by 0xJijimi and given away for free under the MIT license. We didn't write a line of the contract that moves your tokens โ we just wrapped it in a BLAZE-flavoured UI with a preview, a cap, and honest math. Full credit, always, right at the top of the tool, not buried down here. ๐ซก
๐ค the nerd stuff
Contract: Scatter by 0xJijimi, deployed on Sonic
Mainnet at
0xe907b1f554214129935820fdb8d7e771e1951d67, verified on
SonicScan.
Source (MIT license): github.com/0xJijimi/scatter, dapp at scatter.jijimi.online.
It is third-party code and not audited by us โ we read the source ourselves before integrating it, but that is not the same thing as a professional audit, and we are not claiming it is. The multisender page is UI only: it builds a call, your wallet signs it, and Scatter does the actual moving.
Approve, then send
๐ฅฑ degen tl;dr
Two clicks. First you approve the exact total Scatter needs โ never an unlimited allowance, only ever the batch total. Then you send, and Scatter pays every recipient in your list, one by one, in a single transaction. Native S skips the approve step entirely โ there's nothing to approve for a plain S transfer.
๐ค the nerd stuff
For an ERC20 token, Scatter's scatterERC20Token(token, recipients, amounts)
calls transferFrom(msg.sender, recipient, amount) once per recipient โ it
pulls tokens directly from your wallet, which is why an approval is required first.
The
page sets that approval to the exact sum of the batch via
approve(scatterAddress, total), never
type(uint256).max, so a compromised or buggy Scatter deployment could never
move more than the batch you just reviewed.
For native S, scatterNativeCurrency(recipients, amounts) is called with
msg.value set to the batch total. The contract requires
msg.value >= totalAmount, pays each recipient with a raw call, and
refunds any excess S back to the sender โ so sending a little extra is
safe, it just comes back. No approval step applies to native currency at all.
The Scatter contract address is hardcoded in the page โ it is never read from user input and never derived โ because this tool moves real balances and the address your wallet is asked to approve/send to must not be influenceable by anything on the page.
The BLAZE transfer-tax caveat
๐ฅฑ degen tl;dr
BLAZE burns a tiny 0.042% on every single transfer. Scatter sends one transfer per recipient, so with BLAZE selected, everyone on your list gets a hair less than the number you typed. The page says this plainly in the preview โ it is not a Scatter fee, it's the BLAZE token contract doing what it always does.
This caveat is BLAZE-specific: other tokens, and native S, don't carry any transfer tax, so the page doesn't show the warning for them.
๐ค the nerd stuff
One consequence specific to BLAZE: because the token burns before it spends the allowance, a batch approved for exactly its total leaves about 0.042% of that total still approved to Scatter afterwards. The page now offers to clear it โ once a batch lands, a ๐งน Revoke it control appears alongside the button and sets the approval back to zero in one press.
The same control does the more important job on the NFT side. ERC-1155 batches need
setApprovalForAll, which has no amount and no expiry โ Scatter stays an
approved operator over the whole collection until somebody turns it off. After an NFT
batch the control offers exactly that.
Why clean up afterwards instead of approving less up front? Scatter is a third-party contract and its ERC-20 path is not verified on SonicScan, so we cannot tell from outside whether it moves tokens once per recipient or pulls the total first. Approving less on a guess about its internals would revert real batches.
Revoking after the fact is correct either way, and it also clears anything left behind by earlier batches.
Missed the in-page control, or left a batch's approval standing from before it
existed? ๐งน The Great Revoker finds every approval your
wallet has ever granted on Sonic โ including a leftover Scatter allowance from a
multisend batch โ and clears it the same way: approve(spender, 0) or
setApprovalForAll(spender, false), never anything more.
BlazeToken's auto-burn tax (burnPercentage = 42 / 100000 =
0.042%) applies to every transfer while
totalSupply() > 3.18e9 โ including the individual
transferFrom calls Scatter makes on your behalf.
Since Scatter moves BLAZE with N separate transfers rather than one bulk move, the tax is deducted N times, once per recipient, exactly like any other BLAZE transfer. There is no way to route around this from the UI, because it's a property of the token contract itself, not of Scatter or this page.
What this tool checks for you
Every pasted batch is parsed strictly: a bad address or a malformed amount fails the whole batch with the exact line number, rather than silently dropping the bad line and sending an incomplete batch. Duplicate recipients are flagged as a warning (both sends still go through โ that's a doubled total, not a bug).
All the
math โ the total, the per-recipient amounts, the balance check โ is done in exact
integer (BigInt) arithmetic using the selected token's own decimals, never floating
point, so nothing drifts. A custom pasted ERC20 is checked for real bytecode
(eth_getCode) and a working symbol()/decimals()
before it's accepted; an ordinary wallet address or a non-token contract is rejected
with a clear message.
There's a hard cap on recipients per batch so the page can never build an unbounded client-side loop, and a softer warning above ~200 recipients as a gas heads-up.