Skip to main content
setCurve rewrites an entire curve slot and validates every segment of it in the same transaction. For smooth curves this can cost tens of thousands of compute units, all in your update transaction. Queued curve updates split that work in two:
  • Your transaction only writes the edits into a small buffer. submitCurveUpdates costs 58 CU regardless of batch size.
  • The validation work runs when the batch is applied, which by default is the next swap on the pool.
A smaller compute-unit limit means a cheaper priority fee for the same price per CU, and a transaction that lands more reliably when blocks are busy. That makes queued updates a good fit for operators who update the curve alongside every oracle tick. Three instructions make up this flow:
Because the next swap applies the queued batch, an invalid batch makes every swap on the pool fail with that batch’s error until you replace it. Always validate a batch with validateCurveUpdates before you send it.

  1. Build the submitCurveUpdates instruction.
  2. Simulate a transaction containing submitCurveUpdates followed by validateCurveUpdates.
    • Error 73 (ValidationSimulationSuccess) on the validate instruction means the batch is valid.
    • Any other error is the exact error the real apply would return.
  3. Remove validateCurveUpdates and send submitCurveUpdates, typically in the same transaction as your updateMidprice. The next swap applies the batch.
validateCurveUpdates never commits state, so a transaction that contains it always fails. Include it only when simulating.

submitCurveUpdates

Each submit replaces the buffer; it does not append. If you submit twice before the buffer is applied, only the second batch remains.

validateCurveUpdates

Simulate submitCurveUpdates and validateCurveUpdates together, so the dry-run checks the batch you are about to send:
On failure the simulation logs name the op that failed, for example L-06 apply[2] ct=0 kind=Edit idx=4 fail=point-op-validation.
You can also call validateCurveUpdates on its own to check a batch that is already queued on-chain.

Send the update

Deferred validation can halt swaps on your pool. submitCurveUpdates does not check your ops. They are only checked when the batch is applied, which is usually inside the next swap. If the batch is invalid, every swap on the pool fails until you submit a valid batch to replace it.This is the tradeoff for keeping validation out of your update transaction. Never send a batch without first simulating it with validateCurveUpdates. If you cannot simulate first, use setCurve, which rejects a bad curve in your own transaction.
After the simulation passes, remove validateCurveUpdates and send submitCurveUpdates with your oracle update under a tight compute-unit limit:
The Hadron instructions in this transaction use under 100 CU (updateMidprice about 37, submitCurveUpdates 58). Each compute-budget instruction adds about 150 CU, so a limit of 1,000 leaves plenty of headroom.
Until the next swap applies the batch, the curve account still holds the old points, and off-chain quoters (including aggregators) quote from it. The swap that applies the batch executes against the new points. Send applyCurveUpdates yourself if you need the new points live and quoted before the next trade.

applyCurveUpdates

Applies every queued op in order and clears the buffer, exactly as the next swap would. If any op fails, the whole instruction fails and nothing changes. Applying an empty buffer is a no-op. Use it when you want the edits live immediately and are willing to pay the validation CU yourself.

Batch rules

  • Ops apply in order. Each op is checked against the curve as the earlier ops in the same batch left it, not against the final curve. A set of edits that is valid in the end can still fail midway. For example, to move two neighbouring points to the right, edit the right-hand point first. If you edit the left-hand point first, it lands past its old neighbour and the op fails with CurvePointsNotSorted (error 9). Validate catches this, so reorder the ops and simulate again.
  • Indexes follow earlier ops. pointIndex and expectedXIn refer to the curve after the earlier ops in the batch. After an Add or Remove, the points to its right shift by one.
  • One failure fails the batch. No partial apply.
  • Max 28 ops per submit.

Where the compute units go

Validation cost depends on the curve’s interpolation and on how many segments are checked. setCurve checks every segment. A queued op checks only the segments next to the point it touches (at most two). Measured on the deployed program: With the queue, your transaction pays only the 58 CU for submitCurveUpdates. The right-hand column is paid by whoever applies the batch: the next swap, or you if you send applyCurveUpdates. validateCurveUpdates costs the same as an apply, but only in simulation.
  • Updating the curve with every oracle tick: use the queue. Your update transaction stays under 100 CU of Hadron work however long or smooth the curve is.
  • Short or cheap curves: setCurve on a 2-point flat curve already costs under 700 CU, so the queue saves little.
  • Keep batches small. The swap that applies the batch pays about 1,000–5,700 CU per op on top of its own cost. A large batch can push an aggregator’s swap over the compute budget it simulated. For large reshapes, use setCurve or send applyCurveUpdates yourself.

Errors

See Errors for the full list.