glossary·2026-08-03·2 min read

Interface

Interface

An interface declares what a program must provide. A program implements one by naming it after a colon in the program declaration.

leo
interface Counter {
    fn increment(amount: u64) -> u64;
}

program my_counter.aleo : Counter {
    @noupgrade
    constructor() {}

    fn increment(amount: u64) -> u64 {
        return amount + 1u64;
    }
}

Interface declarations live outside the program { } block, alongside structs and helper functions. They can declare function signatures, record definitions, mappings, and storage variables, and they support inheritance:

leo
interface Base {
    fn get_value() -> u64;
}

interface Extended : Base {
    fn set_value(v: u64) -> u64;
}

Interfaces arrived in Leo 4.0 and matter because of what they enable: dynamic dispatch, where a caller receives a program reference at runtime and calls through the interface rather than against a program ID fixed at compile time. A payment router can accept any program implementing a token interface without knowing which one it will be handed. Consensus V18 added translation-key support so credits.aleo can participate in that path too, rather than being excluded for being protocol infrastructure.

The boundaries are deliberate. Runtime selection does not erase compile-time program boundaries: the caller and callee still need compatible input and output types, and Leo 4.4 rejects cross-program final calls that would write another program's state, following transitive calls so the restriction cannot be hidden behind a helper. An interface gets you a callable surface, not shared mutable state.

Sources