Skip to content
Fe 26.0 is not production-ready. This is an initial release of a new compiler. Learn more

Standard Library Effects

Fe’s standard library provides effect traits for common EVM operations. These are available via the prelude — no imports needed.

The Ctx trait provides read-only access to the EVM execution environment:

fn get_caller() -> Address uses (ctx: Ctx) {
ctx.caller()
}
fn get_block() -> u256 uses (ctx: Ctx) {
ctx.block_number()
}

Available methods on Ctx:

MethodReturnsDescription
caller()AddressMessage sender
address()AddressContract’s own address
value()u256Ether sent with the call
timestamp()u256Current block timestamp
block_number()u256Current block number

The Log trait allows emitting EVM log events. It requires mut because emitting is a side effect:

#[event]
struct Transfer {
#[indexed]
from: Address,
#[indexed]
to: Address,
value: u256,
}
fn emit_transfer(from: Address, to: Address, value: u256) uses (log: mut Log) {
log.emit(Transfer { from, to, value })
}

The emit() method works with any struct marked #[event].

Under the hood, Ctx and Log are traits. The struct that implements them all is Evm. When you write uses (ctx: Ctx), the contract’s Evm instance satisfies that requirement.

Evm implements: Ctx, Log, RawMem, RawStorage, RawOps, Create, Call.

In tests, you interact with Evm directly:

#[test]
fn test_with_evm() uses (evm: mut Evm) {
let addr = evm.create2<Example>(value: 0, args: (), salt: 0)
assert(addr.inner != 0)
}

Any type — struct, trait, or enum — can serve as an effect. The standard library effects are not special; they follow the same rules as user-defined effects. See Storage as Effects for the most common pattern: using your own structs as effects in contracts.

Here is a non-storage example — injecting validation logic as an effect:

pub struct RangeValidator {
pub min: u256,
pub max: u256,
}
impl RangeValidator {
pub fn is_valid(self, value: u256) -> bool {
value >= self.min && value <= self.max
}
}
fn validate(value: u256) -> bool uses (v: RangeValidator) {
v.is_valid(value)
}
#[test]
fn test_custom_effect() {
let validator = RangeValidator { min: 10, max: 100 }
let result = with (validator) {
validate(value: 50)
}
assert(result == true)
let result2 = with (validator) {
validate(value: 5)
}
assert(result2 == false)
}
EffectTypePurpose
CtxTrait (std)Execution environment (caller, block info)
LogTrait (std)Event emission
EvmStruct (std)Root effect implementing all EVM traits
CustomAny typeWhatever capability your code needs