Skip to content
LogoLogo

Constants

Lithe has no constant declaration. A pure function with no parameters is a named constant, and the compiler folds it to a literal. That covers every use of Solidity's constant: numbers, hashes, and the length of a fixed list.

constants.lithe
(* A constant is a pure function of no arguments. It compiles to the literal. *)
 
import "std/address";
import "std/crypto";
import "std/int";
import "std/uint";
 
storage is record {
  feeBps : uint;
  admins : list(address, maxAdmins());
}
 
pure function maxFeeBps() : uint is
  1_000
 
pure function denominator() : uint is
  10_000
 
(* The hash of a literal is a constant too. *)
pure function pauserRole() : bytes32 is
  Crypto.keccak256("PAUSER_ROLE")
 
(* A named constant can be a fixed list's length. *)
pure function maxAdmins() : uint is
  3
 
error FeeTooHigh of uint;
 
external function setFee(const feeBps : uint)
  raises FeeTooHigh
is {
  assert(feeBps <= maxFeeBps(), FeeTooHigh(feeBps));
  storage.feeBps := feeBps;
}
 
external view function feeOn(const amount : uint) : uint is
  amount * storage.feeBps / denominator()
 
(* Built-in constants take their width from context. *)
external pure function limits() : (uint, uint16, int, address) is
  (Uint.max, Uint.max, Int.max, Address.zero)
  • 1_000 uses _ as a digit separator.
  • Uint.max is type(uint256).max, or the maximum of whatever width the context expects. Here limits returns it both as a uint and as a uint16.
  • Crypto.keccak256("PAUSER_ROLE") compiles to the 32-byte hash, so a role id or an EIP-712 typehash is written as its preimage, not pasted in.
  • A fixed list's length can be a named constant, M.n() from a module, or arithmetic over those: list(address, maxAdmins()), list(uint, maxAdmins() * 2).
  • Arithmetic on constants is checked when the contract compiles: maxFeeBps() * Uint.max is a compile error, not a panic at run time.