Fragments of verbose memory

冗長な記憶の断片 - Web技術のメモをほぼ毎日更新

Mar 20, 2026 - 日記

Alloy: Rust製EthereumライブラリでのWeb3開発入門

Alloy: Rust製EthereumライブラリでのWeb3開発入門

Rust でEthereumアプリケーションを開発するなら、Alloy を知っておく必要があります。

Alloyは、長く使われてきた ethers-rs の後継ライブラリです。モダンなRustのイディオムを取り入れ、パフォーマンスと型安全性を大幅に向上させました。2024年6月にv0.1が初回リリースされ、2025年5月にv1.0安定版に到達しました。2026年現在では新規Ethereum プロジェクトの標準的な選択肢となっています。

ethers-rsからAlloyへの移行背景

ethers-rs はRustにおけるEthereum開発の先駆けでした。しかし、コードベースが肥大化し、メンテナンスが困難になっていました。

主な問題は以下の通りです。

  • モノリシックな設計で必要ない機能も依存関係に含まれる
  • 非同期処理まわりのAPIが一貫していない
  • コンパイル時の型チェックが不十分な箇所がある
  • ドキュメントが分散していて学習コストが高い

Alloyはこれらの課題を解決するために、ゼロから設計されました。ethers-rsの主要な開発者たちが中心となって開発を進めており、APIの互換性よりも正しい設計を優先しています。

Alloyのコアコンポーネント

Alloyは複数のクレートに分割されたモジュラー設計です。必要なコンポーネントだけを依存関係に追加できます。

Provider

Provider はEthereumノードとの通信を担います。HTTPやWebSocket、IPC経由でノードに接続できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
use alloy::providers::{Provider, ProviderBuilder};
use alloy::primitives::address;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Infuraや自前ノードのURLを指定してProviderを作成する
    let provider = ProviderBuilder::new()
        .on_http("https://mainnet.infura.io/v3/YOUR_KEY".parse()?);

    // 最新ブロック番号を取得する
    let block_number = provider.get_block_number().await?;
    println!("最新ブロック: {}", block_number);

    Ok(())
}

ProviderBuilder のビルダーパターンにより、ミドルウェア(ガス見積もり、nonce管理など)を層として追加できます。ethers-rsのミドルウェア設計より直感的です。

Signer

トランザクションへの署名を担うのが Signer です。ローカル秘密鍵、ハードウェアウォレット、AWS KMSなど複数のバックエンドをサポートします。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
use alloy::signers::local::PrivateKeySigner;
use alloy::network::EthereumWallet;

// 秘密鍵からSignerを作成する(本番環境では環境変数から読み込むこと)
let signer: PrivateKeySigner = "0xYOUR_PRIVATE_KEY".parse()?;
let wallet = EthereumWallet::from(signer);

// ウォレットをProviderに組み込む
let provider = ProviderBuilder::new()
    .with_recommended_fillers()
    .wallet(wallet)
    .on_http(rpc_url);

with_recommended_fillers() を追加すると、nonceやガス代の自動設定が有効になります。手動で設定する手間が省けます。

ETHの送金

署名付きProviderができれば、ETHの送金は数行で書けます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
use alloy::primitives::{address, U256};
use alloy::rpc::types::TransactionRequest;

let to = address!("d8dA6BF26964aF9D7eEd9e03E53415D37aA96045");
let value = U256::from(1_000_000_000_000_000_u64); // 0.001 ETH (wei単位)

let tx = TransactionRequest::default()
    .with_to(to)
    .with_value(value);

// トランザクションを送信してレシートを待つ
let receipt = provider.send_transaction(tx).await?.get_receipt().await?;
println!("Tx hash: {:?}", receipt.transaction_hash);

get_receipt() はトランザクションのマイニング完了まで待機します。タイムアウトの設定も可能です。

Contractの操作

スマートコントラクトとのやり取りには sol! マクロを使います。ABIから型安全なRustコードを生成できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
use alloy::sol;

// ABIをインラインで定義する(JSONファイルからの読み込みも可能)
sol! {
    #[allow(missing_docs)]
    #[sol(rpc)]
    ERC20Token,
    "abi/ERC20.json"
}

// コントラクトインスタンスを作成する
let token_address = address!("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48");
let token = ERC20Token::new(token_address, &provider);

// balanceOfを呼び出す(読み取りのみ、ガス不要)
let balance = token.balanceOf(my_address).call().await?._0;
println!("残高: {} USDC", balance);

コンパイル時にABIの型チェックが走るため、存在しない関数を呼び出すとビルドエラーになります。ランタイムエラーを大幅に削減できます。

Alloyの主要な利点

型安全性の向上

Alloyでは AddressU256Bytes32 などのプリミティブ型が充実しています。文字列をそのまま渡す箇所が減り、型ミスマッチをコンパイル時に検出できます。

モジュラー設計

alloy-corealloy-providersalloy-signers などのクレートが独立しています。ライブラリ開発者はコアのみを使い、アプリケーション開発者は必要なものだけを追加する、という使い分けができます。

パフォーマンス

内部的にはゼロコピーのデシリアライズを採用しています。大量のトランザクションを処理するインデクサーやボットの開発では、ethers-rsより明確な速度改善が見られます。

ethers-rsからの移行ポイント

移行で最もつまずきやすい箇所を整理します。

Provider作成の変更: Provider::try_from(url) から ProviderBuilder::new().on_http(url) に変わりました。

ミドルウェアチェーンの廃止: ethers-rsの SignerMiddleware などは存在しません。代わりに ProviderBuilder のフィラー(fillers)とウォレットを使います。

型名の変更: H256B256H160AddressU256 はそのままです。alloy::primitives に統一されています。

Contract呼び出しの変更: call() の戻り値がタプル構造体になりました。フィールドには ._0._1 でアクセスします。

移行作業の目安は、中規模プロジェクト(2,000〜3,000行)で数日程度です。コンパイルエラーを一つずつ潰していくアプローチが確実です。

Alloy vs ethers-rs vs web3.rs の使い分け

ライブラリ推奨ケース
Alloy新規プロジェクト全般。型安全性とパフォーマンスを重視する場合
ethers-rs既存コードベースの保守。移行コストが見合わない場合
web3.rsメンテナンスが止まっており、新規採用は非推奨

結論として、新しくRustでEthereum開発を始めるなら Alloy 一択です。ethers-rsは現在もメンテナンスモードで動きますが、新機能の追加は期待できません。

ここで切り分けたいのは、Alloy はあくまでライブラリの話だという点です。スマートコントラクト開発では、ライブラリ選定と CI/CD の再現性確保は別の問題です。もし「Docker で build/test 手順を固定したい」「監査や fuzz を含む step を構成として残したい」という関心が強いなら、Circle Contract-CLIでスマートコントラクトCI/CDを固定する も合わせて読むと、レイヤーの違いが整理しやすいと思います。

まとめ

Alloyは「型安全」「モジュラー」「高パフォーマンス」という三拍子が揃ったライブラリです。

  • ProviderBuilder でノード接続を組み立てる
  • sol! マクロでABIから型安全なコードを生成する
  • with_recommended_fillers() + wallet() でトランザクション送信を簡潔に書く

ethers-rsのユーザーなら移行コストはかかりますが、長期的なメンテナンス性を考えると早めに乗り換えておくことを強くお勧めします。

参考