A Solana developer encounters a transaction that succeeded on-chain but produced unexpected results: funds moved, a token was minted, but an intermediary contract call appears to have failed silently. The transaction receipt shows confirmation, yet the intended state change never occurred. The developer cannot reproduce the issue locally, and without visibility into the actual sequence of program invocations that executed, debugging becomes a manual guessing game. This is the core challenge of cross-program invocation (CPI) debugging on Solana: understanding not just whether a transaction succeeded, but precisely which programs were called, in what order, with what parameters, and where the execution diverged from expectation.
Solscan, the leading blockchain explorer for the Solana network, provides the tools to reconstruct that execution flow with precision. By combining transaction tracing, instruction inspection, program verification, and real-time account state tracking, developers can move from guessing at contract behavior to observing exactly what happened on-chain. The platform does not require private key access, login, or special permissions; every transaction and program interaction is publicly visible and can be examined in full detail. Understanding how to read and interpret Solscan’s output transforms a confusing failure into a clear sequence of events.
Understanding the CPI call stack and instruction hierarchy
Cross-program invocation is Solana’s mechanism for one program to call another. Unlike traditional function calls in a single process, a CPI requires one program to construct an instruction, invoke the system, and allow another program to execute with a specified set of accounts and data. The original program can continue executing after the invoked program completes, and the invoked program can in turn invoke yet another program. This creates a tree-like structure of invocations that can be difficult to trace without the right tools.
When viewing a transaction on Solscan, the instruction hierarchy appears as a nested list. The top-level instructions are the ones submitted directly as part of the transaction; any invocations triggered by those instructions appear indented beneath them. Each level represents a program being invoked, the accounts it accessed, and the data it received. A failed instruction will show an error status, but critically, any CPIs triggered before that failure will still be visible and executed. Understanding this structure is essential because a CPI failure does not automatically roll back the entire transaction—only the failed instruction’s effects are reversed, while earlier effects may persist.
Solscan displays each instruction with its program address, the accounts it touched, the data it received, and its status. By reading from the top down, a developer can reconstruct the exact sequence of execution. If a token swap routed through multiple aggregators, each program invocation appears in order. If a governance proposal triggered a series of program updates, the sequence is visible. The key insight is that every interaction on Solana—whether successful or failed—leaves a permanent, publicly verifiable record that Solscan makes accessible and readable.
The instruction view also shows the data passed to each program, typically represented in hexadecimal or decoded into recognizable instruction types if the program has been verified on Solscan. A verified program displays human-readable instruction names and parameter layouts rather than raw bytes. This dramatically reduces the cognitive load of debugging. Instead of decoding a hex string by hand, a developer can immediately see that an instruction was a “swap” with specific input and output token amounts, or a “transfer” with a recipient and amount.
Decoding account state changes across the CPI chain
Each program that executes can read and modify account data. Understanding which accounts changed, and how, is often the difference between identifying a bug and remaining confused. Solscan provides a “Balances” view for each transaction that shows the net change to account balances at the conclusion of the transaction. However, intermediate account states—the values that existed between two CPIs—are not retained by the blockchain itself. Instead, developers must infer them by reading the accounts involved in each instruction and understanding what each program does with them.
When examining a CPI chain, pay particular attention to the accounts listed for each instruction. An account marked as “writable” was modified; an account marked as “read-only” was only consulted. The order of accounts often matters because many Solana programs use positional account parsing. The first account might be the user’s token account, the second the destination, the third a mint authority, and so on. If an instruction has accounts in the wrong order, or if a read-only account is marked incorrectly, the program will reject the instruction or behave unexpectedly.
Solscan’s account explorer complements this by showing the complete history of a specific account: its current balance or data, previous transactions that touched it, and account metadata such as owner program and rent status. If a token account was frozen by a program during a CPI and the subsequent instruction tried to transfer from it, the account history will make that sequence clear. By cross-referencing the account involved in each CPI instruction, a developer can reconstruct the state evolution and identify where expectations diverged from reality.
A concrete example: a developer expects a swap to reduce token A in a user’s account and increase token B. Examining the transaction on Solscan, they see the swap program was called with the correct accounts, but the final balance shows that token A did not decrease. By inspecting the token account history and the swap instruction’s parameters, they discover that the swap used a different token account—one belonging to a liquidity pool or intermediary—rather than the user’s intended account. The CPI chain made the mistake visible.
Using developer tools and API access for deeper inspection
Beyond the web interface, Solscan exposes developer tools and API access that allow programmatic querying of on-chain data. A developer can retrieve transaction details, instruction parameters, account states, and historical data without clicking through the web interface. This is particularly useful when debugging requires inspecting multiple related transactions, comparing program behavior across different scenarios, or building automated monitoring and alerting systems.
The API allows developers to fetch transaction information by signature, examine specific accounts, retrieve balance history, and access smart contract verification details. When a program is verified on Solscan, its IDL (Interface Definition Language) is uploaded, allowing the platform to decode instructions and account layouts automatically. For developers building their own debugging tools or integrating on-chain data into a development environment, the API provides the same underlying data that powers the web interface.
To debug a CPI chain programmatically, a developer might fetch a transaction by signature, iterate through its instructions, and for each instruction check the program’s verification status. If verified, the API returns the decoded instruction type and parameters. If not verified, the raw instruction data can still be fetched and decoded locally if the developer has access to the program’s IDL. This allows for automated analysis: a developer could scan a series of failed transactions to identify common patterns, account misconfigurations, or sequence violations that led to failures.
Rate limits and API quotas apply, but the free tier provides substantial access for development and debugging purposes. For production monitoring or high-volume analysis, higher tiers offer increased limits and priority access. The important point is that learn more about integrating Solscan’s developer tools into your workflow to move debugging from manual inspection to systematic investigation.
Identifying CPI errors and failure propagation
When a CPI fails, the error message may not be immediately obvious. A program that invokes another program receives a result code; if it does not check that result code, execution continues as though the CPI succeeded. This is a common source of subtle bugs: a developer assumes a transfer completed, but the transfer instruction actually failed due to insufficient balance, frozen accounts, or authorization issues. The outer program continued, perhaps updating its internal state to reflect a transfer that never actually happened.
Solscan displays the status of each instruction: “Success”, “Failed”, or occasionally an intermediate state. When an instruction fails, the reason is often provided in human-readable form if the program is verified. A message such as “Insufficient lamports” or “Token account is frozen” immediately identifies the problem. For unverified programs, the error code is displayed numerically, requiring the developer to consult the program’s source code or documentation to interpret it.
One subtle but important detail: when a CPI fails, any state changes made by the invoked program are rolled back, but state changes made before the CPI are not. If Program A modifies an account, then invokes Program B which fails, Program A’s modification persists. This is by design—it allows for sophisticated error handling and recovery patterns—but it also means a developer must trace through each instruction individually to understand what actually happened to account state.
A practical debugging checklist: First, verify that each instruction in the CPI chain succeeded rather than assuming all instructions with a “Success” transaction status also succeeded individually. Second, confirm that the accounts passed to each instruction match what that program expects. Third, check that accounts were marked as writable or read-only correctly. Fourth, examine the raw instruction data or decoded parameters to ensure they align with the program’s expected input format. Solscan makes each of these checks feasible by displaying all the necessary information in one place.
Comparing local simulation with on-chain execution
During development, a programmer typically tests transactions using a local validator or devnet before deploying to mainnet or other production networks. The local environment can be controlled and reproduces in theory, but discrepancies between local and production execution are common. These arise from differences in account state, rent-exempt balance requirements, program versions, or subtle timing and ordering issues that only appear with real on-chain traffic.
When a transaction succeeds locally but fails on-chain, Solscan becomes the window into what actually happened. A developer can run the same transaction against a local validator, observe its success, then submit it to devnet or mainnet, inspect the resulting transaction on Solscan, and compare. If the on-chain version shows different account states, different instruction sequences, or unexpected CPIs, those differences reveal the source of the bug. Perhaps an intermediate program behaves differently when invoked as a CPI versus when called directly. Perhaps an account has a different owner or state in production.
The comparison process is systematic: fetch the transaction details from Solscan, extract the exact instruction sequence and account states, then replay or re-simulate those conditions locally. Many Solana development tools support constructing transactions with identical account states to reproduce the exact scenario. By aligning the local and on-chain views, a developer can identify whether the issue is in program logic, account configuration, or external state that only exists in production.
Solscan’s transaction search and filtering capabilities make it easy to locate relevant transactions. A developer can search by program address to find all transactions that invoked a specific program, by wallet address to find all activity associated with a specific account, or by block range to examine activity during a specific time window. These searches help isolate the pattern of failures or unexpected behavior, rather than examining each transaction in isolation.
Monitoring and alerting for production contract behavior
Once a contract is deployed and in production, developers need to ensure it continues behaving as expected. Unusual transaction patterns, error spikes, or unexpected account state changes can indicate bugs, security issues, or external pressure on the system. Solscan’s real-time updates and blockchain data provide the raw material for monitoring systems that track contract health and alert developers to anomalies.
A developer can set up automated monitoring by periodically querying Solscan’s API for transactions involving their contract. By tracking instruction success rates, error types, account state changes, and CPI patterns, they can establish baselines for normal behavior and detect deviations. If a program suddenly begins failing with a specific error code, or if a frequently-called instruction stops being invoked, these changes become visible and actionable before they impact users.
The monitoring system can also track CPI patterns. If a program typically invokes a specific set of other programs in a specific order, but a production transaction diverges from that pattern, it might indicate that an upstream dependency changed or behaved unexpectedly. By maintaining visibility into the entire CPI chain, not just the top-level program, developers can catch cascading failures before they propagate.
Historical data on Solscan allows developers to correlate contract behavior with external events. If a program consistently succeeds except during specific windows, or if certain types of accounts trigger different behavior, those patterns can be identified by examining historical transactions. This historical perspective transforms random observations into systematic understanding, and understanding enables prevention.
Reconstructing transaction flow for security audits and verification
When conducting a security audit or verification of a smart contract system, auditors must understand not just the code, but how it behaves when invoked by real transactions. A theoretically secure program can be exploited if the CPI sequence allows for unexpected interactions or if account state assumptions are violated. Solscan provides the evidence layer for verification: the actual on-chain interactions that resulted from the code under audit.
An auditor can search for all transactions involving a contract, examine a representative sample across different scenarios, and verify that the transaction patterns match the program’s documented behavior and security model. If a program claims to prevent reentrancy through checks-effects-interactions patterns, but the CPI chain shows an interaction in the wrong order, the audit has found evidence of a potential issue. If a program claims to enforce specific access controls, but a transaction shows an unauthorized account modifying restricted state, Solscan makes that violation visible.
The combination of source code review (understanding intent), smart contract verification on Solscan (confirming what code was deployed), and transaction analysis (observing actual behavior) creates a complete audit trail. This is particularly important for high-value contracts where security properties must be verified with high confidence. Solscan’s role is to ensure that the deployed code’s actual behavior is observable and subject to external verification.
Documentation of findings also becomes more rigorous when supported by Solscan evidence. Rather than claiming a program “might have” a specific behavior, auditors can point to specific transactions, instruction sequences, and account state changes on Solscan as proof of actual behavior. This transforms security findings from theoretical concerns into documented facts.
Frequently asked questions
How do I view the CPI chain for a specific transaction on Solscan?
Search for the transaction signature in Solscan’s search bar. The transaction details page displays all instructions in a nested hierarchy. Top-level instructions appear first, and any CPIs triggered by those instructions appear indented beneath them. Click on any instruction to view its program address, accounts, data, and status. If the program is verified, instruction types and parameters are decoded automatically.
Can I trace which program failed if a transaction shows as successful?
Yes. A transaction can show an overall successful status while individual instructions within it have failed. Examine each instruction in the CPI chain individually to check their status. Look for any instruction marked as “Failed” along with its associated error message. Account state changes will reflect only the effects of successful instructions; failed CPIs are rolled back but do not prevent earlier instructions from persisting.
What information do I need to verify a program’s behavior on Solscan?
Locate the program address and search for it on Solscan. If the program is verified, its IDL and source code are available, enabling automatic decoding of instructions and account layouts. If not verified, you can still see all transactions involving that program and their instruction data in raw form. Compare multiple transactions to identify patterns and confirm that the actual on-chain behavior matches the program’s intended design. Use account history to track state changes and validate security properties.
Comentários