← All documentation

WarpScript Contracts

WarpScript is WarpCoin's declarative, no-code smart-contract model. Users compose agreements from typed parameters and when/then clauses in a visual studio (no Solidity, no CLI); the compiler turns the design into a deterministic, content-addressed artifact that WarpVM executes on-chain. A deployed contract custodies real WARP, and the chain moves those funds by re-running WarpVM during block processing — with no contract private key. See On-chain execution (WarpVM) below.

A defining property: the compiler is byte-compatible across implementations. The Go node compiler and the WarpWallet TypeScript compiler produce the identical contract id and W… contract address for the same spec — verified by a cross-language golden test.


The contract model

A ContractSpec (schema warpscript/v1) is:

{
  "schema": "warpscript/v1",
  "name": "Milestone Escrow",
  "description": "Two-party escrow with arbiter fallback.",
  "author": "W…",                 // creator's address
  "network": "earth",             // earth | luna | mars | interplanetary
  "params":  [ Param,  … ],
  "clauses": [ Clause, … ],
  "createdAt": 1718360000000
}

Param — a typed input:

{ "key": "amount", "label": "Amount (flux)", "type": "amount", "value": "", "required": true }

typeaddress | tag | amount | duration | number | text | date | boolean.

Clause — a when/then rule:

{
  "id": "release",
  "name": "Release to seller",
  "trigger":    { "type": "on_approval", "ref": "buyer" },
  "conditions": [ { "type": "any_approved", "ref": "buyer,arbiter" } ],
  "actions":    [ { "type": "release", "to": "seller", "amount": "amount" } ]
}

Building blocks (palette)

Triggers Conditions Actions
manual always transfer
on_fund signed_by release
on_approval all_approved / any_approved refund
on_deadline amount_at_least split
on_oracle before / after lock
on_light_time light_time_elapsed notify

The on_light_time trigger and light_time_elapsed condition make inter-planetary contracts possible: settlement that waits for the round-trip light delay to the destination world to elapse before finalizing. The on_oracle trigger fires from a signed oracle feed — both are supplied to WarpVM as deterministic, on-chain inputs (see below).


Determinism & contract addresses

The compiler is fully deterministic. The content hash is taken over a canonical JSON serialization — object keys sorted recursively, compact, no HTML escaping — so the same spec always hashes the same way, in any language:

contractId      = hex( sha256d( canonicalJSON(spec) ) )
contractAddress = Base58Check( 0x49 || sha256d(canonicalJSON)[0:20] )

The contract address reuses the account address scheme (version byte 0x49), so contract addresses are indistinguishable in form from account addresses and begin with W. Identical specs ⇒ identical addresses across the web app and the node.

Compiler output

Compile(spec) returns:

  • contractId — hex content hash.
  • contractAddress — deterministic W… address.
  • warpscript — a human-readable source rendering of the spec.
  • bytecode — the machine artifact WarpVM loads and executes (params, clauses).
  • warnings — static-analysis findings (missing required values, unknown param references, clauses with no actions, …).

Example rendered WarpScript:

contract "Milestone Escrow" {
  network earth
  author W…
  param buyer: address required
  param seller: address required
  param amount: amount required

  clause "Release to seller" {
    on on_approval(buyer)
    when any_approved(buyer,arbiter)
    do release(amount to seller)
  }
}

Templates

The studio ships starter templates that build a complete spec for you:

Template Category What it does
Milestone Escrow Commerce Buyer funds; release on approval, else refund after a deadline.
Time-Locked Vesting Treasury Lock WARP for a beneficiary until a release date.
Multisig Treasury Treasury Pay out only on a quorum of signer approvals.
Interplanetary Delayed Transfer Interplanetary Finalize only after the round-trip light delay elapses.
Subscription Commerce Recurring per-period payout to a merchant.

API

Endpoint Method Purpose
POST /contract/compile POST { spec } → compiled artifact (no deploy; live preview)
POST /contract/deploy POST { spec } → stored, content-addressed contract + warnings
GET /contract/get?id=<contractId> GET fetch a deployed contract
GET /contract/list?author=<addr> GET list deployed contracts (optionally by author)
GET /contract/templates GET the template catalog
GET /contract/palette GET available triggers, conditions, and actions

On-chain execution (WarpVM)

WarpVM is WarpCoin's contract engine, and it runs as consensus. A contract's compiled artifact becomes consensus state, it custodies real WARP, and the chain settles it by re-running WarpVM during block processing — overflow-safe, gas-bounded, and fully deterministic (time comes from the block timestamp, never a wall clock). There is no contract private key; the chain itself moves the funds.

Contract interactions ride on ordinary signed transactions via a ContractOp field — the transaction's own signature authorizes the operation:

Op Consensus effect
deploy compile the spec, register it, create VM state
fund debit the sender; add to the contract's custodied balance; fire on_fund; record the funding time
approve record the sender's approval and re-evaluate
invoke fire manual / time-based clauses
oracle record a signed oracle feed and fire the matching on_oracle clauses

Deterministic trigger feeds. on_oracle fires when the address named by the clause's referenced param submits a signed oracle op — the signature is the authorization, so no oracle key lives on-chain. on_light_time / light_time_elapsed fire once the round-trip light delay to the destination world (computed from the block clock) has elapsed since funding. Both are pure functions of consensus state, so every node derives identical settlement.

Mempool pre-simulation. A contract-op transaction that would fail execution is rejected before it is gossiped or mined, so a failing op can never invalidate the block that includes it.

Money is conserved exactly: the sum of account balances plus contract custody equals the issued supply. Clients submit these as transactions (POST /tx) and read on-chain state with GET /chain/contract?id=; the CLI wraps both:

warpcoin contract deploy  --template milestone-escrow \
  --params "buyer=W..,seller=W..,amount=5000,deadline=9000000000"
warpcoin contract fund    --id <contractId> --amount 5000   # flux
warpcoin contract approve --id <contractId>                 # releases on-chain
warpcoin contract oracle  --id <contractId> --ref <param>   # fire a signed feed
warpcoin contract show    --id <contractId>                 # on-chain state