Falcon tips & transaction requirements
Exactly what Falcon accepts as a tip on a Solana transaction: instruction shape, allowed accounts, the 1,000,000 lamport minimum and the 1,232-byte cap.
Falcon checks every transaction before it forwards anything. Yours has to deserialize cleanly, carry as many signatures as its message header requires, fit in 1,232 bytes, and pay a tip that matches all four rules below.
Tip selection
A tip only counts when one top-level instruction meets every condition at once:
| Condition | Detail |
|---|---|
| Program | System Program |
| Instruction | transfer: the plain 8-byte-lamports transfer, not transferWithSeed |
| Recipient | One of the tip accounts, present in the transaction's static account keys |
| Amount | At least 1,000,000 lamports, in one instruction |
That rules out several arrangements that look like they should work:
- Amounts never add up. Falcon walks the instructions in order and takes the first System transfer to an allowed tip account that already meets the minimum. Two half-sized transfers qualify as neither.
- Address lookup tables don't work for the tip. The recipient is matched against static account keys only.
- A CPI tip doesn't count. The transfer has to be an instruction in the transaction you submit, not something your program does internally.
- A tip declared in an HTTP field, a header or a client variable means nothing. Only the instruction is read.
Amount and accounts
The minimum tip is 1,000,000 lamports (0.001 SOL), paid in one transfer to any of these accounts:
Fa1con11xLjPddfzRwRUB16sbFZggp2JeJkCeWREyR8X
Fa1con11TM1RuAQzbQzYjTy4Ekfap9Lnc9fnEbQYEd6Q
Fa1con113Bvi76nS5AzUiRDC2fqjfzkNMUNRLgQybMYt
Fa1con1QGHJK232s8yZpzZZwqPexnAKcoyKj626LNsMv
Fa1con1zUzb6qJVFz5tNkPq1Ahm8H1qKW7Q48252QbkQ
Fa1con16d3MSwd3SAiwvr2LwgkpE7ot8zntbpuec8HAx
Fa1con1i7mpa7Qc6epYJ6r4P9AbU77DFFz173r59Df1x
Fa1con18nWn8TdAGL7JX8PertfMUGVSc899NawokJ4Bq
Fa1con1GKusK2EqsfzrDzGPaYZSxQtFGzJiRMMU9Zm2g
Fa1con1RDwVwM9VrJ53CwVefD3VU9c58EMpDawV7fLMiPick one at random per transaction: tipping the same account from everywhere makes every transaction compete for one write lock.
A JSON-RPC tip rejection comes back as -32602 transaction does not include required tip with "data":{"minimumLamports":N}. N is the required minimum; trust it over a hard-coded value.
Every other requirement
| Requirement | Rule | Failure |
|---|---|---|
| Serialization | Standard Solana transaction wire bytes, legacy or v0 | could not deserialize transaction |
| Trailing bytes | None; the buffer must end exactly where the transaction ends | could not deserialize transaction |
| Size | ≤ 1,232 serialized bytes | transaction exceeds maximum size of 1232 bytes |
| Signatures | At least one, and never more than 127 | transaction has no valid signature |
| Signature count | Must equal num_required_signatures in the message header | transaction signature count does not match required signatures, with "data":{"expected":n,"actual":n} |
Falcon checks the signature count, not the signatures themselves. A partially signed transaction serialized with placeholder slots for the missing signers still carries the expected count, so Falcon forwards it and it fails on chain instead. Only a signature array that doesn't match num_required_signatures (or holds 0, or more than 127) is rejected here. Signatures are verified cryptographically in exactly one place: preflight simulation, which runs when you set skipPreflight: false.
Add the tip in TypeScript
import { PublicKey, SystemProgram, Transaction } from '@solana/web3.js';
const tipAccount = process.env.FALCON_TIP_ACCOUNT;
const tipLamports = Number(process.env.FALCON_MIN_TIP_LAMPORTS);
if (!tipAccount) {
throw new Error('Set FALCON_TIP_ACCOUNT');
}
if (!Number.isSafeInteger(tipLamports) || tipLamports < 1_000_000) {
throw new Error('FALCON_MIN_TIP_LAMPORTS must be at least 1000000');
}
const transaction = new Transaction();
// 1. Your application instructions.
// 2. The tip: a top-level System Program transfer.
transaction.add(
SystemProgram.transfer({
fromPubkey: payer.publicKey,
toPubkey: new PublicKey(tipAccount),
lamports: tipLamports,
}),
);
// 3. Fee payer + fresh blockhash, then sign, then serialize.The tip is an ordinary instruction, so the lamports only move if the transaction executes on chain.
Symptom → cause → fix
| Symptom | Cause | Fix |
|---|---|---|
transaction does not include required tip (or SubmitError::MissingTip) with a tip you believe is there | The transfer is below minimumLamports, the recipient is not one of the tip accounts, or the recipient came from an ALT | Use data.minimumLamports, an account from the list, and put the recipient in the static account keys |
| Tip rejected only on some transactions | The tip was split across instructions, so no single transfer reaches the minimum | Pay the whole tip in one transfer |
transaction signature count does not match required signatures | A required signer is missing, or the message was edited after signing | Rebuild, sign with all signers, serialize once |
could not deserialize transaction: verify encoding and format | Wrong encoding, base64 sent as base58, or extra bytes appended | Match encoding to the string you send; submit the exact serialized bytes |
transaction exceeds maximum size of 1232 bytes after adding the tip | The tip pushed you over the cap | Drop an instruction, use an ALT for application accounts (not the tip), or split the work |
| Nothing happens at all on UDP | Any of the above | Reproduce the same transaction over JSON-RPC to see the real reason |
Per-transport response shapes are on Falcon errors & retries.
Falcon quick start
Verify your Falcon key, submit a signed Solana transaction over JSON-RPC or QUIC, then confirm the signature on a normal Solana RPC.
Falcon submission methods
Falcon JSON-RPC, /binary, /plaintext and QUIC reference: request shapes, size limits, options and exactly what each success response proves.