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_inforequires that Sysvar account is passed to the program wasting the limited space available to the transactions. - The
from_account_infodeserializes 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_infoand 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