Back to Blog

Solanaエコシステムの安全確保(3)— プログラムアップグレード

March 27, 2022

0. レビュー

1. 概要

前回のブログでは、invoke関数とinvoke_signed関数によるクロスプログラム呼び出しの実装方法をご紹介しました。本稿では、もう一つの基本的なトピックであるプログラムのアップグレードについてご紹介します。

2. アップグレード可能なプログラムのデプロイ

デフォルトでは、Solanaにデプロイされるすべてのプログラムは、BPFLoaderUpgradeableローダーを使用してデプロイされます。これは、プログラムがアップグレード可能であることを意味します。これに加えて、Solanaは--finalオプションを提供しており、デプロイされたプログラムが不変であることを保証します。この場合、プログラムのデプロイにはBPFLoader2ローダーが使用されます。デプロイ後は、プログラムのアップグレードはできません。

BPFLoaderUpgradeableローダープログラムは、プログラムアカウントプログラムデータアカウントバッファアカウントの3種類のアカウントを管理します。デプロイプロセスでは、まずバッファアカウントが作成されます。その後、Solana CLIはターゲットプログラムのバイトコードをロードし、バッファアカウントに書き込みます。最終的に、バッファアカウントに格納されたバイトコードはプログラムデータアカウントにコピーされます。

このように、バッファアカウントはアップグレード可能なBPFローダーがデプロイプロセス中にバイトコードを一時的に格納するために使用され、プログラムデータアカウントはプログラムの実際のデータを格納し、プログラムアカウントは対応するプログラムデータアカウントを指すプロキシとして機能します。

以下では、プログラムをアップグレードする方法について、いくつかのサンプルを見ていきます。本稿で使用するコードはすべてこちらで見つけることができます。

2.1 コードレビュー (Rectangle_Area)

このサンプルコントラクトでは、13行目から17行目にかけて、widthheightareaの3つの属性を持つRectangleという構造体を定義しています。また、Rectangle用のarea()関数も定義しています。area()関数は、widthheightを使用して長方形の面積を計算します。

process_instruction()関数では、まずunpack_u32()関数を使用して、命令データから長方形のwidthheightを抽出します(45行目-46行目)。51行目では、長方形のデータを格納するために使用されるアカウントを抽出します。59行目では、try_from_slice_unchecked()関数を使用して、アカウントのデータをRectangle構造体の型でデシリアライズします。次に、データを構造体の対応するフィールドに割り当て、面積の値を計算します(61行目-63行目)。最後のステップは、データをシリアライズし、データアカウントに書き戻すことです。

デプロイされたプログラムは、以下のリンクで見ることができます。

https://explorer.solana.com/address/84mMqHRTQT6b2vfsD7XRxVKA3XMd7xoEXFdF6pLNw8y?cluster=testnet

2.2 トランザクションの送信

クライアント側では、まずデータを格納するためアカウントを作成するトランザクションを送信します。十分なスペースを確保するため、スペースサイズを1,024バイトに設定します。

次に、長方形の面積を計算し、データアカウントに格納するための別のトランザクションを送信します。

トランザクションは以下のリンクで見ることができます。

https://explorer.solana.com/tx/4PybjXGRpuPKpak7FAz4BKMbcQCWmway69zAxtTnpFRuTTg7onyxW7agSe6ETx44iAGexbgnBUa8WdzdTTQSawJ3?cluster=testnet

3. アップグレード

ここで、プログラムに新しい関数を追加して、長方形の周囲長を計算できるようにします。

更新されたプロジェクトをコンパイルした後、以下のコマンドでオンチェーンのデプロイ済みプログラムをアップグレードします。

solana program deploy /path/to/program.so --program-id <PROGRAM_ID>

コントラクトは直接アップグレードでき、関連するトランザクションは以下で確認できます。

https://explorer.solana.com/tx/4Dm9v4zMiijKjQBhatx1D9xbV9PvMLdaonUWLaC2VwzkFvzdgorzbX5vsy4VQ7VxSUmqadftjiDzbyUmXgQchYmk?cluster=testnet

さらに、プログラムにトランザクションを送信して、正常にアップグレードされたことを確認します。結果は、関数が正常に機能していることを示しています。

関連するトランザクションは以下で見ることができます。

https://explorer.solana.com/tx/21c2G7kPVktAtdUFkH3QwGVi7orajRmy5PJo1UxX1mmAMU68eUkNuLzWYJRBaTzwGi5DxeocYjHfpWiU4hcSFtpQ?cluster=testnet

4. 再度アップグレード

今回は、計算された周囲長をデータアカウントに格納することにします。この場合、構造体Rectangleperimeterという属性を1つ追加します(18行目)。

データアカウントの構造体が以前のものと異なるため、まずデータアカウントからデータを読み取る必要があります。以前の構造体(つまりOldRectangle)を使用して格納されたデータをデシリアライズします。その後、対応する属性を新しい構造体(つまりCurrentRectangle)に割り当て、新しい属性(つまりperimeter)を初期化します。

最後に、周囲長の値を計算し、それをupdate_accountに割り当ててから、account_dataにシリアライズします。

アップグレードのためのトランザクションは以下で見ることができます。

https://explorer.solana.com/tx/5J3oKxZXtCi755gD7pMnVh48AFvmeVzRLPgJiyNn8JFeCKx1xpAfJtsi34zjyYKJmnMk8LtC3bcwfFSP7H2gtj5o?cluster=testnet

アップグレード後、solana account <DataAccount>コマンドでアカウントに格納されているデータをチェックできます。属性は最初の32バイトに格納されていることがわかります。これでアップグレードプロセス全体が完了しました。

5. 結論

この記事では、Solanaでプログラムをアップグレードする方法について説明しました。詳細なプロセスを説明するために、さまざまな例を使用しました。続報にご期待ください。Solanaに関する記事は今後も掲載していきます。

このシリーズの他の記事を読む:


BlockSecについて

BlockSecは、世界的に著名なセキュリティ専門家グループによって2021年に設立された、最先端のブロックチェーンセキュリティ企業です。当社は、Web3の世界のセキュリティとユーザビリティを向上させ、その大規模な普及を促進することに尽力しています。この目的のため、BlockSecはスマートコントラクトとEVMチェーンのセキュリティ監査サービス、セキュリティ開発と脅威のプロアクティブなブロックのためのPhalconプラットフォーム、資金追跡と調査のためのMetaSleuthプラットフォーム、そしてWeb3ビルダーが仮想通貨の世界を効率的にサーフィンするためのMetaSuites拡張機能を提供しています。

現在までに、MetaMask、Uniswap Foundation、Compound、Forta、PancakeSwapなど300社を超える著名なクライアントにサービスを提供し、Matrix Partners、Vitalbridge Capital、Fenbushi Capitalなどの著名な投資家から2回の資金調達で数千万米ドルを獲得しています。

公式ウェブサイト: https://blocksec.com/

公式Twitterアカウント: https://twitter.com/BlockSecTeam

Sign up for the latest updates
Drift Protocol Incident: Multisig Governance Compromise via Durable Nonce Exploitation
Security Insights

Drift Protocol Incident: Multisig Governance Compromise via Durable Nonce Exploitation

On April 1, 2026 (UTC), Drift Protocol on Solana suffered a $285.3M loss after an attacker exploited Solana's durable nonce mechanism to delay the execution of phished multisig approvals, ultimately transferring administrative control of the protocol's 2-of-5 Squads governance with zero timelock. With full admin privileges, the attacker created a malicious collateral market (CVT), inflated its oracle price, relaxed withdrawal protections, and drained USDC, JLP, SOL, cbBTC, and other assets through 31 rapid withdrawals in approximately 12 minutes. This incident highlights how durable nonce-based delayed execution can decouple signer intent from on-chain execution, bypassing the temporal assumptions that multisig security implicitly relies on.

Weekly Web3 Security Incident Roundup | Mar 23 – Mar 29, 2026
Security Insights

Weekly Web3 Security Incident Roundup | Mar 23 – Mar 29, 2026

This BlockSec weekly security report covers eight DeFi attack incidents detected between March 23 and March 29, 2026, across Ethereum and BNB Chain, with total estimated losses of approximately $1.53M. Incidents include a $679K flawed burn mechanism exploit on the BCE token, a $512K spot-price manipulation attack on Cyrus Finance's PancakeSwap V3 liquidity withdrawal, a $133.5K flash-loan-driven referral reward manipulation on a TUR staking contract, and multiple integer overflow, reentrancy, and accounting error vulnerabilities in DeFi protocols. The report provides detailed vulnerability analysis and attack transaction breakdowns for each incident.

Newsletter -  March 2026
Security Insights

Newsletter - March 2026

In March 2026, the DeFi ecosystem experienced three major security incidents. Resolv Protocol lost ~$80M due to compromised privileged infrastructure keys, BitcoinReserveOffering suffered ~$2.7M from a double-minting logic flaw, and Venus Protocol incurred ~$2.15M following a donation attack combined with market manipulation.