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.
submitCurveUpdatescosts 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.
The recommended flow
- Build the
submitCurveUpdatesinstruction. - Simulate a transaction containing
submitCurveUpdatesfollowed byvalidateCurveUpdates.- Error
73(ValidationSimulationSuccess) on the validate instruction means the batch is valid. - Any other error is the exact error the real apply would return.
- Error
- Remove
validateCurveUpdatesand sendsubmitCurveUpdates, typically in the same transaction as yourupdateMidprice. 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
SimulatesubmitCurveUpdates and validateCurveUpdates together, so the dry-run checks the batch you are about to send:
L-06 apply[2] ct=0 kind=Edit idx=4 fail=point-op-validation.
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.validateCurveUpdates and send submitCurveUpdates with your oracle update under a tight compute-unit limit:
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
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(error9). Validate catches this, so reorder the ops and simulate again. - Indexes follow earlier ops.
pointIndexandexpectedXInrefer to the curve after the earlier ops in the batch. After anAddorRemove, 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:
setCurveon 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
setCurveor sendapplyCurveUpdatesyourself.
Errors
See Errors for the full list.