Skip to content
EN

← Return to Guides

Developer solanaexecution-authorityfinality

Solana Authority, Finality, and Economic Reconciliation in FarmDash

How FarmDash bounds Solana agent authority with signed policies, a 14-state preparation lifecycle, and independent on-chain economic reconciliation — and why finalized is not the same as reconciled.

By FarmDash Pioneers · Published 2026-11-10 · Updated 2026-11-10

TLDR: FarmDash never server-broadcasts Solana transactions. A bounded, signed policy grants a session signer limited authority; the owner signs and submits the transaction themselves. After submission, FarmDash independently verifies on-chain finality and reconciles exact economic deltas — and treats finalized as strictly weaker than economically reconciled.

Why This Matters for Agents

Agent systems that touch Solana face two distinct failure classes, and conflating them is the root of most Solana agent-safety incidents.

The first is authority abuse: an agent doing more than it was permitted. This includes spending beyond a budget, invoking a program outside an allowlist, or acting after a grant expired. Authority abuse is prevented before submission, by binding a grant to explicit bounds and refusing to prepare anything outside them.

The second is outcome fabrication: a receipt claiming success that the chain does not support. A transaction can be finalized and still have delivered the wrong output amount, skipped a fee transfer, or moved value through an unexpected path. Outcome fabrication is detected after submission, by independently re-reading the chain and comparing economic reality against the expectation.

FarmDash addresses these with two separate mechanisms, and neither substitutes for the other:

  1. Bounded authority — a signed, hashed policy naming the exact mints, programs, values, and time window a session signer may act within.
  2. Independent reconciliation — a post-submission verification pass that re-reads the chain and compares actual economic deltas against the expectation.

A valid signature over a policy does not prove the swap delivered the expected output. A successful swap does not prove the agent stayed inside its grant. Only both together support a trustworthy claim.

The Authority Policy

Every bounded Solana grant carries a policy versioned as farmdash-solana-authority/v1. The policy binds:

Field Meaning
ownerPubkey The wallet that retains custody and signs the transaction.
sessionSignerPubkey The delegated signer permitted to prepare within bounds.
sessionId The active session the grant belongs to.
allowedInputMints / allowedOutputMints Exact mint allowlists — no wildcard.
allowedPrograms Program IDs the session may invoke. Jupiter v6 and v4 are both pinned explicitly.
maxValuePerSwapLamports Per-swap notional ceiling.
maxTotalValueLamports Cumulative ceiling across the grant's lifetime.
maxSlippageBps Slippage ceiling in basis points.
validAfter / validUntil Time window; outside it the policy is invalid.
nonce Replay protection.

The policy is serialized into a canonical message and hashed with SHA-256 to produce a policyHash. The owner's signature over that message is what authorizes the grant. Because the hash covers every field above, a grant cannot be widened after signing without invalidating the signature — changing a single mint or raising a limit by one lamport produces a different hash and therefore a different authorization.

Empty allowlists are fail-closed. An empty allowedPrograms or mint list denies everything; it is never interpreted as "allow anything." This is the correct default for a delegation system: ambiguity resolves to denial, not to permission.

Jupiter pinning is explicit and dual-version. FarmDash pins both the v6 program ID (JUP6LkbZbjS1jKKwapdHNy74bHTajnWDJ42Wg9UHN9Y) and the v4 program ID (JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB). Any description of the integration that claims a single pinned version is inaccurate; both are accepted, and the preparation path reports which program a route actually uses.

The 14-State Lifecycle

Solana execution moves through a fixed state machine. Each state is an explicit, queryable condition — there is no implicit transition.

PREPARING → QUOTE → SIMULATED → PREPARED → AWAITING_USER_SIGNATURE → SUBMITTED_BY_USER → CONFIRMED → FINALIZED → RECONCILED

Terminal and failure states: RECONCILIATION_FAILED, FAILED, EXPIRED, REJECTED, UNKNOWN.

Two properties deserve emphasis.

  • Preparation is leased, not held open. A preparation is valid for 30 seconds (SOLANA_PREPARATION_LEASE_SECONDS). After that it expires and cannot be submitted. This bounds the window in which a prepared payload could be replayed, front-run, or submitted against a moved market. A preparation that has expired is not a dormant asset; it is dead, and a fresh quote must be obtained.
  • The owner submits. FarmDash never server-broadcasts compatibility transactions. SUBMITTED_BY_USER is a distinct state precisely because submission is a user action, not a FarmDash one. Any description of FarmDash "executing" a Solana swap is wrong at the mechanism level: FarmDash prepares, the user signs and submits, and FarmDash verifies.

Budget reservations

Value is held against a grant through a reservation lifecycle that is separate from the execution state machine: reserved → consumed / released / held_ambiguous.

  • reserved — value is held for an in-flight preparation.
  • consumed — the swap completed and the held value is spent against the grant's cumulative budget.
  • released — the preparation expired, failed, or the transaction reverted, so the hold is returned.
  • held_ambiguous — the outcome could not be determined with confidence, so the value stays held rather than being wrongly released or consumed.

A reservation that was already released cannot be consumed, and a transaction that reverts releases the reservation rather than leaving it locked. held_ambiguous is the honest default when the chain does not give a definitive answer; it prevents a missing observation from being read as either success or failure.

Revocation

A grant is revoked by an explicit owner signature over an exact revocation message bound to that grant and policy. The proof carries its own issuance and expiry timestamps; an expired or future-dated proof is rejected, and a missing proof is rejected outright rather than treated as permission.

Revocation verification checks the signature against the owner's public key over the exact message, and the proof's nonce is scoped to one immutable grant and policy. Because revocation state is monotonic and durable, replaying a revocation is idempotent — it returns success without changing state, and it never releases budget that is still legitimately held.

Two properties are worth noting. First, revocation requires the owner's signature: commercial access to FarmDash is not wallet authority, and a paid tier cannot revoke a grant it does not own. Second, revocation does not by itself free held value; a held_ambiguous reservation remains held after revocation because the outcome was never determined, and releasing it would misstate the grant's position.

Quotes and request binding

A Jupiter quote is fetched against a specific wallet and is considered authoritative only within its freshness window. The quote carries an explicit expiry, and a quote older than that expiry is stale and cannot be used to prepare a transaction. The 30-second quote TTL is the same order as the preparation lease, so both the price and the authorization expire together rather than one outliving the other.

Requests are bound by a parameter digest covering the wallet, input mint, output mint, amount, slippage, and minimum output. If any of these drift between quote and preparation, the digest no longer matches and preparation fails closed. This prevents a quoted price from being silently reused for a materially different request.

Valid state transitions

The state machine is not merely descriptive; transitions are validated, and an invalid transition is refused rather than recorded. The rules are:

From Permitted to
PREPARING AWAITING_USER_SIGNATURE
QUOTE SIMULATED
SIMULATED PREPARED
PREPARED AWAITING_USER_SIGNATURE
AWAITING_USER_SIGNATURE SUBMITTED_BY_USER
SUBMITTED_BY_USER CONFIRMED
CONFIRMED FINALIZED
FINALIZED RECONCILED

Any state may move to a terminal failure state (FAILED, EXPIRED, REJECTED, UNKNOWN, RECONCILIATION_FAILED) — failures are always permitted. No other forward transition is valid. This means a record cannot jump from SIMULATED directly to FINALIZED, or from PREPARING to RECONCILED; the chain of evidence must be complete.

Revocation proofs

Revocation messages are versioned farmdash-solana-authority-revocation/v1 and carry a maximum lifetime of 300 seconds. A proof older than that window is rejected even if its signature is valid, because a long-lived revocation authorization is itself a risk. The proof binds the grant id, the owner public key, the policy hash, and the issuance and expiry timestamps, so it cannot be redirected to a different grant or a different policy.

Simulation evidence

Before a transaction is prepared, FarmDash simulates it and records the evidence that simulation produced. Simulation is not a formality: it establishes the expected economic shape of the transaction — input delta, output delta, and fee — before any value moves. That expectation is what reconciliation later compares against, so a swap without a recorded simulation expectation has nothing authoritative to reconcile against.

Simulation runs against resolved RPC endpoints, and the evidence records which endpoint produced the result. This matters for diagnosing discrepancies: a simulation from one RPC provider can differ from the state another provider observes, and the receipt preserves which one was used.

The simulation result is treated as evidence, not as truth about the future. It describes what the transaction would do if submitted against the observed state; it does not guarantee what will happen when it is submitted, because state can move in the interim. That gap between simulation and submission is exactly why reconciliation exists as a separate step.

Identifiers and validation

Solana identifiers are validated by shape before use. Mints and pubkeys must match the base58 alphabet and fall within the expected length range; transaction signatures must match a separate, longer pattern. Native SOL and USDC mints are pinned as constants so the common cases cannot be mistyped, and system, token, and associated-token program IDs are fixed constants rather than caller-supplied values.

Validation happens at the boundary. An identifier that fails shape validation is rejected before any quote, simulation, or preparation work begins, which prevents malformed input from being silently coerced into something that happens to resolve.

Error handling and failure classification

Failures are classified rather than collapsed into a single error. A preparation that expires is EXPIRED, distinct from one that was refused by policy (REJECTED) and distinct from one whose transaction landed but failed reconciliation (RECONCILIATION_FAILED). Each carries a different implication for value: an expired preparation holds nothing, a rejected one never held anything, and a reconciliation failure means value moved in a way that does not match the expectation.

Value handling follows the classification. An expired or rejected preparation releases its reservation immediately because no transaction exists. A reconciliation failure leaves the reservation's disposition to the reconciliation path, because the economic outcome is not yet understood. Treating all failures identically would either leak value or lock it indefinitely; the classification exists so each case gets the correct treatment.

Evidence retention

Every stage of the lifecycle retains the evidence it produced: the quote and its expiry, the simulation result and its endpoint, the preparation and its lease, the submission, and the reconciliation outcome. This is what makes a dispute diagnosable after the fact. Without retained evidence, a user reporting "the swap was worse than quoted" and an operator asserting "the quote was correct" would have no shared record to examine.

The evidence is retained per execution record and is queryable by session. An auditor can reconstruct the full sequence for a given swap and see exactly which expectation was set, which transaction landed, and where the two diverged.

Finalized Is Not Reconciled

This is the doctrine that matters most when reading FarmDash Solana state. The verification layer enforces strict semantic separation between:

  • verified — the transaction exists and its message digest matches what was prepared.
  • hasTreasuryTransfer — a fee transfer to the treasury is present.
  • confirmed — the cluster has confirmed the transaction.
  • finalized — the transaction reached finalized commitment.
  • economically reconciled — the actual economic deltas match the expectation.
  • success / fee collected — fee bookkeeping completed.

finalized only means the chain considers the transaction final. It says nothing about whether the user received the expected output, whether the input delta matched, or whether the treasury fee arrived. Only economically reconciled asserts that.

The distinction is not academic. A swap can be finalized with a far worse fill than quoted, can skip the fee transfer entirely, or can succeed while the expectation recorded a different minimum output. Each of those is a finalized transaction that fails reconciliation, and each must be reported as a failed outcome.

What Reconciliation Actually Checks

reconcileSolanaSwapReceipt re-reads the transaction from the cluster and authoritatively verifies six things:

  1. Transaction succeeded — meta.err is null. A transaction that reverted on-chain is not a successful swap regardless of what any client reported.
  2. True on-chain finality — the transaction is read at the requested commitment level, so confirmed and finalized are measured rather than assumed.
  3. The user wallet was a required signer — fee payer or authorized signer. This prevents a third party from attributing someone else's swap to a FarmDash expectation, and it is what makes the receipt binding to the session owner.
  4. Exact message digest binding — the compiled instructions were not altered between preparation and submission. If the transaction that landed differs from the transaction that was prepared, the binding fails.
  5. Exact economic deltas — principal spent, associated-token-account rent separated from principal, and output delivered. Rent is separated because creating a token account costs lamports that are not part of the swap's economic input; conflating the two would make every swap appear to spend more than it did.
  6. Treasury fee transfer — if one was expected.

A mismatch in any of these yields reconciliationStatus: 'failed' with a specific error, not a generic failure. The error identifies which check failed so an operator can diagnose the cause rather than guessing.

Commitment levels

Reconciliation reads at a configurable commitment level, defaulting to confirmed. Reading at finalized is stronger but slower. The choice is explicit because it changes what the reconciliation asserts: a confirmed reconciliation can in principle be superseded by a deeper reorg, while a finalized one cannot. FarmDash does not silently upgrade between these.

Reading a Solana Receipt Correctly

When an agent consumes a FarmDash Solana receipt, the correct interpretation order is:

  1. Check verified before anything else. If false, no further field is meaningful — there is no verified transaction to reason about.
  2. Check finality. confirmed and finalized are different commitments; do not treat one as the other.
  3. Check userSigned. A swap the user did not sign is not attributable to the session.
  4. Check reconciliationStatus. finalized with a failed reconciliation is a failed swap that happened to land on-chain.
  5. Only then read economic fields. minimumOutputSatisfied and treasuryFeeCollectedLamports support conclusions only after the preceding checks pass.

Skipping this order produces the classic error: reading a minimumOutputSatisfied: true flag on a receipt whose reconciliation failed, and reporting a successful swap.

Failure Modes and Their Meaning

Observation Interpretation
EXPIRED Preparation lease elapsed before submission. No transaction exists.
REJECTED Policy or authority check refused the action. Nothing was submitted.
RECONCILIATION_FAILED A transaction landed but its economics did not match the expectation.
held_ambiguous reservation Outcome unknown; value remains held. Not a success.
finalized without reconciliation Finality only. Do not report a settled outcome.

Capability Boundaries

Solana support in FarmDash is preparation and verification, not autonomous execution. The owner signs and submits; FarmDash prepares, bounds, and reconciles. Do not describe this surface as a FarmDash-controlled signing lane, and do not imply that a finalized transaction constitutes a settled or reconciled outcome.

Consult the live capability contract for current authorization and execution state before making any claim about what an agent can do on Solana. Documentation describes the mechanism; it is not execution qualification.

Continue researching