smart-contracts について
RustでStellarスマートコントラクトを開発、テスト、レビューするためのスキルガイドです。基本手順に加え、開発・テスト・セキュリティの詳しい資料をタスク別に案内します。
主な機能
- 01Rustコントラクトの設定と手順
- 02開発パターンの資料
- 03各層のテストガイド
- 04セキュリティレビューのチェックリスト
- 05ビルドとデプロイの手順
活用シーン
- 01StellarのRustコントラクトを開始
- 02コントラクトのテスト方法を選択
- 03メインネット前の安全性レビュー
- 04認証やストレージのエラー調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ stellar/ stellar-dev-skill --skill smart-contractsインストール後、Claude Code で/smart-contractsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
development.mdsecurity.mdtesting.md詳細
Stellar スマートコントラクト
Rust で Stellar スマートコントラクトを構築するためのガイドです。Stellar のスマートコントラクトは、以前は「Soroban」というブランド名で呼ばれていました。プラットフォーム名は廃止されましたが、Rust SDK(soroban-sdk)や複数のツール名には、引き続きこの接頭辞が使われています。
このファイルでは、セットアップと基本的なワークフローを扱います。詳しい解説は関連ファイルにあります。タスクに合ったファイルをお読みください。
| タスク | ファイル |
|---|---|
| ストレージ/TTL、認証、コンストラクター、コントラクト間呼び出し、トークン、イベント、エラー、アップグレード、ファクトリー、ガバナンス/DeFi のパターン、手数料/リソース、トラブルシューティング | development.md |
| ユニットテスト、統合テスト、ファジングテスト、プロパティテスト、フォークテスト、ミューテーションテスト | testing.md |
| セキュリティレビュー、脆弱性の種類、チェックリスト、監査準備、ツール | security.md |
このスキルを使用する場面
- Rust で Stellar スマートコントラクトを作成する
- コントラクトテストを(任意のレイヤーで)セットアップする
- コントラクトのセキュリティ上の問題をレビューする
- アップグレード可能なコントラクト、ファクトリー、カスタムアカウント、DeFi プリミティブを設計する
- コントラクト固有のエラー(認証、ストレージ、アーカイブ、リソース制限)をデバッグする
関連スキル
- アセットの発行、トラストライン、SAC のデプロイ →
../assets/SKILL.md - コントラクトを呼び出すフロントエンド/ウォレット →
../dapp/SKILL.md - チェーンデータのクエリ(RPC/Horizon) →
../data/SKILL.md - ZK 検証(BLS12-381、Groth16、Circom/Noir/RISC Zero) →
../zk-proofs/SKILL.md - SEP/CAP 標準とエコシステムのリンク →
../standards/SKILL.md
バージョン
このスキルは protocol 27(soroban-sdk v27、rs-soroban-env v27、stellar-cli v27)を基準に作成されています。例に記載されているバージョン番号は参考用です。ドキュメントを鵜呑みにせず、以下の情報源から最新のバージョンを確認してください。
soroban-sdkのメジャーバージョンはプロトコルバージョンに対応します(SDK 27 ↔ protocol 27)。このルールは、特定のリリースが終了しても変わりません。- 最新の SDK リリース:crates.io/crates/soroban-sdk(または
cargo add soroban-sdkで解決されるバージョン)。プレリリース(-rc.x)はプロトコルのロールアウト期間中のみ公開され、正確なバージョン文字列で固定する必要があります。GitHub releases では、変更履歴とともに一覧を確認できます。 - ネットワークはバリデーターの投票によりアップグレードされ、テストネットがメインネットに先行します。デプロイ先のネットワークに合った SDK のメジャーバージョンを固定してください。稼働中のプロトコルバージョンは、RPC の
getVersionInfoまたは Stellar Lab で確認できます。 - ここに記載されている数値のネットワーク制限は、執筆時点のメインネット設定です。投票により変更されます。最新の値は Stellar Lab's Network Limits page と
stellar network settings --network mainnetで確認できます。
プラットフォームの制約
コントラクトは Rust から WebAssembly にコンパイルされ、サンドボックス化されたホスト上で実行されます。
#![no_std]が必須です。Rust 標準ライブラリではなく、soroban_sdkの型(String、Vec、Map、Symbol)を使用してくださいwasm32v1-noneターゲット(Rust ≥ 1.84)向けにコンパイルしてください。Stellar ランタイムがサポートする Wasm ターゲットはこれだけです- コンパイル済みコントラクトのサイズ上限は 128KB です(ネットワーク設定による)
Symbolは 32 文字(a-zA-Z0-9_)までです。symbol_short!()は最大 9 文字に対応します- ストレージはレンタル方式です。各エントリーには TTL があり、アーカイブされる場合があります。development.md を参照してください
delegatecallはなく、ホストによってコントラクト間の再入がブロックされます。security.md を参照してください- I/O やネットワーク通信はできず、参照できる時刻はレジャーのタイムスタンプのみです。コントラクトが実行できる操作はすべて
Envを介して行います
プロジェクトのセットアップ
stellar contract init my-contract # scaffolds a Cargo workspace with contracts/
cd my-contract
rustup target add wasm32v1-none # once per toolchain
Cargo.toml の基本項目(stellar contract init が生成するもの):
[lib]
crate-type = ["lib", "cdylib"] # lib is needed for tests and fuzzing
[dependencies]
soroban-sdk = "27" # protocol 27, which mainnet runs at the time of writing.
# Pre-releases (`-rc.x`) exist only during a rollout and need the
# exact version string. Check crates.io for the latest release, and
# the live protocol version of your target network, before deploying.
[dev-dependencies]
soroban-sdk = { version = "27", features = ["testutils"] } # match above
[profile.release]
opt-level = "z"
overflow-checks = true
debug = 0
strip = "symbols"
debug-assertions = false
panic = "abort"
codegen-units = 1
lto = true
コントラクトの構造
状態、コンストラクター、認証、TTL、型付きエラー、イベントを示す簡潔な例です。
#![no_std]
use soroban_sdk::{
contract, contracterror, contractevent, contractimpl, contracttype, Address, Env,
};
#[contracttype]
#[derive(Clone)]
pub enum DataKey {
Admin,
Counter,
}
#[contracterror]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(u32)]
pub enum Error {
NotInitialized = 1,
}
// Emitted as topics ("incremented", by) with data {count} — #[topic] fields
// become topics, the rest go in the data payload.
#[contractevent]
pub struct Incremented {
#[topic]
pub by: Address,
pub count: u32,
}
#[contract]
pub struct CounterContract;
#[contractimpl]
impl CounterContract {
// Runs once, atomically, at deploy time. Must be named `__constructor`.
// Does not run again on upgrade.
pub fn __constructor(env: Env, admin: Address) {
env.storage().instance().set(&DataKey::Admin, &admin);
env.storage().instance().set(&DataKey::Counter, &0u32);
}
pub fn increment(env: Env) -> Result<u32, Error> {
let admin: Address = env
.storage()
.instance()
.get(&DataKey::Admin)
.ok_or(Error::NotInitialized)?;
admin.require_auth();
let count: u32 = env.storage().instance().get(&DataKey::Counter).unwrap_or(0);
let count = count + 1;
env.storage().instance().set(&DataKey::Counter, &count);
// Extend TTL so contract state is not archived (threshold, extend-to)
env.storage().instance().extend_ttl(120 * 17280, 180 * 17280);
Incremented { by: admin, count }.publish(&env);
Ok(count)
}
pub fn get_count(env: Env) -> u32 {
env.storage().instance().get(&DataKey::Counter).unwrap_or(0)
}
}
ストレージの 3 種類、認証の各種形式、コントラクト間呼び出し、トークン、カスタム型を含む詳細なパターンは、development.md を参照してください。
ビルド、デプロイ、呼び出し
# Build optimized WASM → target/wasm32v1-none/release/*.wasm
# (optimization is on by default; --optimize=false to disable)
stellar contract build
# Create and fund an identity (testnet)
stellar keys generate alice --network testnet --fund
# Deploy (constructor args go after the `--`)
stellar contract deploy \
--wasm target/wasm32v1-none/release/my_contract.wasm \
--source-account alice \
--network testnet \
-- \
--admin alice
# Invoke
stellar contract invoke \
--id CONTRACT_ID \
--source-account alice \
--network testnet \
-- \
increment
インスタンス化せずに WASM をアップロードする場合(ファクトリーやアップグレードなど)は、stellar contract upload を使用します(古い stellar contract install は非推奨のエイリアスです)。
ビルドを検証する
デプロイされた WASM とそのソースをオンチェーンで結び付けるものはありません。SEP-0055(ドラフト)は、この隔たりを埋めます。GitHub Actions でビルドし、ソースリポジトリを WASM の contractmetav0 セクションに記録して、バイナリに対するGitHub ビルドアテステーションを公開します。これにより、誰でもオンチェーンの WASM ハッシュから、その生成元のコミットとワークフロー実行までたどれます。検証者は認証なしで api.github.com/repos/<owner>/<repo>/attestations/sha256:<wasm-hash> からアテステーションを取得するため、「誰でも」確認できるようにするには、ソースリポジトリが公開されている必要があります。Free、Pro、Team プランでは、プライベートまたは内部リポジトリからアテステーションを公開できません。Enterprise Cloud では公開できますが、リポジトリへのアクセス権があるアカウントしか読み取れないため、コントラクトの利用者は確認できません。すべてのメインネットデプロイの前に、これを標準の手順として組み込んでください。必要なのはワークフローファイルひとつなので、ユーザー向けのコントラクトだけに限る理由はありません。
2 つのメタデータエントリーで設定します(stellar contract build --meta key=value で追加し、stellar contract info meta --wasm <file> で確認できます)。
source_repo=github:<owner>/<repo>— ソースの保存場所home_domain=<domain>— SEP-1 のstellar.tomlを配信するドメイン。組織/トークンの検索に使用します(任意。スキームやパスを含まないドメインのみ)
soroban-build-workflow が、メタデータ付きのビルド、最適化、アテステーション、WASM を添付したリリースの公開、stellar.expert のコントラクト検証へのビルド登録までを一括で行います。
このファイルを含め、ドキュメントに記載されたピンをそのまま使うのではなく、自分でバージョンを特定してください。ピンは古くなることがあり、そのリポジトリの最新タグが公開済みリリースとは限りません。
REPO=stellar-expert/soroban-build-workflow
TAG=$(gh release view --repo "$REPO" --json tagName --jq .tagName) # latest release
SHA=$(gh api "repos/$REPO/commits/$TAG" --jq .sha) # its commit
gh api "repos/$REPO/contents/.github/workflows/release.yml?ref=$SHA" \
-H "Accept: application/vnd.github.raw" # the file you will pin
タグではなく、その SHA の release.yml を確認してください。2 つの手順の間にタグが移動する可能性があり、その場合は一方のコミットを確認して、別のコミットをピン留めすることになります。タグ付きコミットをチェックアウトし、ソースからビルドして、アップロードするものと同じファイルにアテステーションを付与することを確認してください。そうでなければ、ピン留めせずに作業を中止してユーザーに伝えてください。このワークフローはリポジトリのトークン、OIDC、アテステーションの権限を使って実行されるため、完全な SHA をピン留めしてください。
そのピン留めで固定できる範囲をユーザーに伝えてください。固定されるのは release.yml であり、そこから呼び出すアクションではありません。それらは独自の可変タグ(actions/checkout@v4、CLI、アテストアクション)を参照し、同じ権限のもとで実行時に解決されます。呼び出し側からそれらをピン留めすることはできません。この残存リスクを許容できない場合は、ワークフローをフォークしてください。
# .github/workflows/release.yml — verified build on every version tag
name: Build and Release
on:
push:
tags: ["v*"]
permissions: # inherited by the called workflow, which cannot elevate them
contents: write # create the release, attach the WASM
id-token: write # sign the attestation
attestations: write # publish it
jobs:
release:
# the SHA you resolved and reviewed; keep the version in the comment
uses: stellar-expert/soroban-build-workflow/.github/workflows/release.yml@<commit-sha> # vX.Y.Z
with:
release_name: ${{ github.ref_name }}
home_domain: example.com # optional
package: my-contract # optional — omit to build the working directory
secrets:
release_token: ${{ secrets.GITHUB_TOKEN }} # created by GitHub, nothing to configure
その後、ローカルで再ビルドしたものではなく、そのリリースに添付された WASMをデプロイしてください。コンパイル環境は異なる場合があり、1 バイトでも異なるハッシュにはアテステーションが一致しません。
結果はStellar Lab のコントラクトエクスプローラーと stellar.expert に表示されます。何が証明されるのかを、ユーザーに正確に説明してください。特定のワークフロー実行が、このバイナリをこのコミットからビルドしたことが証明されます。そのコードが安全か、またはレビューされたことがあるかは示しません。
最小限のテスト
// src/test.rs — included from lib.rs with `mod test;`
#![cfg(test)]
use super::*;
use soroban_sdk::{testutils::Address as _, Address, Env};
#[test]
fn test_increment() {
let env = Env::default();
env.mock_all_auths();
let admin = Address::generate(&env);
let contract_id = env.register(CounterContract, (admin.clone(),));
let client = CounterContractClient::new(&env, &contract_id);
assert_eq!(client.increment(), 1);
assert_eq!(client.get_count(), 1);
}
認証のモック、イベントのアサーション、ファジング、フォークテスト、CI のセットアップについては、testing.md を参照してください。
メインネットの前に
security.md のチェックリストに沿って確認してください。認可、再初期化、算術演算、ストレージ TTL、コントラクト間の検証は、繰り返し発生する不具合の原因です。検証済みビルドを通じてデプロイし、オンチェーンの WASM ハッシュからレビュー可能なコミットまでたどれるようにしてください。