๐Ÿ“œ The Blaze Papers โ† back to sonicblaze.xyz

๐Ÿ“œ 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.