Auto-ticket expressions

An auto-ticket expression is a small formula that returns one number: the total number of satoshis to allocate to a ticket, including the ticket fee. The formula can use the payment amount and the current fees, so it can express fixed budgets, percentages, caps, minimums, and conditional pricing without application code.

Core evaluates the expression once for each confirmed payment received by an auto-ticket address. This page documents the expression language and exact evaluator. For the payment-address lifecycle, confirmations, metadata, and monitoring, start with the auto-ticket deposit address guide.

budget = FLOOR(your formula); 0 ≤ budget net_amountthe returned number is floored, then checked against the available net amount and ticket fee
Inputs

Four values in, one budget out.

Every value is a number of satoshis. Variable names are case-insensitive, soNET_AMOUNT and net_amount are equivalent.

  • gross_amount

    The full confirmed payment before the deposit fee is deducted.

  • deposit_fee

    The amount charged to process the payment. It is capped at the gross amount, so net_amount can never be negative.

  • net_amount

    The amount available for the ticket budget and balance remainder. It is always gross_amount - deposit_fee.

  • ticket_fee

    The flat fee for creating one ticket, snapshotted for this evaluation. A budget must be greater than this fee to leave a positive contribution.

Example: allocate 80% of the net payment

For NET_AMOUNT * 0.8, assume a payment of 100,000 sats, a deposit fee of 58 sats, and a ticket fee of 100 sats:

gross_amount = 100,000net_amount = 100,000 − 58 = 99,942budget = FLOOR(99,942 × 0.8) = 79,953ticket contribution = 79,953 − 100 = 79,853balance remainder = 99,942 − 79,953 = 19,989

The formula returns the 79,953-sat budget. Core, not the expression, subtracts the ticket fee and calculates the balance remainder.

Try it

The playground runs the real evaluator.

Change the four input values, write an expression, and inspect the exact returned budget, ticket contribution, and balance remainder. The playground uses the same parser, floating-point arithmetic, flooring, range checks, and error messages as Core.

Formula
Sample deposit

Sample amounts in sats. Real deposits use the fees Core has configured at confirmation time; the deposit fee is capped at the gross deposit.

createdTicket created — 4,900 sats play

The budget is 5,000 sats: 100 pay the ticket fee, 4,900 become the ticket's contribution, and 4,942 stay as balance.

Where the 10,000-sat deposit goes
  • Deposit fee58
  • Ticket fee100
  • Contribution4,900
  • Balance4,942
  1. Formula returns5,000
  2. Floor5,000
  3. Within 0…9,942?5,000 — yesthe ticket budget
  4. Above the 100-sat fee?yes — ticket
Across deposit sizesup to 19,842 sats play

Solid: sats that play at each deposit size. Dashed: the most that could play there (net amount minus the ticket fee). The marker is the sample deposit above.

Starting points
Use it

The formula travels in one field when you create the deposit address: autoTicket.expression on POST /api/partners/{partnerPayoutAddress}/deposit-addresses. It is validated there and immutable afterwards.

{
  "id": "018f58d2-2800-4000-8000-000000000457",
  "metadata": {
    "orderId": "private-order-123"
  },
  "autoTicket": {
    "expression": "MIN(net_amount, 5000)",
    "metadata": {
      "orderReference": "public-order-123"
    }
  }
}
The language

Small on purpose.

Four variables, seven numeric functions, arithmetic, comparisons, and an eager IF. No loops, no strings, no state — every valid formula reads four numbers and halts with one. Names and keywords are case-insensitive. Numbers use IEEE-754 binary64, with integer and decimal forms like 0.75 plus scientific forms like 1.5e3. Calculations can produce infinities and NaN. TRUE andFALSE exist only for conditions.

MIN(a, …)Returns the smallest argument. Commonly used to cap a ticket budget.MIN(9942, 5000) → 5000
MAX(a, …)Returns the largest argument. Commonly used to set a budget floor.MAX(1000, 250) → 1000
ABS(x)Absolute value.ABS(-40) → 40
CLAMP(x, lo, hi)x bounded into lo…hi. Bounds that cross fail at runtime.CLAMP(12000, 0, 5000) → 5000
FLOOR(x)Round down toward negative infinity.FLOOR(7456.5) → 7456
CEIL(x)Round up toward positive infinity.CEIL(7456.1) → 7457
ROUND(x)Nearest integer, halves away from zero.ROUND(2.5) → 3
IF(cond, then, else)Eager — the condition and both numeric branches are evaluated.IF(9942 > 5000, 5000, 0) → 5000

Precedence, strongest first

  1. binds first( … )Grouping — the innermost group is evaluated first.
  2. 2^Exponent, right-associative: 2 ^ 3 ^ 2 is 512, not 64.
  3. 3+x, -xUnary sign.
  4. 4*, /, %Multiply, divide, modulo with IEEE-754 binary64 behavior.
  5. 5+, -Add, subtract.
  6. 6=, ==, !=, <, <=, >, >=Numeric comparison to a boolean. Chains like a < b < c are rejected.
  7. 7NOTBoolean negation.
  8. 8ANDBoolean and. Both operands are evaluated.
  9. binds lastORBoolean or. Both operands are evaluated.

Types never mix: arithmetic refuses booleans, conditions refuse bare numbers, and the finished formula must return a number — a bare comparison is rejected when the address is created. Infinities and NaN can flow through intermediate calculations, but the final floored budget must be a finite safe integer from zero through net_amount. Use MIN, MAX, or CLAMP when you want explicit saturation.

Evaluation contract

How Core interprets the result.

The expression language uses IEEE-754 binary64 arithmetic, but a ticket budget must end as a finite whole-satoshi value within the available net amount.

  1. Parse and type-check

    Unknown names, incorrect function arguments, type mixing, and a boolean final value reject the expression. Syntax errors include their character position.

  2. Evaluate every branch

    Functions and operators use binary64 numbers. Logical operands and both branches of IF are evaluated eagerly; do not rely on short-circuiting to hide an invalid calculation.

  3. Floor the returned number

    Core applies FLOOR to the final numeric result. Intermediate calculations may be fractional, but the resulting budget is always a whole number of satoshis.

  4. Check the budget range

    The floored result must be finite and satisfy 0 ≤ budget ≤ net_amount. Core does not silently clamp an out-of-range result.

  5. Apply the ticket fee

    A budget greater than ticket_fee leaves a positive ticket contribution. A smaller valid budget or an invalid result does not create a ticket; the address guide explains the resulting payment states.

  6. Enforce expression limits

    Source is limited to 500 characters, 256 syntax nodes, and 32 nesting levels. These limits are checked before the expression is stored.

Ship it

Store the finished expression.

Send the validated source text as autoTicket.expression when creating an auto-ticket deposit address. The stored expression is immutable; create another address when the formula needs to change.