Caller and signer (std::ctx)
Leo has two accessors for identifying who invoked an entry point, and picking the wrong one is a security bug rather than a style preference.
std::ctx::caller() returns the immediate caller. If program A calls program B, then inside B this is A's address, not the user's.
std::ctx::signer() returns the account that signed the transaction. It is always a user address, never a program, however many programs the call passes through.
const ADMIN: address = aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px;
program vault.aleo {
@noupgrade
constructor() {}
fn admin_only() {
// Correct for user authorization
assert_eq(std::ctx::signer(), ADMIN);
}
}
Use signer() to answer "is this the right person". Use caller() to answer "was I called by the program I expect". The compiler warns about the distinction directly: std::ctx::caller() may return a program address, which cannot spend records.
Both are available in the off-chain proof half of an entry point, not inside a final { } block. Capture the value in the proof half and let the final block close over the variable.
These replaced self.caller and self.signer, which Leo 4.x removed. Code using the old form fails to compile with EPAR0370056. The same module provides std::ctx::addr() for the current program's address, std::ctx::block_height() and std::ctx::block_timestamp() inside final blocks, and std::ctx::network_id().