1

I have a problem with Solana Transaction Prioritization that seems to contradict all network prioritization metrics. (FYI: I am using Quicknode RPC)

Let's look at two transactions:

Our transaction (https://solscan.io/tx/4Pwiy5vHB5HHA57WMxxoqUfK3Ng5pScMHv8L2c5UUN5eS3i8T84y58RphPfBmmDU396K7nqSEkYAcHHhwcLWuNC3):

Compute Unit Price: 8.38 lamports per compute unit Priority Fee: 0.001 SOL ($0.1738) Compute Units Allocated: 119,283 Compute Units Actually Used: 96,226 Result: Required multiple attempts, several minutes to confirm

Phantom's transaction (https://solscan.io/tx/3JqLWxLAn5LTqcuvCDDW87MEeEZfgUCmxMsAuacA6cB6wecHMooM5coZ8wnEkNNK1DW1yxiVvC4uFD2S8PbjyAYb):

Compute Unit Price: 1.3 lamports per compute unit Priority Fee: 0.0004 SOL ($0.06954) Compute Units Allocated: 307,893 Compute Units Actually Used: 243,618 Result: Instant success, confirmed in seconds

Our transaction should be prioritized by ALL metrics:

Higher compute unit price (6.4x higher: 8.38 vs 1.3) Higher priority fee (2.5x higher: 0.001 vs 0.0004 SOL) Lower compute unit usage (96k vs 243k used)

I'm aware of the common advice about compute unit allocation affecting validator preferences. However, in this case, that explanation doesn't apply because:

Our transaction uses LESS compute units (96k vs 243k) We have LOWER CU allocation (119k vs 307k) Yet we have HIGHER fees and priority

According to standard validator behavior:

Validators prefer transactions with lower CU usage (ours uses less) Validators prioritize higher fees (ours has higher fees) Block space is limited to 1.4M CUs (our tx uses less block space)

By every single metric that affects transaction prioritization, our transaction should be preferred by validators and included faster than Phantom's. Yet we consistently see the opposite.

Has anyone encountered similar issues or can explain what might be causing this behavior? All the standard explanations about CU allocation and priority fees don't seem to explain what we're seeing here.

Here is my jupiter swap configuration:

const swapResponse = await axios.post("https://quote-api.jup.ag/v6/swap", {
    quoteResponse: quoteResponse.data,
    userPublicKey: user,
    wrapAndUnwrapSol: true,
    computeUnitPriceMicroLamports: 1200000,  // This results in ~8.38 lamports/CU
    dynamicComputeUnitLimit: true
});

Here is my tx logic:

const sendAndConfirmTx = async (sendConnection, signedTx) => {
  const rawTransaction = bs58.decode(signedTx);
  const signature = await sendConnection.sendRawTransaction(rawTransaction, {
    skipPreflight: true,
    maxRetries: 2,
  });

  let retries = 0;
  while (true) {
    try {
      await sendConnection.confirmTransaction(signature);
      break;
    } catch (e) {
      if (retries > 5) {
        throw e;
      }
      retries += 1;
    }
  }

  return signature;
};

I already set the fees super high and hoped that it would help, but it did not do anything. Perhaps it is a quicknode problem, that they do not forward our txs properly?

2 Answers 2

1

The most likely reason for this is Stake-Weighted Quality of Service (SWQOS). This is a mechanism where (simplifying) highly-staked validators are prioritised when sending transactions to the leader. I'm not sure which RPC provider(s) Phantom uses, but they or their RPC providers likely control or are partnered with highly staked validator(s) and are able to take advantage of this to more quickly/reliably land their transactions. I'm not sure what Quicknode's situation is here, so I'd suggest contacting them to find out if this is the issue you're seeing.

You can read more about SWQOS in the Solana docs: https://solana.com/developers/guides/advanced/stake-weighted-qos

Helius also have a really good deep-dive that goes into a lot of detail: https://www.helius.dev/blog/stake-weighted-quality-of-service-everything-you-need-to-know#what-is-stake-weighted-quality-of-service

0

I also had that problem before, you'll just need to keep sending the transaction until it is confirmed and just recreate another transaction if the last valid block height has expired. What I did is to keep spam send it without any interval, and using getSignatureStatuses alternately after sending the transaction to get an update. Jupiter instructions might cost around 0.0005 - 0.001(around 95k - 100k CU), if you aim for a less confirmation time. But if you create your own swap instruction, it can be less around 40k - 60k cu which would be better like I did. My average cu for swap is 40k-60k, before I just send one transaction and wait for confirmation and it takes ages to be confirmed and after that it only takes 5-20 seconds (depending on the congestion) with a fixed priority fee of 0.0001. All of these are based only on my experiences using helius rpc. The sending of transaction and confirmation delay might also be related on which rpc provider you are using.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.