DEV Community

Cover image for Solana Transactions Are Not What I Expected (Coming From EVM)
Aborisade Ayomiposi
Aborisade Ayomiposi

Posted on

Solana Transactions Are Not What I Expected (Coming From EVM)

I've been building on EVM chains for a while Base, Ethereum, the usual.
I thought picking up Solana would be a lateral move. Same concept, different syntax.

I was wrong, and the transactions are where that became obvious.


What I thought I knew

On EVM chains, a transaction is mostly a wrapper. You have:

  • A to address
  • Some value (ETH)
  • Optional data (the encoded function call)
  • A signature from your wallet

The RPC figures out what to do with it. You don't think too hard about the
structure. ethers.js handles most of it.

Solana transactions look structurally similar at first glance. You sign something,
you broadcast it. But once you actually build one from scratch, the differences
become hard to ignore.


The anatomy is more explicit

A Solana transaction is made of instructions, and each instruction spells
out exactly which accounts it touches and whether each account is a signer,
writable, or read-only.

You don't just call a function and let the runtime figure out state. You declare
upfront: "This instruction reads from account A and writes to account B."

Here's what building a simple transfer looked like when I did it:

const transaction = new Transaction().add(
  SystemProgram.transfer({
    fromPubkey: sender.publicKey,
    toPubkey: recipient,
    lamports: LAMPORTS_PER_SOL * 0.001,
  })
);

transaction.recentBlockhash = (
  await connection.getLatestBlockhash()
).blockhash;

transaction.feePayer = sender.publicKey;
Enter fullscreen mode Exit fullscreen mode

Three things you set manually that ethers.js would've handled for you:
the instruction, the blockhash, and the fee payer. On Solana, you're closer
to the metal.


The blockhash thing caught me off guard

Every Solana transaction includes a recentBlockhash. It's not optional.
It's what ties your transaction to a specific point in time, and it expires.

If your transaction doesn't land within roughly 60 to 90 seconds, it's dead.
You have to rebuild it with a fresh blockhash and try again.

On EVM chains, you deal with nonces and gas price wars. Transactions can sit
in the mempool for minutes. Solana's model is different: it's intentionally
short-lived. Either your transaction lands fast, or it doesn't land at all.

I actually triggered this on devnet by fetching a blockhash, waiting too long,
and then trying to send. The transaction came back invalid. Once I understood
why, it made sense, Solana is optimizing for speed and finality, not
for letting transactions queue.


Breaking transactions taught me more than building them

The task I was working through asked me to intentionally break transactions
to understand the failure modes. That turned out to be the most useful part.

Some things I broke on purpose:

  • Sending without enough SOL for rent-exempt balance
  • Exceeding the compute budget (Solana allocates compute units per transaction, similar to gas but more explicit)
  • Including too many instructions in one transaction, Solana has a hard 1,232-byte size limit on transactions

That last one doesn't have a direct EVM equivalent. On Ethereum, you can
pack a lot into calldata. On Solana, 1,232 bytes is the ceiling, full stop.
It shapes how you design programs. If you need to do a lot, you batch across
multiple transactions or restructure your logic.

The failed transactions show up on Solana Explorer with a clear error log.
That's actually better than what I'm used to on EVM, where a reverted
transaction sometimes just says "execution reverted" with nothing useful attached.


The mental model that finally clicked

On EVM, I think of a transaction as sending a message to a contract.

On Solana, it's closer to submitting a batch of state changes that either
all succeed or all fail. The accounts are the state. The instructions are the
operations. The transaction is the atomic unit that wraps them.

That's not a huge conceptual leap, but the way you build for it is different.
You think about accounts before you think about logic. You declare intent upfront
instead of letting the runtime discover it.

I'm still early in this. Day 20 of 100. But transactions are the part where
Solana stopped feeling like "Ethereum but faster" and started feeling like
its own thing.


Building through the 100 Days of Solana challenge. If you're doing the same,
feel free to connect.

Top comments (0)