LayerZeroFault
ai agents-api

Fix: ElizaOS Solana Blockhash Not Found and Jito MEV Reverts

VV

Written by

Fact-Checked on September 11, 2026

Verified Expert

Fix: ElizaOS Solana Blockhash Not Found and Jito MEV Reverts

Autonomous trading agents and liquidity rebalancers built on ElizaOS (using @elizaos/plugin-solana, Raydium SDK, or Jupiter v6 swap aggregates) frequently suffer from severe execution friction during volatile market events:

SendTransactionError: Transaction simulation failed: Blockhash not found
    at Connection.sendEncodedTransaction (/node_modules/@solana/web3.js/src/connection.ts:5892:13)
    at SolanaTradeService.executeSwap (/packages/plugin-solana/src/services/swap.ts:241:20)
[ERROR] Swap execution failed: Transaction was not confirmed in 60.00 seconds.
[ABORT] Blockhash expired before slot leader reached transaction index.

The agent identifies an arbitrage opportunity, formats the swap instructions, and signs the transaction. However, the transaction never lands on-chain, dropping silently or throwing Blockhash not found when polled by confirmation workers.

The root cause of this failure mode is blockhash obsolescence compounded by lack of dynamic priority fees: standard Solana transactions remain valid for only 150 slots (~60–75 seconds). When agents utilize congested public RPC endpoints without dynamic compute unit pricing or MEV bundles, packets queue up behind spam transactions, expiring before the assigned block leader can evaluate them.

If your agent is also failing during initial public key derivation from private seed strings, review our foundational guide on Resolving ElizaOS Solana Public Key Not Found Errors.


Architectural Breakdown: The Solana 150-Slot Blockhash Window

Solana does not utilize sequential account nonces like Ethereum. Instead, every transaction incorporates a recentBlockhash that acts as a replay-prevention mechanism and temporal expiration timestamp.

Placeholder: Sequence Diagram of Solana Blockhash Expiration Window and Jito MEV Direct Validator Inclusion Pipeline

Why Standard RPC Submissions Fail During Volatility

  1. Commitment Delay: Calling getLatestBlockhash() with 'finalized' commitment returns a blockhash that is already 32+ slots old, reducing the transaction’s remaining flight window to under 45 seconds.
  2. Leader Schedule Queueing: Solana validators rotate leadership every 4 slots (~1.6 seconds). Standard RPC nodes forward transactions to the estimated current leader via UDP/QUIC. If network latency drops packets, the transaction waits for the next rotation.
  3. Compute Unit Starvation: Without ComputeBudgetProgram.setComputeUnitPrice, transactions offer 0 priority micro-lamports, causing validators to drop them in favor of transactions paying priority fees.

Step-by-Step Resolution Protocol

To guarantee sub-second execution and zero dropped transactions in your ElizaOS Solana agent swarm, implement this three-part production pipeline.

Placeholder: Architecture Flowchart of Dynamic Priority Fee Estimation, Jito Tip Injection, and Bundle Submission

1. Optimize Blockhash Acquisition with confirmed Commitment

In your Solana connection utility, always fetch the blockhash with 'confirmed' commitment and store the context lastValidBlockHeight for precise expiration tracking:

// src/services/solanaConnection.ts
import { Connection, BlockhashWithExpiryBlockHeight } from '@solana/web3.js';

export async function getFreshBlockhash(connection: Connection): Promise<BlockhashWithExpiryBlockHeight> {
  // CRITICAL: Use 'confirmed' commitment to maximize the remaining 150-slot validity lifetime
  const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhashAndContext('confirmed');
  
  return {
    blockhash,
    lastValidBlockHeight,
  };
}

2. Inject Dynamic Priority Fees via Compute Budget Program

Prepend compute budget instructions to every transaction to ensure validators prioritize your agent’s transaction:

// src/services/transactionBuilder.ts
import { 
  TransactionInstruction, 
  ComputeBudgetProgram, 
  TransactionMessage, 
  VersionedTransaction,
  PublicKey,
  Connection 
} from '@solana/web3.js';

export async function attachPriorityFeeInstructions(
  connection: Connection,
  instructions: TransactionInstruction[],
  payer: PublicKey
): Promise<TransactionInstruction[]> {
  // Query current 75th percentile priority fees from RPC
  let microLamports = 50000; // 50,000 micro-lamports default baseline

  try {
    const recentFees = await (connection as any).getRecentPrioritizationFees();
    if (recentFees && recentFees.length > 0) {
      const sorted = recentFees.map((f: any) => f.prioritizationFee).sort((a: number, b: number) => a - b);
      microLamports = sorted[Math.floor(sorted.length * 0.75)] || microLamports;
    }
  } catch (err) {
    console.warn('[PriorityFee] Failed to query dynamic fees, using fallback baseline.');
  }

  const computeUnitsIx = ComputeBudgetProgram.setComputeUnitLimit({
    units: 300000, // Explicitly bound compute units
  });

  const priorityFeeIx = ComputeBudgetProgram.setComputeUnitPrice({
    microLamports: Math.max(microLamports, 25000),
  });

  return [computeUnitsIx, priorityFeeIx, ...instructions];
}

3. Route Transactions through Jito MEV Tip Bundles

For critical swaps, route transactions directly to Jito Block Engine endpoints, attaching a direct tip payment instruction:

// src/services/jitoBundleService.ts
import { SystemProgram, PublicKey, TransactionInstruction } from '@solana/web3.js';

// Randomly select one of Jito's 8 official tip accounts
const JITO_TIP_ACCOUNTS = [
  '96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5',
  'HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe',
  'Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvMAy',
  'ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49',
  'DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh',
  'ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt',
  'DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL',
  '3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT',
];

export function createJitoTipInstruction(payer: PublicKey, tipLamports = 100000): TransactionInstruction {
  const randomTipAccount = new PublicKey(
    JITO_TIP_ACCOUNTS[Math.floor(Math.random() * JITO_TIP_ACCOUNTS.length)]
  );

  return SystemProgram.transfer({
    fromPubkey: payer,
    toPubkey: randomTipAccount,
    lamports: tipLamports, // E.g. 0.0001 SOL tip for guaranteed block inclusion
  });
}

Transaction Routing Performance Matrix

Routing MethodAverage Inclusion LatencyDrop Rate During CongestionTypical Cost
Standard Public RPC (0 tip)18–45 seconds65% - 80% Dropped~0.000005 SOL
RPC with Dynamic Priority Fee3–8 seconds15% - 25% Dropped~0.00005 SOL
Jito MEV Direct Validator Bundle400–800 ms (Next Slot)< 1% Dropped~0.0001 SOL

Frequently Asked Questions

Q: Why does Jito bundle submission require a tip instruction inside the transaction?

Jito searchers and block validators operate an auction mechanism. The tip instruction transfers native SOL directly to the validator’s tip address when the bundle executes. If the swap reverts, the bundle is discarded, and no tip is deducted.

Q: Can I use both standard priority fees and a Jito tip simultaneously?

Yes. Setting a modest ComputeUnitPrice ensures fallback priority if the transaction is submitted to standard validators, while the Jito tip guarantees accelerated inclusion on validators running Jito-Solana client software (~80% of current mainnet stake).

Q: What is the maximum number of transactions allowed in a single Jito bundle?

A Jito bundle can contain up to 5 transactions that execute atomically in sequence. If any transaction in the bundle fails, the entire bundle is dropped, providing MEV and sandwich attack protection for autonomous agents.

Partner Spotlight: Gate.io

Trade Securely on Gate.io

Don't risk your assets on centralized silos or unverified endpoints. Trade securely on Gate.io with deep liquidity and institutional-grade security protocols.

Claim $100 Sign-up Bonus

Official Partner Referral Link

Related Inquiries

Why do ElizaOS Solana transactions fail with 'Blockhash not found'?

On Solana, transactions sign a recent blockhash that remains valid for exactly 150 slots (~60 to 75 seconds). During periods of intense mainnet congestion or DEX volume spikes, transactions submitted to standard public RPC nodes get stuck in the leader's TPU queue. By the time the transaction reaches the scheduled slot leader, the blockhash has expired, resulting in simulation or execution rejection.

How does routing transactions through Jito MEV bundles fix blockhash expiration?

Jito bundles bypass the public mempool (TPU) entirely. Transactions are routed through a private direct line to validators running the Jito-Solana client. By appending a microscopic tip instruction (e.g. 0.001 SOL) to a designated Jito tip account, your transaction is guaranteed inclusion in the very next block without waiting in congested RPC queues.

What is the optimal commitment level for fetching recent blockhashes in automated agents?

Always specify commitment: 'confirmed' when calling connection.getLatestBlockhashAndContext(). Fetching with 'finalized' yields older blockhashes that have already consumed 30+ slots of their 150-slot validity window, dramatically increasing the risk of expiration during flight.