What it does:
Lint warns uses of Sysvar::from_account_info
and suggests to use Sysvar::get
instead for
the sysvars implementing Sysvar::get
function. The following sysvars implement Sysvar::get
:
- Clock
- EpochRewards
- EpochSchedule
- Fees
- LastRestartSlot
- Rent
Why is this bad?
The Sysvar::from_account_info
is less efficient than Sysvar::get
because:
- The
from_account_info
requires that Sysvar account is passed to the program wasting the limited space available to the transactions. - The
from_account_info
deserializes the Sysvar account data wasting the computation budget.
The Sysvar::from_account_info
should be used if and only if the program interacts with an old program that
requires the sysvar account to be passed in CPI call. The program could avoid deserialization overhead by using
the passed Sysvar account in CPI (after verifying the ID) and using the Sysvar::get
.
References:
solana_program/sysvar
docs,
Anchor docs
Works on:
- Anchor
- Non Anchor
Known problems:
None
Example:
let clock_account = next_account_info(account_info_iter)?;
let clock = clock::Clock::from_account_info(&clock_account)?;
Use instead:
let clock = clock::Clock::get()?;
How the lint is implemented:
- For every item
- If item is a struct and has
#[derive(Accounts)]
macro - For each field in the struct
- If field is of type Ty::Sysvar(T) and T is one of
Clock
,EpochRewards
,EpochSchedule
,Fees
,LastRestartSlot
,Rent
- Then report the field and suggest to T::get().
- If field is of type Ty::Sysvar(T) and T is one of
- If item is a struct and has
- For every function
- If an expr in function calls T::x() where x is
solana_program::Sysvar::from_account_info
and T is one of sysvars that implementsSysvar::get()
method.- report the call expr and suggest to use T::get().
- If an expr in function calls T::x() where x is