# Example contracts

Three complete contracts, matching the implemented semantics of the compiler and VM. All three come from the compiler's examples/ directory and compile with sclc today.

> Part of the SQRL documentation, section "Protocol".
> Rendered page: https://docs.sqrl.tech/protocol/contracts/example-contracts

## A token contract

Demonstrates field protection via `@writeable_by`, caller gating with `SENDER_ADDRESS()`, overflow and supply-cap checks, and persistent balances in a map.

```scl
contract Token {
    @writeable_by(init, transfer_ownership)
    owner: Str;
    @writeable_by(init, mint, burn)
    total_supply: Int;
    @writeable_by(init, pause, unpause)
    paused: Int;
    @writeable_by(init)
    max_supply: Int;
    @writeable_by(init)
    initialised: Int;

    fn init(owner_addr: Str) {
        if (initialised == 1) {
            return 0;
        }
        owner = owner_addr;
        total_supply = 0;
        paused = 0;
        max_supply = 50000000000000000;
        initialised = 1;
        MAP_SET("balances", owner_addr, 0);
        return 1;
    }

    fn mint(to: Str, amount: Int) {
        let sender = SENDER_ADDRESS();
        if (paused == 1) {
            return 0;
        }
        if (owner != sender) {
            return 0;
        }
        let current = MAP_GET("balances", to);
        let sum = current + amount;
        if (sum < current) {
            return 0;   // overflow check
        }
        let temp = total_supply + amount;
        if (temp > max_supply) {
            return 0;
        }
        MAP_SET("balances", to, sum);
        total_supply = total_supply + amount;
        return 1;
    }

    fn transfer(to: Str, amount: Int) {
        if (paused == 1) {
            return 0;
        }
        let sender = SENDER_ADDRESS();
        let sender_balance = MAP_GET("balances", sender);
        let recipient_balance = MAP_GET("balances", to);
        if (sender_balance < amount) {
            return 0;
        }
        MAP_SET("balances", sender, sender_balance - amount);
        MAP_SET("balances", to, recipient_balance + amount);
        return 1;
    }

    fn pause() {
        let sender = SENDER_ADDRESS();
        if (owner != sender) {
            return 0;
        }
        paused = 1;
        return 1;
    }

    fn balance_of(addr: Str) {
        return MAP_GET("balances", addr);
    }

    fn get_total_supply() {
        return total_supply;
    }
}
```

Note the patterns: functions return `1` for success and `0` for failure; the `initialised` flag makes `init` one-shot; and every state-changing function checks `paused` and the caller before touching a balance.

## A name registry with events

A minimal registry showing event emission for off-chain indexing. Clients subscribe to `NameRegistered` and `NameTransferred` via the node's events API instead of polling state.

```scl
contract BNS {
    event NameRegistered(name: Str, owner: Str);
    event NameTransferred(name: Str, old_owner: Str, new_owner: Str);

    fn register(name: Str, owner: Str) {
        MAP_SET("names", name, owner);
        emit NameRegistered(name, owner);
        return 1;
    }

    fn transfer(name: Str, new_owner: Str) {
        let old_owner = MAP_GET("names", name);
        MAP_SET("names", name, new_owner);
        emit NameTransferred(name, old_owner, new_owner);
        return 1;
    }

    fn lookup(name: Str) {
        return MAP_GET("names", name);
    }
}
```

## A staking contract with cross-contract calls

Demonstrates `CALL` (moving tokens in as the user) versus `CALL_AS_CONTRACT` (paying tokens out as the contract), block-height time-locks, and storage cleanup.

```scl
contract Staking {
    @writeable_by(init)
    token_contract_id: Str;

    fn init(token_contract_id_param: Str) {
        token_contract_id = token_contract_id_param;
        return 0;
    }

    fn stake(sender: Str, amount: Int, lock_until: Int, btc_txid: Str) {
        MAP_SET("stakes", sender, amount);
        MAP_SET("locks", sender, lock_until);
        MAP_SET("txids", sender, btc_txid);
        return CALL(token_contract_id, "transfer", ["Staking", amount]);
    }

    fn claim(sender: Str, btc_txid: Str, current_block: Int) {
        let lock_until = MAP_GET("locks", sender);
        let staked_amount = MAP_GET("stakes", sender);

        if (current_block < lock_until) {
            return 0;
        }
        MAP_SET("stakes", sender, 0);
        MAP_SET("locks", sender, 0);
        MAP_SET("txids", sender, "");
        return CALL_AS_CONTRACT(token_contract_id, "transfer", [sender, staked_amount]);
    }
}
```

The `stake` path uses `CALL`, so the token contract sees the original caller and debits *their* balance. The `claim` path uses `CALL_AS_CONTRACT`, so the token contract sees the staking contract as the sender and pays out from the stake pool it holds.

  Only use built-ins listed in the [Built-ins](/protocol/contracts/built-ins) section. Do not rely on helpers that are not present in the compiler registry yet.

More examples (vesting with multiple beneficiaries, signature-gated emitters, and more) live in the [compiler repository's `examples/` directory](https://github.com/Dark-Fusion-Protocol/scl-compiler).
