part of Ferros
// the smart contract language for Ferros

The language your contracts deserve.

Cudo is a programming language where the compiler proves your parallelism is safe, double-spend is a type error, and reentrancy doesn't exist in the grammar. Hand-write it or point your LLM at it — the compiler catches everything either way.

01 What it looks like

Every Cudo program is a contract. Operations declare what they require, what they touch, and what they emit. The compiler holds you to it.

token.cudo cudo
contract Token<Symbol: copy + drop> {
    version: 1
    contention: per<address>    // Alice→Bob doesn't block Carol→Dave

    state {
        total_supply: u256,
        balances:     Map<address, u256>,
    }

    invariant conservation:    // compiler proves this. no SMT. no tests.
        self.total_supply == self.balances.values().sum()

    operation transfer(to: address, amount: u256)
        requires: self.balances[caller] >= amount
        mutates:  self.balances[caller], self.balances[to]
        emits:    Transfer
    {
        self.balances[caller] -= amount;
        self.balances[to]     += amount;
        emit Transfer { from: caller, to, amount };
    }
}

That's a full token contract. The mutates: clause is enforced — touch state you didn't declare and the compiler rejects it. The invariant is proven after every operation, structurally, no solver needed.

02 Try to break it

Pick a bug. See the exact compiler error. These aren't runtime panics — your code never gets to run.

your_code.cudo
resource Coin { amount: u256 }

operation steal(coin: Coin) {
    send(coin, alice);
    send(coin, bob);   // use after move
}
cudo check
error[E0301]: resource used after move
  --> your_code.cudo:5:10
  |
4 |     send(coin, alice);
  |          ---- moved here
5 |     send(coin, bob);
  |          ^^^^ value used after move
  |
  = note: Coin is a linear resource and
         can only be used once
your_code.cudo
operation oops(payment: Coin) {
    if is_valid {
        send(payment, vendor);
    }
    // else? payment just... vanishes?
    // nope.
}
cudo check
error[E0302]: resource not consumed on all paths
  --> your_code.cudo:1:22
  |
1 | operation oops(payment: Coin) {
  |                ^^^^^^^ not consumed
  |
  = note: `payment` is dropped when the else
         branch is taken (line 4)
  = help: return it, transfer it, or
         explicitly destroy it
your_code.cudo
operation sneaky_transfer(to: address, amt: u256)
    mutates: self.balances[caller]
    // "forgot" to declare self.balances[to]
{
    self.balances[caller] -= amt;
    self.balances[to]     += amt;  // gotcha
}
cudo check
error[E0401]: mutation not in declared set
  --> your_code.cudo:6:5
  |
2 |     mutates: self.balances[caller]
  |              -------- declared set
  ...
6 |     self.balances[to] += amt;
  |          ^^^^^^^^^^^ not in mutates clause
  |
  = help: add self.balances[to] to the
         mutates clause
your_code.cudo
invariant conservation:
    self.total_supply == self.balances.values().sum()

operation free_money(amount: u256)
    mutates: self.total_supply
{
    self.total_supply += amount;
    // balances untouched. oops.
}
cudo check
error[E0501]: invariant 'conservation' violated
  --> your_code.cudo:4:1
  |
1 | invariant conservation:
  |           ------------ defined here
  ...
7 |     self.total_supply += amount;
  |     ^^^^^^^^^^ scalar modified without
  |     matching map update
  |
  = note: conservation requires
         self.balances delta == total_supply delta
03 The CLI

One binary. Full pipeline — parse, type-check, verify invariants, compile to two ISAs, execute with gas metering. No plugins, no toolchain sprawl.

terminal cudo check --schedule
$ cudo check examples/token.cudo --schedule Parsed 1 contract, 3 operations, 2 events Type check passed (linear resources verified) Invariant 'conservation' proven (zero-sum on map) Invariant 'no_negative' proven (requires clause bound) schedule analysis (contention: per<address>): transfer(A,B) transfer(C,D) parallel (disjoint partitions) transfer(A,B) transfer(A,C) ordered (shared partition: A) mint(X) transfer(X,Y) ordered (shared: total_supply) 0 errors, 0 warnings. Checked in 2ms.
terminal cudo compile
$ cudo compile examples/token.cudo -o token.tbc compiling Token<Symbol>... transfer stack: 24 ops register: 16 ops (-33%) mint stack: 18 ops register: 12 ops (-33%) burn stack: 8 ops register: 6 ops (-25%) Written to token.tbc (482 bytes, dual-ISA)
terminal cudo run
$ cudo run examples/token.cudo transfer --default-args executing transfer on register ISA... Preconditions met Execution complete gas used: 847 mutations: balances[caller], balances[to] events: Transfer { from: 0xaa.., to: 0xbb.., amount: 100 } state: all invariants hold
cudo check [file] --schedule

Check & Prove

Parse, type-check, verify linear resources, prove invariants, and analyze parallelism schedule. One command.

cudo compile [file] -o [out]

Dual-ISA Compile

Every operation compiles to both stack bytecode and a 256-register ISA. The fast path is automatic — 25-35% fewer instructions.

cudo run [file] [op] --default-args

Execute & Meter

Run any operation with gas metering, mutation tracking, and event capture. Invariants re-checked post-execution.

cudo inspect [file]

Inspect

Print contract structure: state fields, operations, capabilities, invariants, contention mode. Know what you're deploying.

cudo check [file] --proofs

Export Proofs

Output invariant proofs as structured JSON. Pipe them to CI, attach to audits, or feed to external verifiers.

cudo init [name] --contract [type]

Scaffold

Bootstrap a new contract from built-in scaffolds: token, orderbook, wallet, escrow. Get to the interesting part faster.

04 Your LLM already knows how to write it

Cudo was designed from day one to be written by humans and AI together. Explicit semantics, structured declarations, and a compiler that catches everything means your LLM copilot can ship production contracts — and the compiler will tell it when it's wrong.

prompt you → LLM
Write me a token with per-address parallelism,
a conservation invariant, and freeze capability.
↓ your LLM generates cudo — the compiler verifies it
generated.cudo LLM output
contract Token<Symbol> {
    contention: per<address>
    capability Freezer;

    state {
        total_supply: u256,
        balances: Map<address, u256>,
        frozen: Set<address>,
    }

    invariant conservation:
        self.total_supply == self.balances.values().sum()

    operation transfer(to: address, amount: u256)
        requires: !self.frozen.contains(caller)
                  && self.balances[caller] >= amount
        mutates: self.balances[caller], self.balances[to]
    {
        self.balances[caller] -= amount;
        self.balances[to]     += amount;
    }
}

Deterministic & explicit

No implicit state, no hidden side effects. Every operation declares its full contract. LLMs don't have to guess what's safe — the structure tells them.

The compiler is the reviewer

LLM wrote bad code? The compiler rejects it with the exact error and a fix suggestion. Same errors you saw in section 02. No audit needed for the basics.

Paste the spec, start building

Drop the language spec into your context window. Your LLM can write valid Cudo in the first prompt. The grammar is small and regular — designed to be learned fast by humans and machines alike.

─── ◆ ───
05 Parallelism you can see

EVM: global lock. Sui: binary owned/shared. Cudo: you declare the partition key, the scheduler proves non-interference. No speculation, no rollback.

per<address> partition by account
per<Pair> partition by trading pair
owned single-owner sequential
global consensus-ordered
scheduler view
06 Real programs

Not toy examples. These ship.

stablecoin.cudo 78 loc
contract CompliantStablecoin<Symbol> {
    version: 1
    contention: per<address>

    capability Minter;    // not a role check — a type constraint
    capability Freezer;

    state {
        total_supply: u256,
        balances:     Map<address, u256>,
        frozen:       Set<address>,
    }

    operation transfer(to: address, amount: u256)
        requires: !self.frozen.contains(caller)
                  && self.balances[caller] >= amount
        mutates:  self.balances[caller], self.balances[to]
    {
        self.balances[caller] -= amount;
        self.balances[to]     += amount;
    }

    operation mint(to: address, amount: u256)
        requires: caller has Minter
        mutates:  self.total_supply, self.balances[to]
    {
        self.total_supply += amount;
        self.balances[to]  += amount;
    }

    operation freeze(account: address)
        requires: caller has Freezer
        mutates:  self.frozen
    {
        self.frozen.insert(account);
    }
}
orderbook.cudo 62 loc
contract OrderBook {
    version: 1
    contention: per<Pair>  // ETH/USDC ‖ BTC/USDC — zero contention

    struct Pair { base: address, quote: address }
    enum   Side { Bid, Ask }

    state<Pair> {
        bids: SortedMap<u256, Vec<Order>>,
        asks: SortedMap<u256, Vec<Order>>,
    }

    resource Receipt {   // can't lose it, can't clone it
        pair: Pair, order_id: u64, side: Side,
    }

    operation place_bid(pair: Pair, price: u256,
                       amount: u256) -> Receipt
        mutates: self[pair].bids
    {
        self[pair].bids.insert(price, order);
        return Receipt { pair, order_id, side: Side::Bid };
    }

    operation cancel(receipt: Receipt)
        consumes: receipt   // receipt destroyed here
    {
        destroy receipt;
    }

    view best_bid(pair: Pair) -> u256 {
        self[pair].bids.last_key()
    }
}
aa_wallet.cudo 48 loc
contract AAWallet {
    version: 1
    contention: owned  // single owner, sequential by nature

    capability Owner;
    capability Guardian;

    struct SessionKey {
        key: address, expires: u64,
        spending_limit: u256, spent: u256,
    }

    state {
        owner:       address,
        guardians:   Set<address>,
        session_keys: Map<address, SessionKey>,
    }

    operation send(to: address, amount: u256)
        requires: caller has Owner
        mutates:  self.balance, self.nonce
    {
        self.balance -= amount;
        self.nonce   += 1;
    }

    operation add_session_key(key: address,
        limit: u256, duration: u64)
        requires: caller has Owner
        mutates:  self.session_keys
    {
        self.session_keys.insert(key, SessionKey {
            key, expires: block_timestamp + duration,
            spending_limit: limit, spent: 0,
        });
    }
}
─── ◆ ───
07 Bug classes killed at compile time

Not mitigated. Not warned about. Killed. These are hard compilation failures.

killed

Reentrancy

No callback mechanism in the grammar. Operations can't re-enter. The DAO hack is a syntax error.

no syntax for callbacks
killed

Double-Spend

Linear resources used exactly once. Using a coin twice is the same class of error as adding a string to an int.

linear type tracking
killed

Integer Overflow

All arithmetic checked. Overflow aborts. Want wrapping? Opt in with +% -% *%.

checked by default
killed

Silent Side Effects

The mutates: clause is the law. Touch undeclared state and your program doesn't compile.

enforced mutation sets
08 vs.
cudo
solidity
move
parallelism
declared partitions
none (global lock)
binary owned/shared
double-spend
compile error
runtime check
runtime (linear)
reentrancy
impossible in grammar
convention
syntax-limited
verification
built-in, no SMT
external tools
external tools
mutation tracking
enforced clause
none
implicit
overflow
checked default
0.8+ checked
aborts
09 Get it
terminal
$ git clone https://github.com/user/cudo && cd cudo
$ cargo build --release
$ cudo check examples/token.cudo --schedule

Rust toolchain required. cudo check, cudo compile, cudo run, cudo inspect — that's the whole CLI. Read the spec, browse examples, or just start writing.