契約のアップグレード

コマンドラインからパッケージ契約をアップグレードできます。

次のステップでは、トークン化された保証金契約プロジェクトのサンプルをアップグレードする方法を示します。その他のパッケージ契約については、契約パッケージにバンドルされているREADMEファイルを参照してください。

アップグレードでは、既存のプロキシの背後にある実装が変更されます。新しいプロキシを作成したり、そのストレージをリセットしたりすることはありません。

Hardhatコマンドライン・インタフェースでは、契約のアップグレードがサポートされています。RPCプロキシAPIを使用してスマート・コントラクトをデプロイした場合、それは不変であり、アップグレードできません。

リファレンス・プロジェクトには、デモンストレーションおよびテスト用のV2実装が含まれています。
  • トークン: contracts/TokenizedDeposit/_testContracts/TokenizedDepositUpgradeableV2.sol
  • アカウント: contracts/obp-sdk/accounts/modules/v1/_testContracts/AccountWithERC5982UUPSV2.sol
V2契約では、V1記憶域レイアウトが保持され、version()がv2.0.0として公開され、空のinitializeV2()再初期化子が含まれます。参照コードとして扱い、レビューして、実際のアップグレード用に独自の互換性のある実装に置き換えます。

契約をアップグレードするには、契約のプロキシ・アドレス、構成されたOracle Blockchain Platform Besuネットワークおよびガバナンス提案を送信する権限が必要です。デプロイされた契約はアクティブであり、構成済のアップグレード認可パスに適格である必要があります。

実装を変更する前に、ストレージの互換性を保持します。ストレージ・フィールドのみを追加します。既存のフィールドのタイプを並べ替えたり、削除したり、変更したり、継承された記憶域レイアウトを変更したり、アップグレード検証をバイパスしたりしないでください。変更に互換性がない場合は、新しいプロキシをデプロイし、かわりに状態を明示的に移行します。

ノート:

アップグレードされたソースを指す必要があります。IMPLEMENTATION_CONTRACT変数は、Hardhatの契約ファクトリに渡されます。アップグレードされたバージョンの完全修飾されたSolidity契約名に設定します。
<path-to-upgraded-contract>.sol:<upgraded-contract-name>
現在のV1契約で変数を指さないでください。たとえば、Tokenized Deposit V2リファレンス実装を次の例に示します。
contracts/TokenizedDeposit/_testContracts/TokenizedDepositUpgradeableV2.sol:TokenizedDepositUpgradeableV2
別のV3またはカスタム実装を作成する場合は、コマンド内のパス名と契約名の両方をアップグレードされたソースに置き換えます。変更後、およびprepareコマンドを実行する前にコンパイルします。

トークン・プロキシのアップグレード

  1. 次のコマンドを実行して、トークンのアップグレードを準備します。準備により、実装とストレージのレイアウトが検証され、正確な新しい実装がデプロイされ、コード・ハッシュとライブラリ・アドレスがアップグレード・マニフェストに記録され、必要なガバナンス目的が送信されます。プロキシはまだアップグレードされていません。
    UPGRADE_ACTION=prepare \
    GOVERNANCE_INTENT_MODE=obp-besu \
    TOKEN_PROXY=<token-proxy-address> \
    IMPLEMENTATION_CONTRACT='contracts/TokenizedDeposit/_testContracts/TokenizedDepositUpgradeableV2.sol:TokenizedDepositUpgradeableV2' \
    LIBRARIES_JSON='{"ERC20TokenHelperLib":null,"ERC20MultiLevelApprovalHelperLib":null}' \
    DEPLOY_LIBRARIES=true \
    INITIALIZER_DATA=0x \
    UPGRADE_MANIFEST=.obp-da/upgrades/deposittoken-v2.json \
    npx hardhat run scripts/upgrade/upgrade-deposittoken.ts --network obp-besu

    DEPLOY_LIBRARIESをtrueに設定すると、nullライブラリ・エントリがデプロイされ、そのアドレスがレビューされた実装コード・ハッシュの一部になります。ライブラリを再利用するには、LIBRARIES_JSON変数に既存の互換性のあるライブラリ・アドレスを指定します。INITIALIZER_DATA変数は、upgradeToAndCall関数に渡されるRAW ABIでエンコードされたcalldataです。initializeV2()が空であるため、指定された参照V2契約に0xを使用します。新しい実装を初期化する必要がある場合は、正しくエンコードされたreinitializerのcalldataを指定して、アップグレード提案の一部としてレビューしてください。

  2. ガバナンスの提案を承認します。GOVERNANCE_INTENT_MODE変数がobp-besuに設定されている場合、準備ステップではOracle Blockchain Platform RPCプロキシを介して提案が送信されます。ターゲット・ガバナンス構成に必要な承認を取得します。プロキシは、提案が承認されて実行ステップが完了するまで、古い実装のままです。GOVERNANCE_INTENT_MODE=json-rpcは、Oracle Blockchain Platformエンドポイントではなく、ガバナンス・インテントを契約に直接送信するようにプロジェクトが構成されている場合にのみ使用します。
  3. トークン・アップグレードを実行します。承認後、prepareコマンドで記述されたものと同じマニフェストを実行します。
    UPGRADE_ACTION=execute \
    UPGRADE_MANIFEST=.obp-da/upgrades/deposittoken-v2.json \
    npx hardhat run scripts/upgrade/upgrade-deposittoken.ts --network obp-besu
    このスクリプトは、upgradeToAndCallファンクションをコールする前に、マニフェスト・チェーンID、期限および準備済実装バイトコード・ハッシュを検証します。

アカウント・プロキシのアップグレード

  1. 次のコマンドを実行して、アカウントのアップグレードを準備します。
    UPGRADE_ACTION=prepare \
    GOVERNANCE_INTENT_MODE=obp-besu \
    ACCOUNT_PROXY=<account-proxy-address> \
    IMPLEMENTATION_CONTRACT='contracts/obp-sdk/accounts/modules/v1/_testContracts/AccountWithERC5982UUPSV2.sol:AccountWithERC5982UUPSV2' \
    LIBRARIES_JSON='{}' \
    DEPLOY_LIBRARIES=false \
    INITIALIZER_DATA=0x \
    UPGRADE_MANIFEST=.obp-da/upgrades/deposittoken-account-v2.json \
    npx hardhat run scripts/upgrade/upgrade-account.ts --network obp-besu
    
    IMPLEMENTATION_CONTRACT変数の完全修飾値を、新しいアカウント実装のパスおよび契約名に置き換えます。アカウントのアップグレードにトークンのソースパス、プロキシアドレス、またはマニフェストを再利用しないでください。
  2. アカウントのアップグレード提案が必要なガバナンス承認を受けた後、次のコマンドを実行して、アカウントのアップグレードを承認および完了します。
    UPGRADE_ACTION=execute \
    UPGRADE_MANIFEST=.obp-da/upgrades/deposittoken-account-v2.json \
    npx hardhat run scripts/upgrade/upgrade-account.ts --network obp-besu

トラブルシューティング

条件 解決策
準備がストレージ検証に失敗する 強制的にアップグレードしないでください。互換性のないレイアウトの変更を修正するか、新しいプロキシをデプロイして状態を移行します。
前の準備マニフェストが期限切れであるか、別の実装をターゲットにしています REPREPARE=trueを設定し、古いマニフェストを監査レコードとして保持することによって、意図的に置換を作成します。
承認前に実行 最初にガバナンス承認を取得します。準備されたアップグレードが実行可能になる前に、承認されたインテントが必要です。
間違った実装が選択されています IMPLEMENTATION_CONTRACT変数がアップグレードされたソースの完全修飾path:contract値を使用していることを確認してから、新しいマニフェストを再コンパイルして準備します。別の実装用に準備されたマニフェストを実行しないでください。
実行が再実行されます スクリプトは、すでにアップグレードされているプロキシを検出し、2番目のアップグレード・トランザクションを送信するのではなく、その結果を記録します。implementationContractが欠落している古いマニフェストの場合は、実装履歴を同期できるように、実行時に同じIMPLEMENTATION_CONTRACT値を指定します。