Back to Blog

Solanaエコシステムを保護する(2)―プログラム間呼び出し

March 18, 2022
5 min read

0. レビュー

1. 概要

前回のブログでは、プログラムのデプロイとインタラクションの方法を紹介しました。クライアントサイドからプログラムの命令を呼び出す以外にも、 Solanaではクロスプログラム呼び出しと呼ばれるメカニズムを通じて、プログラム同士が呼び出し合うことも可能です。本稿では、クロスプログラム呼び出しがどのように使用されるかを説明します。テストコードはこちらにあります。

2. クロスプログラム呼び出し

クロスプログラム呼び出しは通常、invoke関数で実装されます。このセクションでは、プログラム内でlamportを転送する際のinvokeの使用法を説明します。

Solanaには、新しいアカウントの作成やlamport(SOL)の転送を担う、System Programというネイティブプログラムがあります。 この場合、プログラムAのようなプログラム内でlamportを転送するには、プログラムAはSystem Program内のtransfer()関数を呼び出します。具体的な例を以下に示します。

2.1 コードレビュー

3行目から10行目にかけて、必要なライブラリをインポートします。invoke()関数はsolana_program::programライブラリにあることに注意してください。

process_instruction関数において、22行目から30行目にかけて、クライアントによって渡された3つのアカウントを抽出します。lamportはfrom_accountからto_accountへ転送されます。33行目から44行目にかけて、invoke()関数が呼び出されます。この関数は2つの引数を受け取ります。1つ目は呼び出されるターゲット命令、2つ目はアカウントのセットです。 この例では、ターゲット命令はlamportの転送に使用されるtransfer()です。アカウントには、呼び出される命令に必要なすべてのアカウントが含まれます。この場合、from_accountto_accountです。

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

https://explorer.solana.com/address/EPaLuYQ4c11BJAe9ucLbta3xGFb17Zy3cZh3UDPbXRG9?cluster=devnet

2.2 Lamportの転送

前述の通り、トランザクションをデプロイされたプログラムに送信します。デプロイされたプログラムは、さらにSystem Programを呼び出してlamportをターゲットアドレスに転送します。 上記のコードは、クライアントがトランザクションを構築する方法を示しています。93行目から101行目にかけて、デプロイされたプログラムのprogramIdを抽出します。103行目から109行目にかけて、送信者、受信者、およびSystem Programのアドレスを生成します。111行目から117行目にかけて、トランザクションを構築します。118行目で、トランザクションはSolanaクラスタに送信されます。このトランザクションの唯一の署名者は送信者であることに注意してください。これは112行目で設定されています。送信者は、自分のアカウントから資金を引き出すトランザクションに承認(つまり署名)する必要がありますが、受信者は(113行目)署名する必要はありません。

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

https://explorer.solana.com/tx/4cxqnff8SakVcE9y5phmh6utcbBUGaLDPvqMRgSy9aPGdNVH6DCsQyJXCCzRGvW5CpygUi5pqhgBQxczXnWCoqPJ?cluster=devnet

3. Invoke または Invoke_signed

Solanaでは、プログラムは実行時にプログラム由来アドレス(PDA)と呼ばれるアカウントを生成できます。プログラムによって呼び出されるターゲット命令にPDAを持つ署名済みアカウントが含まれる場合、invoke()の代わりにinvoke_signed()を使用する必要があります。invoke_signed()の使用法を実証するために、別の例を使用します。まず、コントラクトコードをレビューしましょう。

3.1 コードレビュー

この例では、プログラムB内で実行時にPDAを作成します。PDAを作成するには、System ProgramをプログラムBで呼び出す必要があります。

3行目から10行目にかけて、必要なライブラリをインポートします。今回はinvoke_signed()がインポートされていることに注意してください(6行目)。

セクション2の例と同様に、必要なアカウント(22〜27行目)を抽出します。これらはSystem ProgramとPDAです。次に、find_program_address()関数を使用して、PDAのアドレスと、このPDAをed25519曲線からオフセットするために使用されるシードを生成します(29〜30行目)。これは、アドレスに秘密鍵が関連付けられていないことを保証するためです。この例では、クライアントとプログラムは同じシード(つまり「You pass butter」)を使用してPDAを生成します。したがって、公開鍵は同じであるはずであり、これは31〜34行目で確認されます。その後、invoke_signerを呼び出して、37〜47行目のallocate()命令を発行します。invoke()関数とは異なり、PDAを作成するために使用されたシードと、find_program_address()関数によって使用されたバンプシードという、さらに1つの引数を受け取ります。

アカウントを作成/割り当てるには、アカウント自体が署名を提供する必要があります。この例ではPDAが署名者です。PDAに署名するには、invoke_signedが使用されます。具体的には、Solanaはシードと呼び出し元(プログラムB)のprogramIdを使用してPDAを再作成し、それを指定されたアカウント(2番目の引数)と一致させます。それらが等しい場合、PDAに署名されます。

デプロイされたプログラムは以下で確認できます。

https://explorer.solana.com/address/4h3RXGsouTRvUWNG1Dqq2tuuASTXFebHC3wFzv3tSFCK?cluster=devnet

3.2 PDAの作成

2番目の例のクライアントスクリプトを見てみましょう。

104行目で、findProgramAddress()関数を介してPDAとバンプシードを抽出します。 112行目から120行目にかけて、トランザクションが作成され、送信されます。ここでPDAのプロパティ(isSigner)は「false」(113行目)になります。これは、クライアントによって署名できないためです。実行時には、プログラムBがPDAに署名し、System Program内のallocate命令を呼び出します。

PDAが割り当てられたトランザクションは以下で見つけることができます。

https://explorer.solana.com/tx/5fzdfzbD4281pY1HJm37f1fxSEMGmWtQmbmFPzEiP9v6hWF8GRRZmfcMDvPJugTrs3npnCsaWUGvw15URyBhx3LS?cluster=devnet

3.3 Invoke()は使用できますか?

invokeが使用できないことを実証するために、別のプログラム(プログラムC)を使用してallocation命令を呼び出します。

唯一の変更点は、invoke_signed()関数をinvoke()関数に変更したことです。アカウントが作成できなかったことがわかりました。

エラーは、クロスプログラム呼び出しが正常に実行されるためには署名者が必要であることを示しています。つまり、invoke_signed()関数が必要です。

4. 結論

本記事では、invoke()関数を介してクロスプログラム呼び出しを実装する方法を紹介しました。また、invoke()invoke_signed()の違いを実証するために、さまざまな例を使用しました。引き続き、このシリーズの他の記事も公開予定です。

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

Sign up for the latest updates
The Decentralization Dilemma: Cascading Risk and Emergency Power in the KelpDAO Crisis
Security Insights

The Decentralization Dilemma: Cascading Risk and Emergency Power in the KelpDAO Crisis

This BlockSec deep-dive analyzes the KelpDAO $290M rsETH cross-chain bridge exploit (April 18, 2026), attributed to the Lazarus Group, tracing a causal chain across three layers: how a single-point DVN dependency enabled the attack, how DeFi composability cascaded the damage through Aave V3 lending markets to freeze WETH liquidity exceeding $6.7B across Ethereum, Arbitrum, Base, Mantle, and Linea, and how the crisis forced decentralized governance to exercise centralized emergency powers. The article examines three parameters that shaped the cascade's severity (LTV, pool depth, and cross-chain deployment count) and provides an exclusive technical breakdown of Arbitrum Security Council's forced state transition, an atomic contract upgrade that moved 30,766 ETH without the holder's signature.

Weekly Web3 Security Incident Roundup | Apr 13 – Apr 19, 2026
Security Insights

Weekly Web3 Security Incident Roundup | Apr 13 – Apr 19, 2026

This BlockSec weekly security report covers four attack incidents detected between April 13 and April 19, 2026, across multiple chains such as Ethereum, Unichain, Arbitrum, and NEAR, with total estimated losses of approximately $310M. The highlighted incident is the $290M KelpDAO rsETH bridge exploit, where an attacker poisoned the RPC infrastructure of the sole LayerZero DVN to fabricate a cross-chain message, triggering a cascading WETH freeze across five chains and an Arbitrum Security Council forced state transition that raises questions about the actual trust boundaries of decentralized systems. Other incidents include a $242K MMR proof forgery on Hyperbridge, a $1.5M signed integer abuse on Dango, and an $18.4M circular swap path exploit on Rhea Finance's Burrowland protocol.

Weekly Web3 Security Incident Roundup | Apr 6 – Apr 12, 2026
Security Insights

Weekly Web3 Security Incident Roundup | Apr 6 – Apr 12, 2026

This BlockSec weekly security report covers four DeFi attack incidents detected between April 6 and April 12, 2026, across Linea, BNB Chain, Arbitrum, Optimism, Avalanche, and Base, with total estimated losses of approximately $928.6K. Notable incidents include a $517K approval-related exploit where a user mistakenly approved a permissionless SquidMulticall contract enabling arbitrary external calls, a $193K business logic flaw in the HB token's reward-settlement logic that allowed direct AMM reserve manipulation, a $165.6K exploit in Denaria's perpetual DEX caused by a rounding asymmetry compounded with an unsafe cast, and a $53K access control issue in XBITVault caused by an initialization-dependent check that failed open. The report provides detailed vulnerability analysis and attack transaction breakdowns for each incident.