# Rust スマートコントラクト養成日記(9)契約アップグレードスマートコントラクト本質的にはプログラムであり、欠陥は避けがたいです。大量のテストと監査を経たスマートコントラクトであっても、脆弱性が存在する可能性があります。契約の脆弱性が一旦攻撃者に利用されると、ユーザー資産の損失を引き起こす可能性があり、その結果は深刻です。脆弱性の修正は通常、契約のアップグレードによって実現されます。脆弱性を修正するだけでなく、新しい機能を追加することも契約のアップグレードを必要とします。したがって、契約のアップグレード可能性は非常に重要です。本記事では、Rust契約のアップグレード方法について紹介します。## 1. Solidityスマートコントラクトの一般的なアップグレード方法イーサリアムスマートコントラクトは不変性を持ち、デプロイ後は変更できません。契約に脆弱性がある場合や新機能が必要な場合は、新しい契約をブロックチェーンにデプロイする必要があります。この方法が直面する課題は、契約をデプロイするたびに新しいアドレスが割り当てられることです。この契約を使用するすべてのDAppは、新しい契約に適応するために契約アドレスを変更する必要があります。さらに、旧バージョンの契約の状態を新バージョンに移行する必要があり、複雑な契約の状態移行作業は大きな負担であり、エラーが発生しやすいです。したがって、通常はデータとロジックを分離したアーキテクチャを採用し、データはロジックを処理しないステートコントラクトに保存し、すべてのロジックは別のロジックコントラクトで実装されます。このように、アップグレード時にはロジックコントラクトのみを更新すればよく、ステートの移行を考慮する必要はありません。この問題を解決するためには、プロキシコントラクト(Proxy Contract)を使用できます。プロキシコントラクトはデータを保存するために使用され、deleGatecallを使用してロジックコントラクトAを呼び出します。これにより、コントラクトAが読み書きするデータはすべてプロキシコントラクトに保存されます。アップグレードする際には、新しいコントラクトBをデプロイし、トランザクションを送信してプロキシコントラクトを新しいロジックコントラクトBに指向させればよいのです。! [](https://img-cdn.gateio.im/social/moments-54db9c46be493cda1cd1968fc890b4d6)## 2. NEAR スマートコントラクトアップグレードの一般的な方法StatusMessageプロジェクトを例に、NEARコントラクトの一般的なアップグレード方法を紹介します。### 2.1 合約データ構造は変更されていません契約のロジックだけを変更し、データ構造の変更がない場合は、near deployを使用して新しいコードをデプロイできます。旧契約のデータは正常に読み取ることができます。### 2.2 合約データ構造が変更されました契約のデータ構造を変更した場合、直接再デプロイすると契約の状態を逆シリアル化できなくなります。これは、契約の状態がシリアライズされたデータ形式で永続的に保存され、再デプロイ後にコード内のデータ構造が変更されるためですが、状態は変わらず、新しいデータ構造が古い状態と一致できなくなるからです。### 2.3 スマートコントラクトのアップグレードNEARは契約をアップグレードするためのMigrateメソッドを提供しています。新しい契約にmigrateメソッドを追加します:サビ#[private]#[init(ignore_state)]pub fn migrate() -> セルフ { old_stateさせてください: OldStatusMessage = env::state_read().expect('failed'); セルフ { タグライン: old_state.records, bios: LookupMap::new(b'b'.to_vec()), }}コントラクトを再展開する際にmigrateメソッドを呼び出します:近くにデプロイ \ --wasmファイルターゲット/wasm32-unknown-unknown/release/status_message.wasm \ --initFunction 'migrate' \ --initArgs '{}' \ --accountId statusmessage.blocksec_upgrade.testnetこれにより、新しいスマートコントラクトを成功裏にデプロイし、古いデータを移行することができます。! [](https://img-cdn.gateio.im/social/moments-73f5e5195fa71f1f25f5d35ba1e8b8ec)## 3. コントラクトのアップグレードにおける安全性の考慮契約の安全性のアップグレードでは、まず権限管理を考慮する必要があります。一般的に、契約は開発者またはDAOによってのみアップグレードできます。アップグレード関数はonly owner関数であるべきで、ownerのみが呼び出せることを保証します。契約のオーナーをDAOに設定し、提案と投票を通じて契約を共同管理することをお勧めします。個人アカウントをオーナーにすると契約が高度に中央集権化され、オーナーが契約データを自由に変更でき、さらに秘密鍵の喪失リスクも存在します。さらに、開発者が契約の移行を行う際には、以下の提案を考慮することができます:- マイグレーション関数の前に#[init(ignore_state)]を追加し、マイグレーション関数を実行する前に状態を読み込まないようにします。- 移行が完了したら、移行関数を削除し、移行関数が一度だけ呼び出されることを確認してください。- 新しいデータ構造は、移行時に初期化されます。! [](https://img-cdn.gateio.im/social/moments-af3fe22c1999da5db0e2853b8a271276)
Rustスマートコントラクトアップグレードガイド:データ移行からセキュリティ考慮事項まで
Rust スマートコントラクト養成日記(9)契約アップグレード
スマートコントラクト本質的にはプログラムであり、欠陥は避けがたいです。大量のテストと監査を経たスマートコントラクトであっても、脆弱性が存在する可能性があります。契約の脆弱性が一旦攻撃者に利用されると、ユーザー資産の損失を引き起こす可能性があり、その結果は深刻です。脆弱性の修正は通常、契約のアップグレードによって実現されます。脆弱性を修正するだけでなく、新しい機能を追加することも契約のアップグレードを必要とします。したがって、契約のアップグレード可能性は非常に重要です。本記事では、Rust契約のアップグレード方法について紹介します。
1. Solidityスマートコントラクトの一般的なアップグレード方法
イーサリアムスマートコントラクトは不変性を持ち、デプロイ後は変更できません。契約に脆弱性がある場合や新機能が必要な場合は、新しい契約をブロックチェーンにデプロイする必要があります。
この方法が直面する課題は、契約をデプロイするたびに新しいアドレスが割り当てられることです。この契約を使用するすべてのDAppは、新しい契約に適応するために契約アドレスを変更する必要があります。さらに、旧バージョンの契約の状態を新バージョンに移行する必要があり、複雑な契約の状態移行作業は大きな負担であり、エラーが発生しやすいです。
したがって、通常はデータとロジックを分離したアーキテクチャを採用し、データはロジックを処理しないステートコントラクトに保存し、すべてのロジックは別のロジックコントラクトで実装されます。このように、アップグレード時にはロジックコントラクトのみを更新すればよく、ステートの移行を考慮する必要はありません。
この問題を解決するためには、プロキシコントラクト(Proxy Contract)を使用できます。プロキシコントラクトはデータを保存するために使用され、deleGatecallを使用してロジックコントラクトAを呼び出します。これにより、コントラクトAが読み書きするデータはすべてプロキシコントラクトに保存されます。アップグレードする際には、新しいコントラクトBをデプロイし、トランザクションを送信してプロキシコントラクトを新しいロジックコントラクトBに指向させればよいのです。
!
2. NEAR スマートコントラクトアップグレードの一般的な方法
StatusMessageプロジェクトを例に、NEARコントラクトの一般的なアップグレード方法を紹介します。
2.1 合約データ構造は変更されていません
契約のロジックだけを変更し、データ構造の変更がない場合は、near deployを使用して新しいコードをデプロイできます。旧契約のデータは正常に読み取ることができます。
2.2 合約データ構造が変更されました
契約のデータ構造を変更した場合、直接再デプロイすると契約の状態を逆シリアル化できなくなります。これは、契約の状態がシリアライズされたデータ形式で永続的に保存され、再デプロイ後にコード内のデータ構造が変更されるためですが、状態は変わらず、新しいデータ構造が古い状態と一致できなくなるからです。
2.3 スマートコントラクトのアップグレード
NEARは契約をアップグレードするためのMigrateメソッドを提供しています。新しい契約にmigrateメソッドを追加します:
サビ #[private] #[init(ignore_state)] pub fn migrate() -> セルフ { old_stateさせてください: OldStatusMessage = env::state_read().expect('failed'); セルフ { タグライン: old_state.records, bios: LookupMap::new(b'b'.to_vec()), } }
コントラクトを再展開する際にmigrateメソッドを呼び出します:
近くにデプロイ \ --wasmファイルターゲット/wasm32-unknown-unknown/release/status_message.wasm
--initFunction 'migrate'
--initArgs '{}'
--accountId statusmessage.blocksec_upgrade.testnet
これにより、新しいスマートコントラクトを成功裏にデプロイし、古いデータを移行することができます。
!
3. コントラクトのアップグレードにおける安全性の考慮
契約の安全性のアップグレードでは、まず権限管理を考慮する必要があります。一般的に、契約は開発者またはDAOによってのみアップグレードできます。アップグレード関数はonly owner関数であるべきで、ownerのみが呼び出せることを保証します。
契約のオーナーをDAOに設定し、提案と投票を通じて契約を共同管理することをお勧めします。個人アカウントをオーナーにすると契約が高度に中央集権化され、オーナーが契約データを自由に変更でき、さらに秘密鍵の喪失リスクも存在します。
さらに、開発者が契約の移行を行う際には、以下の提案を考慮することができます:
!