Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 5

Understanding Solana's Core Sysvars

Recommended resources

Welcome to the fifth lesson of our introduction to Solana fundamentals. In our last session, we took a deep dive into the anatomy of a transaction, using a block explorer to dissect it into its core components: instructions, accounts, and signers. We even saw a special account, SysvarRent, make an appearance, which served as a perfect preview for today's topic.

This lesson focuses on those special "Sysvar" accounts. You'll learn what they are, what purpose the most common ones serve, and, most importantly, how to access their data from within a Solana program. For a security researcher, understanding Sysvars is non-negotiable. They are a trusted source of on-chain information, but as you'll see, mishandling them can lead to catastrophic vulnerabilities. We'll explore the roles of the Clock, Rent, and Instructions Sysvars, paying close attention to the security implications of each.

1. What Are Sysvars?

In Solana, Sysvars (System Variables) are special read-only accounts that provide programs with access to network state and transaction context. If you're coming from an EVM background, you can think of them as the Solana equivalent of Ethereum's global variables like block.timestamp, block.number, or msg.data, but with a key difference: in Solana, these are actual accounts with fixed, well-known public keys.

Because they are accounts, they must be passed into your program's instruction handler just like any other account. A program can then read the data from these accounts to get reliable information directly from the Solana runtime.

There are two primary ways a program can access a Sysvar:

  1. Using a get() method: The Anchor framework and the solana-program crate provide convenient helper functions (e.g., Clock::get()) for some of the most common Sysvars. This is the easiest method.
  2. Passing the account and deserializing it: For other Sysvars, or when writing native Rust programs, you pass the Sysvar account into your instruction and deserialize its data manually.

We will explore both methods. For a high-level introduction, take a look at the following resource.

Solana Sysvars Explained | RareSkills

This article from RareSkills provides a concise introduction to Sysvars and the methods for accessing them.

Please read the first few sections of the article, from the start down to the end of the introduction. Focus on the core definition and the two access methods described: the get method and using the public address.

Now, let's examine the three most important Sysvars you will encounter constantly in your work.


2. The Clock Sysvar

The Clock Sysvar provides a "best-effort" view of the cluster's time. It's the go-to source for on-chain timekeeping.

  • Purpose: To access slot number, epoch number, and an estimated Unix timestamp.
  • Key Fields:
    • slot: The current slot number. This is the most reliable and monotonically increasing value.
    • epoch: The current epoch number.
    • unix_timestamp: A timestamp estimated by the validators. Crucially, this is not guaranteed to be accurate or monotonically increasing.

Accessing the Clock Sysvar

The Clock is one of the Sysvars that has a convenient get() method. The RareSkills article shows a clear example of this.

Solana Sysvars Explained | RareSkills

In the same article, find the section on the Clock sysvar.

Review the code snippet under the Clock sysvar heading. Notice how Clock::get()? is a simple, single line of code to fetch the entire Clock object.

Security Warning: Insecure Randomness

Given your goal of becoming a security researcher, this is a critical point. It's tempting to use values from the Clock Sysvar, like the slot or timestamp, to generate randomness for applications like lotteries or NFT mints. Do not do this. These values are public, predictable, and can be manipulated by validators or sophisticated users. An attacker can simply simulate the outcome of a transaction in a future slot and only submit their transaction when they know the outcome will be favorable.

The article below highlights this vulnerability pattern.

Solana Vulnerabilities Every Developer Should Know - DEV Community

This article from DEV Community outlines common Solana security pitfalls.

Navigate to the section on Insecure Randomness. Pay close attention to the "DON'T USE" code block, which explicitly warns against using Clock::get()?.slot and Clock::get()?.unix_timestamp for randomness.


3. The Rent Sysvar

We've discussed rent before: it's the fee paid to keep account data alive on the Solana ledger. Accounts can be made "rent-exempt" by depositing a sufficient number of lamports. The Rent Sysvar provides the necessary parameters for a program to calculate this amount.

  • Purpose: To provide the network's current rent parameters.
  • Key Fields:
    • lamports_per_byte_year: The cost in lamports to store one byte for one year.
    • exemption_threshold: A multiplier on the yearly cost to determine the total deposit for rent exemption (typically 2 years' worth).
    • burn_percent: The percentage of rent collected that is burned.

Programs use this Sysvar most often when creating new accounts to ensure they are funded with enough lamports to be rent-exempt.

Accessing the Rent Sysvar

Like the Clock, the Rent Sysvar is easily accessible via a get() method.

Solana Sysvars Explained | RareSkills

Return to the RareSkills article and find the section on the Rent sysvar.

Read the section titled Rent sysvar. Again, note the simplicity of Rent::get()?. The article also breaks down the output, explaining the key fields.

For a more practical, security-oriented example, let's see how you'd use the Rent Sysvar in both native Rust and Anchor to enforce that an account is rent-exempt.

Solana Vulnerabilities Every Developer Should Know - DEV Community

Now, let's look at the DEV Community article again, this time focusing on the "Rent Siphoning" vulnerability.

In the section on fixing this vulnerability, examine the two code blocks. The Anchor example shows how to verify rent exemption using Rent::get(). The Pinocchio/Native example shows how to use Rent::get()? to fetch the minimum balance needed for a new account. These are common patterns you'll use and audit.


4. The Instructions Sysvar

This is arguably one of the most powerful and security-critical Sysvars. It allows a program to inspect other instructions within the same transaction.

  • Purpose: To enable "instruction introspection," giving a program read-only access to the other instructions being processed in the same transaction.
The Instructions Sysvar gives a program access to the array of `Instruction` structs contained within the transaction's `Message`, as shown here. This allows a program to verify what other actions are being taken alongside its own execution.

The Wormhole Hack: A Case Study in Sysvar Validation

The importance of the Instructions Sysvar is best illustrated by the February 2022 Wormhole Bridge exploit, which resulted in a $325 million loss. The vulnerability stemmed from the program failing to validate that the "Instructions Sysvar" account passed to it was the actual, legitimate Sysvar.

The attack worked like this:

  1. The Wormhole program had a function that used the Instructions Sysvar to check the contents of other instructions in the transaction.
  2. However, it used a deprecated function that didn't automatically verify the address of the Sysvar account.
  3. The attacker created a fake account containing malicious, custom-crafted instruction data that looked legitimate.
  4. They called the Wormhole program, but instead of passing the real Instructions Sysvar's public key, they passed the public key of their fake account.
  5. The program read the fake instruction data, believed it was authentic system data, and incorrectly authorized a massive withdrawal.

This incident highlights the single most important rule of using Sysvars that don't have a get() method: You must verify the account's public key.

Solana Vulnerabilities Every Developer Should Know - DEV Community

Let's return to the DEV Community article for a final, critical security lesson.

Read section 12. Sysvar Account Validation. It provides a concise summary of the Wormhole hack and then shows exactly how to prevent it. Pay close attention to the "How to Fix" section. Note the Anchor #[account(address = sysvar::instructions::ID)] constraint and the native Rust if instructions_account.key != &instructions::ID check. This is the correct, secure pattern.

Accessing the Instructions Sysvar

As you've just seen, accessing the Instructions Sysvar involves passing it as a regular account and then validating its address before use. The RareSkills article provides a full code example, including the client-side test script needed to pass the Sysvar's public key.

Solana Sysvars Explained | RareSkills

Let's analyze the full implementation from the RareSkills article.

Find the section for the Instruction sysvar. Read through the entire section. Notice how the Initialize struct is modified to accept instruction_sysvar: AccountInfo<'info'>. Then, in the test file, anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY is passed in the .accounts() call. This shows the full end-to-end flow of passing and using this Sysvar. The article uses load_instruction_at_checked, which is safer than the deprecated function used in the Wormhole hack, but the explicit address check you saw in the dev.to article is the most secure approach.


Conclusion

In this lesson, we demystified Solana's Sysvars, focusing on the three you'll encounter most frequently. They are essential tools that provide your programs with a direct line to the runtime's state.

Here are the key takeaways:

  • Sysvars are special accounts that provide trusted on-chain data like time (Clock), rent costs (Rent), and transaction context (Instructions).
  • Some Sysvars (Clock, Rent) can be easily accessed via a ::get() helper method.
  • Others (Instructions) must be passed into the instruction as an account. When doing so, it is critically important to validate the account's public key to prevent an attacker from passing a fake account. The $325M Wormhole hack is a stark reminder of this.
  • Values from the Clock Sysvar are predictable and must never be used as a source of randomness for security-sensitive applications.

You now have a solid understanding of Solana's account model, transaction lifecycle, and the system variables that provide context to your programs. With these fundamentals in place, you are now ready to start writing code. In the next lesson, we will move into Module 2 and write our first native Solana program from scratch, putting this knowledge into practice by building a program that can deserialize and act upon instruction data.