Skip to content
Pre-Release: Fe is under active development. This documentation covers the upcoming release. Follow progress on GitHub

What Are Effects?

Effects are Fe’s system for making dependencies explicit. They declare what capabilities a function needs (what external resources it can access) and the compiler enforces these declarations.

In many languages, functions can access global state, modify storage, or call external services without any indication in their signature. This leads to:

  • Hidden dependencies: You can’t tell what a function does just by looking at its signature
  • Surprising behavior: Functions may have side effects you didn’t expect
  • Testing difficulties: Mocking hidden dependencies is awkward
  • Security risks: In smart contracts, hidden state access can lead to vulnerabilities
// In languages without effects, this signature tells you nothing
// about what resources the function accesses
fn transfer(from: u256, to: u256, amount: u256) {
}

Fe’s effect system requires functions to declare their capabilities upfront using the uses clause:

fn transfer(from: u256, to: u256, amount: u256) uses (mut balances: Balances) {
// This function can only access Balances
// and can modify it (mut)
}

Now the function signature tells you exactly what it can do:

  • It needs access to Balances
  • It will modify Balances (indicated by mut)
  • It cannot access anything else

Here’s how effects work in practice:

// Define an effect type
pub struct Counter {
pub value: u256,
}
// This function requires the Counter effect
fn increment() uses (mut counter: Counter) {
counter.value = counter.value + 1
}
// This function requires read-only access
fn get_count() -> u256 uses (counter: Counter) {
counter.value
}
// Caller must provide the effect
fn main() {
let mut counter = Counter { value: 0 }
// Provide the effect with 'with'
with (Counter = counter) {
increment()
increment()
let count = get_count() // count is 2
}
}
ConceptDescription
EffectA capability that a function requires to execute
uses clauseDeclares what effects a function needs
mutIndicates the function will modify the effect
withProvides an effect to a scope

The effect system provides:

  1. Explicit dependencies: Function signatures tell you everything
  2. Compiler enforcement: Missing or incorrect effects are compile errors
  3. Scoped access: Effects are only available where explicitly provided
  4. Controlled mutation: Distinguish between reading and modifying

The following sections cover how to declare effects, use mutability, and understand how effects propagate through your code.