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

Standard Traits

Fe provides several built-in traits that enable core language functionality. Understanding these helps you work effectively with Fe’s type system.

The MsgVariant trait is automatically implemented for message variants. It provides the selector and return type information needed for ABI compatibility.

trait MsgVariant {
const SELECTOR: u32
type Return
}

When you define a message:

msg TokenMsg {
#[selector = 0xa9059cbb]
Transfer { to: u256, amount: u256 } -> bool,
}

The compiler generates an implementation like:

// Conceptually generated by the compiler
impl MsgVariant for TokenMsg_Transfer {
const SELECTOR: u32 = 0xa9059cbb
type Return = bool
}

This trait enables:

  • Type-safe message routing
  • Compile-time selector verification
  • Generic code over message types

Fe provides traits for numeric operations:

trait Add {
fn add(self, other: Self) -> Self
}
trait Sub {
fn sub(self, other: Self) -> Self
}
trait Mul {
fn mul(self, other: Self) -> Self
}
trait Div {
fn div(self, other: Self) -> Self
}

Primitive numeric types implement these automatically.

trait Eq {
fn eq(self, other: Self) -> bool
}
trait Ord {
fn lt(self, other: Self) -> bool
fn le(self, other: Self) -> bool
fn gt(self, other: Self) -> bool
fn ge(self, other: Self) -> bool
}

While Fe may not have all these as built-ins yet, these patterns are commonly defined:

Provides a default value:

trait Default {
fn default() -> Self
}
struct Counter {
value: u256,
}
impl Default for Counter {
fn default() -> Self {
Counter { value: 0 }
}
}
let c = Counter::default()

Creates a copy of a value:

trait Clone {
fn clone(self) -> Self
}
struct Point {
x: u256,
y: u256,
}
impl Clone for Point {
fn clone(self) -> Self {
Point { x: self.x, y: self.y }
}
}

Converts between types:

trait Into<T> {
fn into(self) -> T
}
trait From<T> {
fn from(value: T) -> Self
}
struct Percentage {
basis_points: u256,
}
impl From<u256> for Percentage {
fn from(value: u256) -> Self {
Percentage { basis_points: value }
}
}

For your projects, define common traits that types should implement:

trait Identifiable {
fn id(self) -> u256
}
struct User {
user_id: u256,
name: String,
}
impl Identifiable for User {
fn id(self) -> u256 {
self.user_id
}
}
struct Token {
token_id: u256,
value: u256,
}
impl Identifiable for Token {
fn id(self) -> u256 {
self.token_id
}
}
// Generic function works with any Identifiable
fn get_id<T: Identifiable>(item: T) -> u256 {
item.id()
}
trait Validatable {
fn is_valid(self) -> bool
}
struct Transfer {
from: u256,
to: u256,
amount: u256,
}
impl Validatable for Transfer {
fn is_valid(self) -> bool {
self.from != 0 && self.to != 0 && self.amount > 0
}
}
fn process<T: Validatable>(item: T) -> bool {
if !item.is_valid() {
return false
}
// ... process valid item
true
}
trait Hashable {
fn hash(self) -> u256
}
struct Order {
id: u256,
price: u256,
quantity: u256,
}
impl Hashable for Order {
fn hash(self) -> u256 {
// Simple hash combining fields
self.id ^ self.price ^ self.quantity
}
}

Define trait “interfaces” for your contract patterns:

trait ERC20 {
fn total_supply(self) -> u256
fn balance_of(self, account: u256) -> u256
fn transfer(mut self, to: u256, amount: u256) -> bool
}
trait ERC721 {
fn owner_of(self, token_id: u256) -> u256
fn transfer_from(mut self, from: u256, to: u256, token_id: u256)
}
trait Ownable {
fn owner(self) -> u256
fn transfer_ownership(mut self, new_owner: u256)
}
trait Pausable {
fn paused(self) -> bool
fn pause(mut self)
fn unpause(mut self)
}

Build complex behaviors from simple traits:

trait Readable {
fn read(self) -> u256
}
trait Writable {
fn write(mut self, value: u256)
}
// Require both for read-write access
fn update<T: Readable + Writable>(mut storage: T, delta: u256) {
let current = storage.read()
storage.write(current + delta)
}
TraitPurpose
MsgVariantMessage variant metadata (selector, return type)
Add, Sub, Mul, DivArithmetic operations
Eq, OrdComparison operations
DefaultDefault value construction
CloneValue duplication
Into, FromType conversion

Standard traits provide the foundation for generic, reusable code. Define your own traits to create consistent interfaces across your codebase.