Use when writing Rust code that interacts with Ethereum/EVM blockchains using alloy-ext. Covers contract definitions, NetworkProvider, transaction sending, nonce management, event accumulation, error recovery, and the recommended pattern of wrapping contracts with a typed SDK layer.
alloy-ext is a Rust crate that extends the alloy ecosystem with production-grade transaction management: stateful nonce lifecycle, automatic error recovery, transaction rebroadcasting, cancel fallback, and a distributed contract error parsing registry.
Full alloy compatibility: alloy-ext re-exports the entire alloy crate via pub use alloy::*. This means alloy-ext is a superset of alloy — every type, trait, module, and function from alloy is available through alloy-ext unchanged. You do NOT need to add alloy as a separate dependency. Anything you can do with alloy you can do identically with alloy-ext:
alloy::primitives::{Address, U256, B256, Bytes, ...}alloy::providers::{Provider, ProviderBuilder, ...}alloy::signers::local::PrivateKeySigneralloy::sol!, alloy::sol_types::*alloy::rpc::types::{TransactionRequest, ...}alloy::network::{Ethereum, EthereumWallet, ...}alloy::consensus::*, alloy::contract::*, etc.The only addition is alloy::ext::* which contains the extended features (NetworkProvider, TrackedPendingTx, PendingTxAccum, etc.) and the alloy::contract! / alloy::register_contract_errors! macros.
Crate import: In Cargo.toml, use the package alias so you can write alloy:: everywhere:
[dependencies]
alloy = { version = "1.7.4", package = "alloy-ext" }
Always use the latest published version. The
package = "alloy-ext"alias meansuse alloy::*in code gives you both standard alloy and theext::*extensions. There is no need to depend onalloyseparately —alloy-extalready includes everything.
contract! MacroThe contract! macro needs the Forge/Foundry output JSON for each contract. Here's how to locate them:
foundry.toml or a contracts/ / src/ directory containing .sol files.out/ by default (configurable via out in foundry.toml). Run forge build if out/ doesn't exist.out/<FileName>.sol/<ContractName>.json. For example, contracts/OrderBook.sol containing contract OrderBook → out/OrderBook.sol/OrderBook.json.contract!: Use a relative path from your Rust crate root to the JSON file.Common directory layouts:
# Vendored contracts (recommended for SDK crates)
my-sdk/
├── vendor/my-protocol/out/
│ ├── OrderBook.sol/OrderBook.json ← use "vendor/my-protocol/out/OrderBook.sol/OrderBook.json"
│ ├── MarginAccount.sol/MarginAccount.json
│ └── ERC20.sol/ERC20.json
├── src/
│ └── stubs.rs
# Or: contract artifacts copied to a flat directory
my-sdk/
├── contract_artifacts/
│ ├── OrderBook.sol/OrderBook.json ← use "./contract_artifacts/OrderBook.sol/OrderBook.json"
│ └── ERC20.sol/ERC20.json
├── src/
│ └── stubs.rs
Tip: When the user mentions a Forge project, search for
foundry.tomlto find the root andout/for compiled artifacts. Each.jsonfile underout/containsabi,bytecode,methodIdentifiers, etc.
contract! macroThe contract! macro wraps alloy::sol! and auto-registers error parsers for each contract.
// src/stubs.rs — define all your contract stubs in one place