Formula language reference
Formulas are string expressions evaluated at transaction build time. They appear
in output/input amount_sat, a param's compute, hook set values, and witness
expr.
Operators
| Operator | Description |
|---|---|
+ - * / | Integer arithmetic (division truncates) |
== != < <= > >= | Comparison (returns boolean) |
&& || ! | Boolean logic |
( ) | Grouping |
References
| Syntax | Description |
|---|---|
instance.NAME | Contract-template field value, from the instance |
params.NAME | Action parameter by name |
input_id.amount_sat | Satoshi amount of a resolved input |
input_id.asset | Asset ID of a resolved input (hex string) |
input_id.present | Boolean — whether an optional input was found |
asset | (inside an input's own on_resolved only) that input's asset, including one it has just issued |
reissuance_token | (same) the matching reissuance-token asset |
output_id.amount_sat | Satoshi amount of a constructed output (post-construction) |
fee | Estimated transaction fee (used in change and re-lock formulas) |
The $ prefix
Two spellings of a reference exist, and they are not interchangeable:
| Spelling | Where | Meaning |
|---|---|---|
params.NAME, instance.NAME | inside a formula — amount_sat, a compute expression, a hook set value | a term in an expression that is evaluated |
$params.NAME, $instance.NAME, $inputs.ID.FIELD | as a whole value — a create_instance.fields entry, a witness key | take this value as-is; no arithmetic |
The rule of thumb: $ means "this entire value is that reference". Where a
string is parsed as an expression, write the bare form and the evaluator resolves
it; where a string stands for one value and nothing more, the $ says so.
"create_instance": {
"fields": {
"COLLATERAL_AMOUNT": "$params.COLLATERAL_AMOUNT",
"PRINCIPAL_INTEREST_AMOUNT": "params.PRINCIPAL_AMOUNT * params.RATE / 10000"
}
}
Both forms are legal in create_instance.fields: the first copies a resolved
param straight through, the second is an expression that happens to live there.
$inputs.<input_id>.<field> reaches a resolved input — most usefully
$inputs.<id>.issuance_entropy, the value a reissuance later needs, and
$inputs.<id>.issued_asset. It has no bare equivalent; an input's amount and
asset are reached in formulas as input_id.amount_sat and input_id.asset.
Functions
| Function | Signature | Description |
|---|---|---|
pow(base, exp) | (u64, u64) → u64 | Integer exponentiation |
concat(a, b, …) | (bytes…) → bytes | Byte concatenation — OP_RETURN data only, not a general formula function |
There is no way to resolve an input or output
idto its transaction index. A covenant that needs to be told a position (asset_auth'sINPUT_ASSET_INDEX, for instance) takes a literalu32witness, written by hand against the order the inputs and outputs are declared in. See Settling the loan.
Comparison and boolean operators exist but have nowhere to be used on their own: there is no rule block that takes a predicate. They are there for the conditional parts of arithmetic, not for validation.