SCL contract overview

SCL contracts are small, deterministic programs. You write one contract per file, anchor the compiled contract to a Bitcoin UTXO, and verify every state change against that anchor plus Bitcoin-derived context.

Updated 08 Nov 20263 min read

What "deterministic" means here

  • No randomness. No system time.
  • No unbounded control flow; SCL is intentionally not Turing complete.
  • Same payload + same anchor + same Bitcoin context → the same result on every honest node.
  • Disagreements are objective: invalid calls are dropped, not "outvoted."

What lives on Bitcoin vs off-chain

  • On Bitcoin: the deploy commitment (a hash of the compiled bytecode) and a commitment for every call (a protocol stamp of the signed call envelope).
  • Off-chain: mutable state (balances, ownership, listings, pools), maintained by nodes and provable against the anchors.
success:

SCL's bounded behaviour and non-Turing-complete, deterministic core gives convergent replay, and is cheap to verify at scale.

#Install the compiler

You need a stable Rust toolchain with Cargo.

bash
git clone https://github.com/Dark-Fusion-Protocol/scl-compiler
cd scl-compiler
cargo build --release

The binary is created at:

text
target/release/sclc

#Compile

The CLI is positional:

bash
sclc compile <contract.scl> [options]

A minimal contract you can compile now:

scl
contract Hello {
    greeting: Str;

    fn init(who: Str) {
        greeting = who;
    }

    fn greet() {
        PRINT("hello:", greeting);
        return 1;
    }
}

Compile it, emitting bytecode, ABI, and metadata in one JSON blob:

bash
sclc compile hello.scl --json > hello.artifact.json

#Deploy

Deployment is a two-step act: commit the contract on Bitcoin, then register the artifact with an SCL node.

  1. Anchor on Bitcoin. Publish the contract commitment in a Bitcoin transaction, as specified by the protocol.
  2. Register with a node. Send the compiled artifact to the node's deploy endpoint, referencing the anchoring transaction:
bash
curl -X POST http://localhost:8080/deploy_contract \
  -H 'content-type: application/json' \
  -d '{
        "txid": "<bitcoin-txid-with-your-commitment>",
        "bytecode": "<hex bytecode>",
        "abi": [ ... ],
        "function_offsets": { ... },
        "function_offset_to_locals": { ... },
        "constants": [ ... ]
      }'

The bytecode, abi, function_offsets, function_offset_to_locals, and constants fields come straight out of sclc compile --json.

The same artifact deploys unchanged to a banking subnet. Register it with the subnet's nodes instead of a public one: its state stays with the subnet's members, while its commitment and every call are anchored to Bitcoin exactly as on the canonical ledger.

#Call a function

Calls are signed call envelopes, anchored on Bitcoin and submitted to a node:

  1. Build and sign the envelope (contract ID, function, arguments, caller key, call ID, signature). The wallet SDKs and the browser signer do this for you.
  2. Anchor it: broadcast a Bitcoin transaction that carries the envelope's protocol stamp and spends the outpoint the envelope names.
  3. Submit to a node:
bash
curl -X POST http://localhost:8080/contract_call \
  -H 'content-type: application/json' \
  -d '{
        "txid": "<bitcoin-txid-of-the-anchoring-tx>",
        "contract_id": "<contract-id>",
        "payload": "<base64 Borsh-encoded CallEnvelope>"
      }'

Check the call's status:

bash
curl http://localhost:8080/contract_call/<txid>/status

The node validates the envelope's anchor binding at intake and again at confirmation, then applies the deterministic transition once the Bitcoin transaction confirms. See Settlement and validation for the full pipeline, and the Node API reference for every endpoint.

warning:

Do not assume this REST surface is stable. Treat it as the current implementation, not a long-term public API.

#Standards and state classification

Contracts can declare conformance to versioned interfaces like utxo_token_v1, which brings enforced standard shapes, wallet and Lightning legibility, and compact on-chain operations. See Interfaces for the syntax and guarantees.

Interface functions are also classified as touching global or partitioned state, which is what keeps one user's withheld data from ever freezing another user's assets. See Global and partitioned state.

#Next steps

Read Language basics to see the syntax you can use today. Then see Built-ins for what is implemented end to end. For how execution is metered and what it costs, see XRB and network economics.

Was this page helpful?