mcpField
S
solidity-deploy

solidity-deploy

github.com/0xlayerghostクラウド・DevOps4129 回インストール2 週間前に更新
リポジトリ

solidity-deploy について

solidity-deployは、FoundryでSolidityコントラクトをデプロイ・アップグレードする開発者向けのワークフロースキルです。事前・事後チェック、署名とブロードキャストの安全規則に加え、アップグレード可能なコントラクト向けのOpenZeppelin Foundry Upgrades Pluginの指針を提供します。

主な機能

  1. 01Foundryのデプロイ前チェックリスト
  2. 02ドライランとデプロイ後の手順
  3. 03署名とブロードキャストの安全規則
  4. 04OpenZeppelinプロキシデプロイの指針
  5. 05アップグレード検証とストレージ確認

活用シーン

  1. 01Foundryコントラクトのデプロイ準備
  2. 02ブロードキャスト前のデプロイシミュレーション
  3. 03アップグレード可能なプロキシのデプロイや更新
  4. 04デプロイ設定とオンチェーン状態の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/0xlayerghost/solidity-agent-kit --skill solidity-deploy

インストール後、Claude Code で/solidity-deployを入力して読み込まれたか確認します。

詳細

デプロイワークフロー

言語ルール

  • 常にユーザーが使用している言語で応答してください。 ユーザーが中国語で質問した場合は、中国語で応答してください。英語で質問した場合は、英語で応答してください。

デプロイ前チェックリスト(すべて合格する必要があります)

手順コマンド/アクション
コードをフォーマットするforge fmt
すべてのテストを実行するforge test — 失敗がゼロであること
ガスレポートを確認するforge test --gas-report — 重要な関数を確認する
設定を検証するconfig/*.json のパラメーターを手動で確認する
ドライランするforge script <Script> --fork-url <RPC_URL> -vvvv(--broadcast は付けない)
残高を確認するcast balance <DEPLOYER> --rpc-url <RPC_URL> — 十分なガスがありますか?
ガス上限を設定するデプロイコマンドに --gas-limit を含める必要があります

デプロイの判断ルール

状況ルール
デフォルトのデプロイ--verify を付けないでください — デフォルトでは、コントラクトはブロックエクスプローラーで検証されません
ユーザーが検証を要求した場合コマンドに --verify と --etherscan-api-key を追加します
デプロイ後の検証別の手順として forge verify-contract を使用します
マルチチェーンデプロイチェーンごとに別のスクリプトを使用し、複数のチェーンを1つのスクリプトでまとめて処理しないでください
プロキシのデプロイ先に実装をデプロイし、次にプロキシをデプロイします。両方を個別に検証してください
アップグレード可能なコントラクトOpenZeppelin Upgrades Plugin を使用してください(以下を参照)。プロキシのデプロイスクリプトを独自に作成しないでください

デプロイ後の操作(すべて必須)

  1. config/*.json と deployments/latest.env のアドレスを更新します
  2. 重要な関数をテストします。cast call を使って、オンチェーンの状態が正しいことを確認します
  3. 変更を docs/CHANGELOG.md に記録します
  4. デプロイトランザクションのハッシュへのリンクを添えて PR を提出します
  5. 検証が必要な場合は、別途 forge verify-contract を実行します

重要なセキュリティルール

  • ブロードキャストする前に、開発者に署名方法を選択してもらいます。
    • Foundry Keystore(推奨): --account <KEYSTORE_NAME> を使用します。
    • 環境ファイル: PRIVATE_KEY を Git で無視される .env に保存し、source .env を実行してから、--private-key "$PRIVATE_KEY" を使用します。
  • コマンド、スクリプト、ログ、会話、コミットするファイルに、実際の秘密鍵を記載しないでください。 開発者の .env を読み取ったり、内容を表示したりしないでください。
  • テンプレートに --broadcast を含めないでください。 デプロイの準備ができたら、ユーザーが明示的に追加する必要があります。

コマンドテンプレート

# Dry-run (simulation only, no on-chain execution)
forge script script/Deploy.s.sol:DeployScript \
  --rpc-url <RPC_URL> \
  --gas-limit 5000000 \
  -vvvv

# When the developer is ready to deploy, ask them to choose one signer:
#   Keystore (recommended): add --account <KEYSTORE_NAME> --broadcast
#   .env: source .env, then add --private-key "$PRIVATE_KEY" --broadcast

# Verify existing contract separately
forge verify-contract <ADDRESS> <CONTRACT> \
  --chain-id <CHAIN_ID> \
  --etherscan-api-key <API_KEY> \
  --constructor-args $(cast abi-encode "constructor(address)" <ARG>)

# Quick on-chain read test after deployment
cast call <CONTRACT_ADDRESS> "functionName()" --rpc-url <RPC_URL>

アップグレード可能なコントラクトのデプロイ(OpenZeppelin Upgrades Plugin)

アップグレード可能なコントラクト(UUPS、Transparent、Beacon)には、プロキシのデプロイスクリプトを独自に作成するのではなく、OpenZeppelin Foundry Upgrades Plugin を使用してください。

プラグインを使用する理由
手動の方法プラグインを使用する場合
約30行:実装をデプロイ → プロキシをデプロイ → 初期化子をエンコード → 接続を設定1行:Upgrades.deployUUPSProxy(...)
約20行:新しい実装をデプロイ → ストレージを検証 → プロキシをアップグレード1行:Upgrades.upgradeProxy(...)
ストレージレイアウトの互換性:目視で確認自動チェックされ、互換性のないレイアウトは拒否されます
_disableInitializers() を忘れた場合:警告なし自動検証されます
インストール
forge install OpenZeppelin/openzeppelin-foundry-upgrades
forge install OpenZeppelin/openzeppelin-contracts-upgradeable

remappings.txt に追加します:

@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/
@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/
デプロイスクリプトのテンプレート(UUPS)
// script/Deploy.s.sol
import {Script, console} from "forge-std/Script.sol";
import {Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";
import {MyContract} from "../src/MyContract.sol";

contract DeployScript is Script {
    function run() public {
        vm.startBroadcast();

        // One line: deploys impl + proxy + calls initialize
        address proxy = Upgrades.deployUUPSProxy(
            "MyContract.sol",
            abi.encodeCall(MyContract.initialize, (msg.sender))
        );

        console.log("Proxy:", proxy);
        console.log("Impl:", Upgrades.getImplementationAddress(proxy));

        vm.stopBroadcast();
    }
}
アップグレードスクリプトのテンプレート
// script/Upgrade.s.sol
import {Script, console} from "forge-std/Script.sol";
import {Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";

contract UpgradeScript is Script {
    function run() public {
        address proxy = vm.envAddress("PROXY_ADDRESS");
        vm.startBroadcast();

        // One line: validates storage layout + deploys new impl + upgrades proxy
        Upgrades.upgradeProxy(proxy, "MyContractV2.sol", "");

        console.log("Upgraded. New impl:", Upgrades.getImplementationAddress(proxy));

        vm.stopBroadcast();
    }
}

自動参照のため、V2 コントラクトに @custom:oz-upgrades-from MyContract アノテーションを追加します:

/// @custom:oz-upgrades-from MyContract
contract MyContractV2 is Initializable, OwnableUpgradeable, UUPSUpgradeable {
    // ...
}
コマンド
# Deploy proxy (dry-run) — --ffi is required for storage layout checks
forge script script/Deploy.s.sol --rpc-url <RPC_URL> --ffi -vvvv

# Deploy proxy (broadcast) with Foundry Keystore
forge script script/Deploy.s.sol --rpc-url <RPC_URL> --ffi --account <KEYSTORE_NAME> --broadcast

# Or deploy with PRIVATE_KEY from a gitignored .env
source .env
forge script script/Deploy.s.sol --rpc-url <RPC_URL> --ffi --private-key "$PRIVATE_KEY" --broadcast

# Upgrade proxy (dry-run)
PROXY_ADDRESS=0x... forge script script/Upgrade.s.sol --rpc-url <RPC_URL> --ffi -vvvv

# Upgrade proxy (broadcast) with Foundry Keystore
PROXY_ADDRESS=0x... forge script script/Upgrade.s.sol --rpc-url <RPC_URL> --ffi --account <KEYSTORE_NAME> --broadcast

# Or upgrade with PRIVATE_KEY from a gitignored .env
source .env
PROXY_ADDRESS=0x... forge script script/Upgrade.s.sol --rpc-url <RPC_URL> --ffi --private-key "$PRIVATE_KEY" --broadcast

# Validate upgrade without deploying (useful for CI)
# Use Upgrades.validateUpgrade("MyContractV2.sol", opts) in a test
プラグイン API クイックリファレンス
関数用途
Upgrades.deployUUPSProxy(contract, data)UUPS プロキシ + 実装 + 初期化をデプロイします
Upgrades.deployTransparentProxy(contract, admin, data)Transparent プロキシ + 実装 + 初期化をデプロイします
Upgrades.upgradeProxy(proxy, newContract, data)検証 + 新しい実装のデプロイ + アップグレードを行います
Upgrades.validateUpgrade(contract, opts)デプロイせずに検証のみを行います(CI/テスト用)
Upgrades.getImplementationAddress(proxy)現在の実装アドレスを取得します
Upgrades.prepareUpgrade(contract, opts)検証 + 新しい実装をデプロイし、アドレスを返します(マルチシグ用)
重要なルール
  • 常に --ffi フラグを使用してください — プラグインはストレージレイアウトの検証にこのフラグを必要とします
  • アップグレードでは常に --sender <ADDRESS> を追加してください — プロキシの所有者と一致する必要があります。一致しない場合は OwnableUnauthorizedAccount が発生します
  • スクリプトでは Upgrades を使用し、テストでのみ UnsafeUpgrades を使用してください — UnsafeUpgrades はすべての安全性チェックを省略します
  • アップグレード時も V1 のソースコードをプロジェクト内に残してください — プラグインがストレージを比較するために必要です。または @custom:oz-upgrades-from アノテーションを使用してください
  • このプラグインが利用できる場合、プロキシのデプロイを独自に実装しないでください — ストレージレイアウトのチェックだけでも重大なバグを防げます

コメント