Back to Learn
errors

Error Handling

Define custom errors and handle failures gracefully in your contracts.

Error Handling

Proper error handling is crucial for secure smart contracts. Stylus uses Rust's Result type with custom Solidity-compatible errors.

Defining Errors

Use the sol! macro:

``rust

sol! {

error InsufficientBalance(uint256 available, uint256 required);

error Unauthorized();

}

`

Creating Error Enum

Wrap errors in an enum with SolidityError derive:

`rust

#[derive(SolidityError)]

pub enum MyError {

InsufficientBalance(InsufficientBalance),

Unauthorized(Unauthorized),

}

`

Using Result

Return Result from functions:

`rust

pub fn withdraw(&mut self, amount: U256) -> Result<(), MyError> {

if balance < amount {

return Err(MyError::InsufficientBalance(...));

}

Ok(())

}

``

Code Example

#![cfg_attr(not(feature = "export-abi"), no_main)]
extern crate alloc;

use stylus_sdk::prelude::*;
use stylus_sdk::msg;
use stylus_sdk::storage::{StorageU256, StorageAddress};
use alloy_primitives::{Address, U256};
use alloy_sol_types::sol;

// Define errors
sol! {
    error InsufficientBalance(uint256 available, uint256 required);
    error Unauthorized();
    error ZeroAmount();
}

// Wrap in enum
#[derive(SolidityError)]
pub enum VaultError {
    InsufficientBalance(InsufficientBalance),
    Unauthorized(Unauthorized),
    ZeroAmount(ZeroAmount),
}

#[storage]
#[entrypoint]
pub struct Vault {
    balance: StorageU256,
    owner: StorageAddress,
}

#[public]
impl Vault {
    pub fn withdraw(&mut self, amount: U256) -> Result<(), VaultError> {
        // Check zero amount
        if amount == U256::ZERO {
            return Err(VaultError::ZeroAmount(ZeroAmount {}));
        }

        // Check authorization
        if msg::sender() != self.owner.get() {
            return Err(VaultError::Unauthorized(Unauthorized {}));
        }

        // Check balance
        let current = self.balance.get();
        if current < amount {
            return Err(VaultError::InsufficientBalance(InsufficientBalance {
                available: current,
                required: amount,
            }));
        }

        self.balance.set(current - amount);
        Ok(())
    }
}

Practice Challenge

Key Points

  • Define errors with sol! macro
  • Wrap in enum with #[derive(SolidityError)]
  • Return Result<T, YourError> from functions
  • Errors are Solidity-compatible for better tooling
  • Include relevant data in error parameters