Interface
An interface declares what a program must provide. A program implements one by naming it after a colon in the program declaration.
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:
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.