Skip to content

Internals

Why it does that.

The reasoning behind the parts that decide whether a mint lands: the clock, the bid, the send, and the exit that comes after the race. You do not need any of this to use the bot. Start with the guide.

How it is built

Three parts, and the only one that ever holds a key is the one you run.

The cockpit

Browser
The page you operate. It reads contracts, simulates, builds transactions and shows state. It never holds a key and never sees a seed phrase.

The signer

Yours
Holds the keys and signs. Either the encrypted keystore in your own browser, or a process on a machine you control. It receives unsigned transactions and returns signed ones.

The box

Optional
A server that watches chains over persistent connections and fires pre-signed transactions from beside the network rather than from a phone.

Finding the mint call

Before anything can be timed, the bot has to work out what to send.

Most collections are not verified when they start minting, so there is no published list of functions to read. The bot works from the contract's own compiled code instead, and there are only two places a public mint can live.

Where the mint livesWhat the bot sendsHow it is found
On the collectionA call to the collection itselfIts published functions if it is verified, plus a list of the shapes projects actually ship.
On a routerA call to a shared contract that mints on your behalfThe collection is asked which routers it trusts. OpenSea's SeaDrop is the common one.

A candidate is only ever tried when its four-byte selector is physically present in the bytecode of whatever it is aimed at. Nothing is sent on a guess that the receiving contract has never heard of.

Which router, and whether there is one

The collection is asked first, because an OpenSea drop names its own routers. When it will not say, the bot falls back to SeaDrop's canonical address and reads the code there.

The price, and what counts as absurd

Where a router is in play, the price comes from the router's own sale record rather than from a getter on the collection. Either way the reading is checked against a ceiling, because a function named mintPrice on an unverified contract may return a timestamp, a supply, or nothing recognisable, and the only defence is that it is not a plausible amount of money.

Plausible depends on the token. Ten of a chain's gas token is a five-figure sum on Ethereum and ten dollars on a chain that prices gas in a stablecoin, so the ceiling is per chain:

ChainGas tokenPrice ceiling per token
EthereumETH10 ETH
Robinhood ChainETH10 ETH
BaseETH10 ETH
AbstractETH10 ETH
ApeChainAPE10 APE
InkETH10 ETH
MonadMON10 MON
MegaETHETH10 ETH
HyperEVMHYPE10 HYPE
SoneiumETH10 ETH
ArcUSDC25,000 USDC

Allowlist calls, one per wallet

The simulation finds a working call for one wallet, and an allowlist call carries that wallet's address and proof in its arguments. Copied to a second wallet, it reverts with certainty. So the simulation records the function it built as a signature, for example wlMint(uint256,bytes32[]), and every wallet's call is rebuilt from that signature by the same encoder, with its own address and its own proof.

The simulation and the open-watch both run as the first selected wallet that holds a proof, not the first one listed. A list that covers only some of the wallets therefore still simulates clean.

Before anything is signed, the final bytes of every wallet's call are checked for that wallet's proof, word for word. That check is on the bytes that will actually be sent, so it holds whatever path built them.

WalletWhat happensWhat the cockpit says
Has a proof, and its call carries itSigned and raced.Nothing extra.
Has no proofLeft out. Never signed, no nonce used.···4f2a not on the allowlist · racing without it
Has a proof its call does not carryLeft out, for the same reason.···4f2a left out · call would not carry its own proof
None of them passesArm stops. Nothing is signed.No selected wallet is on the allowlist

A wallet left out for any reason, this one or too little money, is not part of the race either, so it cannot hold the result open waiting for a transaction that was never sent.

Allowance lists

A list whose leaves are (address, amount) — “this wallet may mint 3” — is matched the same way, against both the packed and the OpenZeppelin double-hashed encodings, after the address-only shapes fail. A match returns each wallet's amount with its proof. The contract rebuilds the leaf from the arguments it is given, so the amount must also be in the call, in the argument it reads it from.

That argument is taken only from a verified contract's own ABI: a function with at least two uint256 inputs, exactly one of them named like an allowance (allow, max, limit, cap and similar). Unnamed arguments are never guessed, because a wrong slot is a revert. At Arm the server checks the final bytes of each call carry the wallet's own amount in exactly that slot; a wallet whose call does not is left out with ···4f2a left out · call would not carry its own proof.

Matching a large list

Leaves are hashed once per encoding and shared by every layout that uses it, the tree is built on raw bytes, and each proof is looked up by index. Trying every construction against a 50,000-address list that matches none of them took eleven seconds and now takes about five. A list already matched is cached on the server by chain, contract, root and the list's own digest, so pasting it again for another Arm costs nothing, and the proof route may run for up to a minute rather than being cut off by the platform's default.

Signed allowances

For a signature-gated sale the server asks the project's own endpoint once per selected wallet, checksummed address first, then lowercase, and takes the first 65-byte signature anywhere in the answer. An allowance is taken only from a numeric field named like one. Nothing else in the answer is used. The signature goes into the wallet's bytes argument; the simulation then runs as a signed wallet, and because the message a contract checks differs by project, the contract's own answer to that call is the only check that cannot be wrong. At Arm, a wallet with no signature is left out, and so is one whose call does not carry its own.

Lists the contract keeps itself

When the bytecode carries a membership getter such as isAllowlisted(address), the cockpit asks it about every selected wallet as soon as the simulation has found it. Any non-zero answer counts as on the list, because the same getter is as often an allowance (“may mint 2”) as a flag. A getter that reverts or returns nothing readable has not answered, and an unanswered wallet is never left out.

At Arm the server reads the list again itself; the browser only says which getter. A wallet is left out only on a clear no that its own call agrees with: if the getter says no but that wallet's call would pass, it races, because a getter can be named like a list and mean something else. Before the sale opens every call reverts, so there the getter's answer stands on its own. Only the getters the gate check looks for can be called; the list check is not a general call relay.

Firing on time

Reacting to the opening block is already too late. So it does not react.

A sale opens when a block's timestamp crosses the start time. By the moment any watcher can observe that block, the block is built and sealed. Anything that waits to see the open has already missed the opening block, and no amount of connection quality changes that. It is true of a server beside the sequencer and it is true of a phone.

So the bot fires before the open, by roughly the time it takes a send to travel:

fire at:  opensAt − measured send latency

Which requires knowing what time it is on the chain, and your device does not. Clocks drift, and the drift is often larger than the margin that decides the race.

Block times

Measured, not quoted: the timestamp span of the last 2,000 blocks divided by 2,000. They set how often the open-watch and the clock read, how long a bid waits before it is outbid, and how the risk of landing a block early is shown.

ChainSeconds per block
Ethereum12
Robinhood Chain0.1
Base2
Abstract0.8
ApeChain0.9
Ink1
Monad0.3
MegaETH1
HyperEVM1
Soneium2
Arc0.5

The chain clock

Each block header carries the time it was produced. Sampling headers and keeping the maximum of timestamp − observedAt gives the chain's clock, because network delay only ever makes a sample look older than it is. Delay can only bias one way, so the extreme is the truth and the noise is everything else. A read that fails moves the clock to the chain's next endpoint, so one endpoint being down cannot leave the schedule without a clock.

What it aims at

The opening time is read when you arm and kept with the race. Looking at another contract while a ladder is held changes what the screen shows, never when the held ladder fires. It used to read the screen, so a glance at another contract could aim the held ladder at that contract's opening time.

The fee ladder

Several rungs of the same purchase, signed before the open, at rising prices.

The clearing price of a contested mint is not knowable in advance. Bid low and you are not included; bid the maximum every time and you overpay on every quiet mint. So the bot signs a ladder: the same purchase at several fee levels, all prepared before the sale opens.

ValueWhy
Rungs6Enough resolution to find a price without spraying.
Top, with no gas budget12× the starting bidCap and tip alike. A contested mint can clear far above the quiet price. A wallet's balance only ever lowers it.
Top, with a gas budgetThe budgetThe top rung's cap is the budget and its tip is the budget less the room kept for the base fee: the budget is spent on priority, not on headroom.
Floor between rungs10%The network's own minimum for replacing a pending transaction. A smaller step is simply rejected.
On order-of-arrival chains4 rungs, no spanPaying more does not move you up a queue that is not sorted by price.

Every rung is capped by what the wallet can actually afford and by the gas budget you set, so a ladder never signs a rung that would bounce. Those are caps, never targets: money sitting in a wallet is not a reason to bid more. Every rung keeps the room the starting bid had for the base fee to rise, and when the floor between rungs leaves no room for all 6, the ladder has fewer rungs with the top one still exactly on the budget.

Which rung is sent first

Rung 0's tip is the median of the last five blocks' tips at the setting's percentile, read with eth_feeHistory, so one empty or one spiked block cannot set it. That is what a quiet block cleared at, not what a contested opening block will. The rungs above it used to be reachable only by replacement, and a replacement cannot enter a block that has already been built. So on a chain that sells ordering, the opening bid is the only bid that competes for block one, and each setting now chooses it:

SettingRung 0 tipSent firstRoom for the base fee to rise
Safe50th percentile of recent tips, or 1 gwei when history is unreadableRung 02× the base fee
Fast80th percentile of recent tips, or 3 gwei when history is unreadableRung 12.5× the base fee
Nuke95th percentile of recent tips, or 8 gwei when history is unreadableThe top rung4× the base fee

A setting never opens below the cheapest rung that clears the current base fee. On first-come chains every setting opens at rung 0, because the tip there is an admission fee rather than a bid. The box is handed the same opening bid, so it does not quietly open lower than the setting says.

Climbing

After the first send, every watch tick reads the base fee of the block being built and the 95th-percentile tip of the latest block, which is what it took to be in it. A wallet still pending climbs its own signed ladder for one of two reasons:

ReasonClimbs to
The base fee rose past the bid, so it can no longer be includedThe cheapest higher rung that covers the new base fee
Still pending after 1.5 blocks while the latest block cleared at a tip at or above ours (chains that sell ordering only)The cheapest higher rung whose tip beats what cleared, or the top rung when none does
A node refused the bid on price: underpriced, or under the base feeThe cheapest higher rung that covers the base fee being built on, or the next one up when that is not known

A climb sends a rung that was signed at Arm, straight from the browser and through the server at once, so it costs one round trip and no signature. It only ever goes up, and every rung is already capped by the gas budget and the wallet's balance, so no climb can spend more than was agreed at Arm. A send that never reached a node is retried with the identical bytes; one a node refused on price is not, because the same bytes get the same refusal. Where no ladder is held in the browser, as after the box fires, the old path remains: a fresh signature at a fee the server suggests, within the same budget.

Gas limits

Each transaction's gas limit is the simulation's estimate plus 50%, or plus 40,000 gas when that is more, for a wallet whose first mint writes storage the estimating wallet already had. A fixed floor is used only when there is no estimate, as before a sale opens.

The limit is not free even though you are billed only for the gas you use. The gas budget becomes a per-gas cap by dividing by it, so an oversized limit lowers every bid the budget allows, including the one Nuke opens at. And on a chain with small blocks, a limit that is too high is a transaction that does not fit.

Getting it there

Connections are opened and warmed before the moment, not during it.

  • Warm first. Endpoints are contacted ahead of the open so the connection, the name lookup and the handshake are already paid for. A cold connection at the moment of firing costs more than everything else combined.
  • Send to all of them, take the first answer. Endpoints are raced rather than tried in order. One slow node is a node that loses nothing. The server answers on the first node to take the transaction; the slower copies finish after the response rather than holding it.
  • Reads are hedged. A server read asks the first endpoint, and if it has not answered in 400 ms, the next as well; the first answer wins. A failed connection moves on at once. A revert does not: it is the chain's answer, and every node gives the same one.
  • Only a revert is the chain's answer. An error that is about the endpoint — a rate limit, a method it does not serve, a gateway with no backend, a block tag it will not answer — moves the read to the next endpoint, in the browser, on the server and on the box alike. These used to end the read as though the chain had said no.
  • Reads made together travel together. The simulation's getters and candidate calls, and Arm's per-wallet reads, go as JSON-RPC batches of up to 10 calls: a simulation is a handful of requests rather than the sixty or more it used to be, which is also sixty fewer chances for a rate limit to read as “Sim failed”. An endpoint that names a smaller batch limit is split to fit it.
  • Arm does its reads together. The licence check, every wallet's nonce and balance, and the fee quote run at the same time instead of one after another.
  • Each wallet mints at its first open nonce. A transaction it left waiting unmined — usually a bid from a race you stopped — is replaced by the mint rather than queued in front of it, where it could hold the mint back forever or land as a second purchase. The wallet is named at Arm: ···4f2a had a transaction waiting · this mint replaces it.
  • The base fee comes from the block being built, or from the latest block on chains that do not serve the pending one — Abstract, MegaETH, HyperEVM and Arc. Those used to quote a flat 1 gwei, and on Arc the refusal stopped Arm outright.
  • The open-watch reads each endpoint independently. The first endpoint to see the sale open fires, without waiting on the others, and a slow endpoint never has two reads in flight. It reads at least twice a block, never less often than every 600 ms. An endpoint that answers with a rate limit or a fault counts as not watching, never as a sale still shut, so the watching count on screen is the true one.
  • Sign early, send late. Everything that can be computed before the open is, so the moment itself contains a single network call and no work.
  • The licence is checked once per race. Arm checks it and hands back a ticket, signed by the server, naming the contract, the chain and the wallets it approved, valid for 24 hours. Every resend and fee replacement for that race carries the ticket instead of asking the licence ledger again. Anything the ticket does not cover is checked in full.
  • On Ethereum, a private path is available. It goes to a builder rather than the public mempool, with public sending as the fallback when it is not configured. When it is configured, the browser does not broadcast to public nodes at all: the send goes through the server to the builder alone. That is one hop slower on a twelve-second chain, and it keeps the bid out of the public mempool, which a parallel public broadcast would have defeated.
  • A send survives the phone locking, within limits. Browser sends are marked to finish even if the page goes away, but browsers cap the total size of such requests at 64KB and refuse any fetch past it outright. So they are marked only while the total in flight stays under 48KB; past that a send goes out unmarked rather than being refused.
  • A sequencer comes first. Where a chain publishes one, as Robinhood Chain does, every send goes there first, from the browser as well as the server. On a first-come chain, arriving at the sequencer first is the race.

Two other answers look like it and mean something else. “Nonce too low” means the nonce is already spent — often by this very transaction, when the browser's copy was mined before the server's arrived — so the transaction's own hash is kept and its receipt decides. “Replacement transaction underpriced” means the node holds a different transaction for the nonce and refused this one; it is recorded as refused. Both used to be counted as sent.

Keeping track after the send

  • Every bid stays watched. A wallet that climbs its ladder sends several transactions for one nonce, and any of them can be the one mined. All of them are watched until one lands. Only the latest used to be, so an earlier bid that won left the race waiting forever.
  • One round trip per poll. Receipts for the bids still in play, each waiting wallet's transaction count and the fee market go to two endpoints as one batched request each. The poll runs at half a block, between one and three seconds. It used to be a request per transaction per endpoint, every second, including wallets that had already finished.
  • A nonce spent elsewhere ends that wallet. When the chain has moved past a wallet's nonce and none of its bids has a receipt, for three blocks (never less than six seconds), the wallet closes as missed with the reason Nonce used by another transaction · not one of these bids.
  • The race keeps what it was armed with. Resends, fee climbs and the fire use the contract, chain, path, wallets and the sale's opening time frozen at Arm, and a reload brings them back. They used to be read off the screen at the moment of sending, so editing the contract field during a race quietly stopped every retry.
  • A bid a node took is watched, whoever heard about it. The browser sends the same signed bytes straight to the chain and to the server. Any acceptance a node gives the browser is recorded in the race at once, by the hash of the signed bytes, so a climb that lands is watched even when the server's copy of the send failed.
  • Confirmed is counted, not assumed. Every poll also reads the chain's latest block. A win reads Confirmed once it has 2 blocks counting its own on a chain with blocks five seconds or longer, 5 on a faster one; until then it reads Included. A finished race is polled for the head alone until its wins get there, then not at all.
  • Nothing the server says is lost. The receipt poll and the sends both answer about the same race; their answers are merged, never swapped, so a poll cannot erase a hash a resend just recorded. A resend the server refuses is shown, and a fire the server did not record falls back to what the nodes told the browser.

From the box

The box reads and sends differently, because the two jobs want different things. A read wants one good answer. A send wants the transaction in as many mempools as possible, as early as possible.

What the box does
EndpointsRUNNER_RPC_<chainId> on the box, comma-separated, if set. Otherwise every public endpoint the cockpit knows for the chain. A chain's sequencer is always added for sends.
ReadsThe clock and the open-watch ask the first endpoint that answers, and stay on it until it stops. A revert is passed straight back: another node would give the same answer, later.
SendsEvery signed transaction goes to every endpoint at once. A transaction counts as sent the moment the first endpoint takes it; the other copies carry on behind it.
RetriesA connection that fails, times out, or answers with a rate limit or a server error is sent the identical bytes again after 100 ms, then 300 ms. A node that refuses the transaction is not asked again.
The fireA due schedule fires at once. The gate is read only while the schedule is not yet due, to catch a sale that opens early, and the decision after a read uses the clock as it is after the read.
The leadMeasured to every endpoint at Arm. The fastest sets the aim, so no copy arrives early; the rest arrive a little after the open, which is where a backup belongs.
The resultEvery transaction's hash comes back to the cockpit, with whether any endpoint took it. Taken ones join the race and their receipts are read there. Ones nobody took are sent again from the cockpit, same nonce, same fees.

Reading the result

Three outcomes, and the difference between them is money.

OutcomeMeansDistinguished by
inThe purchase landed and tokens moved.A receipt with a success status, plus transfer logs out of the zero address.
revertedThe chain ran it and rejected it. Gas is spent.A receipt with a failure status. The revert reason is decoded where the contract gives one.
missedIt never landed: sold out, beaten, or the wallet's nonce was spent by something else.A send that never reached a node after five tries, or the wallet's nonce spent with no receipt for any of its bids.

A send that never reached a node is none of these. It is a transport failure and the wallet is still live, so it is retried rather than recorded as a loss.

The receipt also says which block the transaction landed in, and that block's own timestamp is read once. How long after the open a mint landed is measured from it — the chain's clock — rather than from when the screen happened to poll, which on a half-second chain was two to four blocks of error in the one number that says whether you made the opening block.

The receipt is also read for the token ids, since every mint emits a transfer from the zero address. ERC-721 is told from ERC-20 by topic count: an indexed token id makes four topics where a fungible transfer has three.

The Solana engine

Its own engine behind the same screen, because the chain's guarantees are different.

Solana has no per-wallet nonce to make a fee ladder safe, no mempool to watch, and a recent blockhash that expires in about a minute, so a bid signed at Arm would be dead long before a scheduled open. The Ethereum engine's machinery does not transfer; its shape does. Solana gets its own engine with the same flow — prepare, sign on the device, hold, send everywhere, watch, outcome — and shares the keystore, the licence, the stage words and the screen.

One hold per wallet, so at most one bid lands

Each wallet gets a durable nonce account — the hold — at an address derived from the wallet and the seed easternbot-hold-v1, so nothing extra is stored and it can be found again from the wallet alone. It costs 0.0011 SOL of rent, refundable. Every bid and the cancel for that wallet are signed against the hold's current value instead of a blockhash, and each starts by advancing it. The first to reach a block moves the value; every other one is then rejected before execution, which means it is never charged. That is the Solana equivalent of every Ethereum rung sharing one nonce, and it is what makes a pre-signed ladder safe.

Every transaction has the same shape

advance hold → compute limit → priority fee → [tip to Jito] → mint × quantity

The mint is last because a guard with bot tax can be set to charge any mint that is not the final instruction. The mint instructions come from Metaplex's own clients (Core candy machine mint_v1, Candy Machine v3 mint_v2), with the guard arguments filled from the guard's on-chain settings: a payment can only go where the creator set it to. When a transaction does not fit Solana's 1232-byte limit — a programmable NFT with several guards comes close — the tip is dropped first, then the compute limit instruction; beyond that it is refused.

What the device checks before it signs

The server builds; the device holding the keys decodes every message and refuses anything outside this list:

  • The fee payer is this wallet, and the only signers are this wallet and the NFT accounts this device just generated.
  • The first instruction advances this wallet's own hold, derived on the device, not taken from the server.
  • Programs: the System Program, Compute Budget, and the guard for this kind of machine. Nothing else.
  • The only System instruction after the advance is at most one transfer to a known Jito tip account, within your cap.
  • Every guard instruction is a mint from the candy machine you pasted, paid and received by this wallet; a Core mint's owner is this wallet, and a v3 mint's token account is this wallet's own.
  • The mint is the last instruction, and fees plus tip stay under your cap.

Setup, cancel and deposit returns have their own, shorter lists. The server applies the same shapes before relaying anything, and checks every signature, so it is not a relay for arbitrary transactions.

When it fires

Holding, the device simulates the signed opening bid itself every 400 ms — signature checks off, against the processed bank — and asks the simulation to report the NFT account the mint would create. It fires on the first simulation that passes and creates that account. The second condition is the bot-tax check: a taxed mint succeeds as a transaction but creates nothing. Before 3 seconds to the open by the chain's clock, it only counts down. The browser simulates against a public endpoint; if that does not answer, the server simulates instead.

Firing on a passing simulation costs about one slot against firing blind at the open. It is the only honest choice here: an early bid either fails and spends the hold — so the ladder is gone — or, on a taxed machine, pays the tax.

Getting it there

  • The browser sends each bid straight to public endpoints; the server sends to SOLANA_RPC_URL (comma-separated, https only; public endpoints when unset) and, for a tipped bid, to one Jito block engine region, rotating, because each region rate-limits per address. SOLANA_JITO_UUID raises that limit.
  • Preflight is off and endpoint retries are off: the bot resends the same bytes itself every 1 s from the browser and every 1.6 s through the server, until the bid lands, the hold moves, or you stop.
  • A bid unlanded after 2 s climbs straight to the first rung above the lowest priority fee that actually landed on the machine in recent slots (getRecentPrioritizationFees); with no sign of being outbid it steps up one rung after 6 s.
  • A keyed endpoint with a staked connection matters more on Solana than a fast phone: it is how a transaction reaches the leader first. The public endpoints are rate-limited and are the fallback, not the plan.

Reading the result

One call every 800 ms asks for every signature sent so far (getSignatureStatuses), every hold's value, and the machine's count. A bid found in a block settles its wallet: in if it succeeded, failed if not — then the landed transaction's logs are read once so the screen can name the rule that refused it. Confirmed means the network's supermajority voted on that block. A hold that moved with none of our signatures found is given 8 s for statuses to catch up, then called missed. Sold out with every hold unmoved means nothing of ours landed and nothing was charged, so those wallets end there.

Compute units come from simulating the mint at Arm when it is open, padded by 25% plus 10,000; otherwise 200,000 for Core, 350,000 for v3 and 450,000 for programmable NFTs.

How selling works

A listing is a signature, which makes it the most dangerous thing here.

Everything else the bot signs is a transaction: it fails loudly, costs gas, and leaves a receipt. A listing does none of that. It never reaches a mempool, costs nothing to make, does not expire until it says it does, and hands whoever holds it the right to take the token. At signing time, a listing that sells a token and one that gives it away are the same shape.

So the signer does not sign typed data. It signs listings it has read, and refuses anything it cannot state in one sentence:

  • the offerer is the wallet being asked, not whoever the request names
  • the offer is tokens, never money, and never a set matched by criteria
  • payment is in one currency, and at least half of it comes back to the seller
  • fixed amounts only, no price that moves over time
  • it expires, within thirty days

Checked by the contract, not by us

Before a listing is offered to anyone, the marketplace contract is asked whether the signature is good. Its validation entry point is a transaction, but called read-only from an address that is not the seller it runs the real signature check and answers for nothing. The contract that would settle the sale is a better judge of the signature than the code that made it.

The settlement contract sits at one address on all eleven chains the bot mints on, so the order is the artifact and the marketplace is only an orderbook. A failed post loses nothing: the signed order is still there to post anywhere.

Key handling

Where the boundary is, and what crosses it.

Crosses the boundaryNever crosses it
Wallet addresses and labelsSeed phrases
Unsigned transactionsPrivate keys
Signed transactions, ready to sendPassphrases
Transaction hashes and outcomesBiometric data
  • Keys held in the browser are encrypted with a key derived from your passphrase, and the derivation is deliberately slow so a stolen file is not a stolen wallet.
  • Face ID and fingerprint unlock wrap the same encrypted material using your device's secure hardware. The biometric never leaves the device and is never sent anywhere.
  • The browser keeps all of it for easternbot.xyz alone, and binds the biometric unlock to that address too. A page on any other address, however alike it looks, cannot read it; a new browser or device starts empty, and you import the phrase there.
  • Solana keys come from the same phrase at m/44'/501'/i'/0' (SLIP-0010, the path Phantom uses), or are imported as the 64-byte secret wallet apps export. They are sealed in the same keystore as the Ethereum keys, under the same passphrase. Each Arm also makes one throwaway key per NFT, on the device: the mint must be signed by the account it creates. Only its public half leaves the device, and it has no power once the NFT exists.
  • The self-hosted signer exposes signing behind a token, on an address you choose. In the box configuration it is not published to the internet at all: the runner reaches it over an internal network, and nothing outside can.

What it cannot do

The honest list. Every one of these is a real limit, not a roadmap entry.

  • It cannot beat a block that is already sealed. Predictive firing is the answer to that, and it depends on the start time being readable from the contract. Where it is not, the bot cannot aim.
  • It cannot place an allowance in an unverified contract's call. When an allowance list matches but the contract's code is not published, nothing says which argument takes the number, and the bot will not guess one: those wallets sit out.
  • It cannot make a signature. A signature-gated sale can be raced only with signatures the project's own server issued, through a link the project exposes. Where the signed message also covers a nonce or a deadline passed as its own argument, the bot has no way to fill it, and the simulation fails rather than a transaction being sent.
  • It cannot mint through a launchpad it has never seen. Where a collection mints only through a private router — not its own contract, not one it will name, not SeaDrop — there is no call to build and no way to guess one. The cockpit says Sim failed · check contract on a mint that is genuinely live, and it is the bot that is short, not the contract.
  • It does not find mints, or judge them. It races the contract you give it. Whether that collection is worth having is yours to decide, before you press Arm.
  • On Solana, it cannot mint what a launchpad signs. A guard that needs a third party's signature, a captcha pass, an NFT from another collection or a vanity address stops the bot for that group, with the reason on screen. Launchpads that build the purchase on their own servers are out of reach the same way.
  • On Solana, it has no box, no remote signer and no Sell. Solana keys must be in the browser, the tab must stay open while it holds, and a win is sold on a marketplace, not from here.
  • On Solana, one transaction per wallet. A Core machine takes up to three mints per wallet in one transaction; a v3 machine takes one. Anything more needs more wallets.
  • It cannot recover your passphrase. Nobody can. That is the point of it.