Errors
Errors are typed and declared, and each compiles to a Solidity custom error. External functions list every error they can raise, and the compiler checks the list.
errors.lithe
(* Errors are typed and declared. Each compiles to a Solidity custom error. *)
(* No payload: `Unauthorized()` *)
import "std/evm";
error Unauthorized;
(* One positional value: `TooSmall(uint256)`, in the ABI as `TooSmall(uint256)` *)
error TooSmall of uint;
(* Named fields: `InsufficientBalance(uint256 available, uint256 required)` *)
error InsufficientBalance of record {
available : uint;
required : uint;
}
(* A named set of errors, for reuse in `raises`. *)
errors withdrawErrors is
| TooSmall
| InsufficientBalance
storage is record {
owner : address;
balances : map(address, uint);
}
(* An internal function's errors are inferred when `raises` is left off. *)
view function requireOwner() is {
assert(Evm.sender() = storage.owner, Unauthorized);
}
(* An external function must declare every error it can raise. *)
external function withdraw(const amount : uint)
raises withdrawErrors
is {
assert(amount >= 100, TooSmall(amount));
const have : uint := storage.balances[Evm.sender()];
if have < amount then {
fail InsufficientBalance { available = have; required = amount; };
}
storage.balances[Evm.sender()] := have - amount;
}
external function reset(const who : address)
raises Unauthorized
is {
requireOwner();
storage.balances[who] := 0;
}Leave TooSmall out of withdrawErrors and compilation fails:
external function `withdraw` may raise `TooSmall`lithe errors errors.lithe prints every error's selector and which entrypoints raise it.

