By the ODIN Tools team. We build Thor, a Telegram trading bot, so the examples below come from our own product.
"Transaction failed" is the most common message a memecoin trader sees. Most of the time it is not a bug. The chain did exactly what the transaction told it to do, and that was to give up.
This post walks through the five reasons on-chain trades fail on Solana (and one on Ethereum), the arithmetic behind each, and what a trading bot can do so the user is not left staring at a red toast.
1. Slippage: the trade refuses a worse price
A swap does not say "buy X tokens at any price". It says "spend 0.5 SOL and give me at least N tokens". That minimum is your slippage tolerance applied to the quote:
// quote: how many tokens 0.5 SOL buys right now
const quotedOut = 1_628_420n; // tokens
const slippageBps = 1_000n; // 10%
// the swap reverts if it would deliver fewer than this
const minOut = quotedOut * (10_000n - slippageBps) / 10_000n;
// => 1_465_578 tokens
Between the quote and the moment your transaction lands, other people trade. On a coin that is up 66% in a day, the price can move more than 10% in a second or two. If the pool would now give you fewer than minOut tokens, the program reverts and nothing is bought.
That is the protection working. The alternative is filling at whatever price the market reached, which on a thin memecoin pool can be very bad.
What the bot should do:
- Say why it failed in plain words ("Price moved 13.1%, over your 10%"), not a program error code.
- Offer a one-tap Retry, and a Review trade that fetches a fresh quote.
- Optionally retry automatically with a little more slippage. Thor re-sends a failed order with slightly higher slippage, up to 5 times, which is what you want for an automated take profit that must not sit unfilled while the price runs away.

A failed buy ("Price moved past your 10% slippage"), the details sheet with the reason and the cost, and the same trade landing on retry.
Note the "Spent: network fee 0.000105 SOL only" line. On Solana a transaction that lands and then reverts still pays its fee. That is why blindly retrying 20 times is a bad idea, and why the bot should show the user what each failure cost.
2. Price impact: your own trade moves the price
Slippage is about other people moving the price. Price impact is about you moving it. In a constant-product pool (x · y = k), a buy that is large compared to the pool's liquidity gets a much worse average price:
// simplified constant-product pool, ignoring fees
function priceImpact(amountIn: number, reserveIn: number) {
// share of the pool your trade consumes
return amountIn / (reserveIn + amountIn);
}
priceImpact(2, 6.5); // ≈ 0.235 → about 24% worse than spot
A 2 SOL buy into a pool with $2.6K of liquidity moves the price by about a quarter. No slippage setting fixes that; the only fix is to buy less.
What the bot should do: check impact before sending, compare it with a limit the user sets, and suggest an amount that fits ("Impact 24%, over your 20% limit. Use 1.6 SOL instead").
3. Priority fees: the network is busy
Every Solana transaction pays a base fee of 5,000 lamports per signature. During a hot launch, thousands of transactions compete for the same accounts, and validators favour the ones that pay a priority fee:
priority fee = compute unit price (micro-lamports per CU) × compute unit limit
Set it too low and your transaction waits, while the price moves past your slippage (back to reason 1). Set it too high on every trade and you overpay on quiet coins.
What the bot should do: offer a few named levels (Thor uses Economy, Standard, Fast and Turbo) instead of raw micro-lamports, set them separately for buys and sells (exits are usually more urgent than entries), and offer a "retry with Turbo" button when a trade fails because the network was busy.
4. Expired blockhash: the transaction timed out
Each Solana transaction includes a recent blockhash, and it is only valid for about 150 blocks, roughly a minute or so. If a transaction has not landed by then, it can never land. It simply disappears without an error on-chain.
For a bot this means two things. It has to track the transaction until it either confirms or its blockhash expires, and only then report "didn't go through". And a retry must be a new transaction with a fresh blockhash and a fresh quote, not the same bytes sent again.
5. No SOL left for fees
This one surprises new traders the most. You hold $287 of a token, you tap Sell, and it fails, because the wallet has 0 SOL and someone has to pay the network fee. Every Solana transaction needs a fee payer with SOL.
The same thing happens in reverse on buys. "Max" that spends the whole SOL balance leaves nothing for the fee, or for the roughly 0.002 SOL of rent needed to open a token account for a coin you have never held.
What the bot should do:
- Make Max count the fees and the rent, so it never builds a transaction that cannot pay for itself.
- On buys, if the amount is a bit more than the balance, buy with what fits instead of failing. Thor calls this Buy protection.
- On sells, let the user sell with 0 SOL. In Thor, Sell protection pays the network cost up front and takes back only what that sell actually cost, out of the SOL the sale returns.
Related: every token you ever bought leaves a token account holding that rent. Closing empty ones gives the SOL back. We wrote about that in how to reclaim SOL rent.
Bonus, Ethereum: the sandwich
On Ethereum, a pending swap sits in a public mempool where anyone can see it. A bot can buy just before you (pushing the price up to your slippage limit) and sell just after you, keeping the difference. Your trade does not fail. It just fills at the worst price your slippage allowed.
Two defences work together: keep slippage as low as the coin allows, and keep the transaction out of the public mempool. That is what an "MEV protection" toggle does. More detail in our MEV protection guide.

Per-chain slippage with separate buy and sell values, a price impact warning that suggests a smaller amount, and the MEV protection switch for Ethereum.
A checklist for anyone building trading UX
- Translate every failure into a reason a trader understands, plus what it cost.
- Retry with a fresh quote and blockhash, never the same transaction.
- Separate slippage and priority fees for buys and sells.
- Check price impact before sending, and suggest a size that fits.
- Make Max reserve fees and rent.
- Never let "no gas" trap a user in a position.
- On EVM chains, offer private submission for swaps.
None of this makes trading safer in the sense of making losses less likely. Memecoins are still memecoins. It just means that when a trade fails, it fails for a reason the trader chose, and they know what to do next.
Top comments (0)