Steel
Steel is a modular framework for building smart contracts on Solana. It provides of a set of helper functions, macros, and code patterns for scaffolding smart contracts. Steel is generally designed to be unopinionated, minimizing boilerplate and maximizing flexibility.
Notes
- This codebase is under active development. All interfaces are subject to change.
- There is currently no CLI, init script, or custom localnet toolchain.
- Use
solana build-sbfto build your programs. - The API macros currently do not support IDL generation.
The account "loaders" currently do not yet return readable or mutable account references.
Getting started
To start building with Steel, simply add it to your workspace dependencies.
cargo add steel
We plan to offer a CLI soon to initialize and manage new projects. For now, you're on your own. We recommend forking one of the example programs to get started with the recommended folder structure. To build, use the standard Solana toolchain:
cargo build-sbf
Folder structure
While not strictly enforced, we recommend organizing your Solana program with the following file structure. We have found this pattern improves code readability, separating the contract interface from its implementation, and scales well as contract complexity increases.
Cargo.toml (workspace)
⌙ api
⌙ Cargo.toml
⌙ src
⌙ consts.rs
⌙ error.rs
⌙ event.rs
⌙ instruction.rs
⌙ lib.rs
⌙ loaders.rs
⌙ sdk.rs
⌙ state
⌙ mod.rs
⌙ account_1.rs
⌙ account_2.rs
⌙ program
⌙ Cargo.toml
⌙ src
⌙ lib.rs
⌙ instruction_1.rs
⌙ instruction_2.rs
API
Steel offers a collection of simple macros for defining your contract API and the basic building blocks of your program.
Accounts
For accounts, Steel uses a single enum to manage discriminators and a struct for each account type. The account! macro helps link these types and implements basic serialization logic.
use *;
/// Enum for account discriminators.
/// Struct for account state.
account!;
Instructions
For instructions, Steel similarly uses a single enum to manage discriminators and a struct for each instruction args type. The instruction! macro helps link these types and implement basic serialization logic.
use *;
/// Enum for instruction discriminators.
/// Struct for instruction args.
/// Struct for instruction args.
instruction!;
instruction!;
Errors
Custom program errors can be created simply by defining an enum for your error messages and passing it to the error! macro.
use *;
/// Enum for error types.
error!;
Events
Similarly, custom program events can be created by defining the event struct and passing it to the event! macro.
use *;
/// Struct for logged events.
event!;
Program
In your contract implementation, Steel offers a series of composable functions to parse accounts, validate state, and execute CPIs.
Entrypoint
Steel provides a utility function to streamline the program entrypoint. Securely parse incoming instruction data and dispatch it to handlers.
use MyInstruction;
use *;
use *;
entrypoint!;
Validation
Steel provides a library of composable account validation checks. You can chain these checks together to validate arbitrary account state and parse it into the type you need.
use Counter;
use *;
CPIs
Steel offers handful of helper functions for executing common CPIs such as initializing PDAs, creating token accounts, minting tokens, burning tokens, and more.
use *;