Solana Quizlet 101
要求:聚焦在solana / spl / solana dapp program 的工程实现细节和攻击面 / checklist
Solana Infrastructure
- What is a solana slot? How long is a solana slot?
- What is a blockhash? What is Solana PoH? what does blockhash has something to do with PoH?
- Each Solana account is identifiable by its unique address, represented as 32 bytes in the format of an Ed25519
PublicKey. How is solana account addresses different from ethereum EOA addresses? - Why I cannot find a block by blockhash on solana explorers? (only by block id)
- What is Address Lookup Table Account (ALT) ?
Solana Transaction
- What's the relationship between a transaction and an instruction (ix)?
- What is Compute Budget ? Please compare it with Ethereum gas accounting. What's same and what's different ?
- Please breifly explain what can Compute Budget Program do (ComputeBudget111111111) ? reference tx.
- What is Compute Uint(CU)? What is CU Limit / CU Price ? What is the differnece between CU Price and CU Limit?
- Can solana programs set CU Limit and CU price themselfs through CPI ?
- If I do not set the CU Limit, what's the default value? Is there a max cap for CU Limit ?
- If I do not set the CU Price, what's the default value? Is there a max cap for CU Price?
- What is Prioritization Fee ?
- Consider a tx with a single signer. CU Limit not set. CU Price not set. How much fee will the signer pay for this tx? what's the difference if this tx fails ?
- Consider a tx with a single signer. CU Limit = 1.4M. CU Price not set. How much fee will the signer pay for this tx? what's the difference if this tx fails ?
- Consider a tx with a single signer. CU Limit = 1.4M. CU Price = 500k. How much fee will the signer pay for this tx? what's the difference if this tx fails ?
- Consider a tx with a single signer. CU Limit not set. CU Price = 500k. How much fee will the signer pay for this tx? what's the difference if this tx fails ?
- Consider a tx with a single signer. CU Limit = 2.8M. CU Price = 500k. How much fee will the signer pay for this tx? what's the difference if this tx fails ?
- Can I call the set CU Limit ix and set CU price ix at the end of my transaction ?
- Since users can have multiple ixs in one single transaction, does it eliminate front-running ?
- What is versioned transaction ? What's the difference between versioned transaction and legacy transaction ?
- There are three commitment statuses for a tx: 1) Processed 2) Confirmed 3)Finalized What's the difference ?
- Is there compute unit limitations for each transaction ? How much ?
- Is there compute unit limitations for each block ? How much ?
- Is there compute unit limitations for each account per block ? How much ?
Solana Account Model
On Solana, all data is stored in what are referred to as "accounts". The way data is organized on Solana resembles a key-value store, where each entry in the database is called an "account".
- What types of data can accounts store, and what is the maximum storage capacity?
- What is the requirement for a rent deposit in SOL for accounts, and how is it related to the amount of data stored?
- If I create a new account but do not store data in this account, should I pay the rent exempt for this account?
- Who can modify the data or deduct the lamport balance of an account, and who is allowed to increase the balance?
- How to query account data on chain ?
Wording
In Solana, the word ==account / authority / mint== is used everywhere. Compare the following words:
- ==owner==: Solana Account Model / Solana Token Account
-
In the solana programing model, each account has its owner.
-
In the solana spl token context, each solana token account has its owner.
Please compare.
- ==authority==: Solana Token Mint / Anchor SPL constraint
-
In the solana spl token context, each individual token mint account has a field called
mint_authority. -
In anchor, there is a constraint like
token::authority = payer.Please compare.
- ==mint==: Solana Token Account / Solana Token Mint
-
In the solana spl token context, each solana token account has a field called
mint. -
In the solana spl token context, each individual token mint account has a field called
mint_authority.Please compare.
Solana Tokens
- Please explain what is the sync native instruction of the token program
- What is the size of a classic token account
- What is the minimum rent exempt for a classic token account
- Please explain the difference between a wSOL token and normal token
- Do native token accounts has rent exempt ?
- Please explain how does tools like https://claimyoursol.com/ works
- What will happen when a token account's balance is reduced to zero during a tranfer instruction? Will the empty account be closed and rent exempt returned?
- What will happen if I trys to close a native account? Under what circumstances will it fail?
- What will happen if I trys to close a non-native account? Under what circumstances will it fail?
- Here is the account structure definition of a solana token account. Please explain what does the field
mintstands for? What is the u64 number of the fieldis_nativestands for?
/// Account data.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Account {
/// The mint associated with this account
pub mint: Pubkey,
/// The owner of this account.
pub owner: Pubkey,
/// The amount of tokens this account holds.
pub **amount**: u64,
/// If `delegate` is `Some` then `**delegated_amount**` represents
/// the amount authorized by the delegate
pub delegate: COption<Pubkey>,
/// The account's state
pub state: AccountState,
/// If is_native.is_some, this is a native token, and the value logs the rent-exempt reserve. An
/// Account is required to be rent-exempt, so the value is used by the Processor to ensure that
/// wrapped SOL accounts do not drop below this threshold.
pub is_native: COption<u64>, // why not bool : the value logs the rent-exempt reserve
/// The amount delegated
pub delegated_amount: u64,
/// Optional authority to close the account.
pub close_authority: COption<Pubkey>,
}
/// Account state.
#[repr(u8)]
#[derive(Clone, Copy, Debug, Default, PartialEq, IntoPrimitive, TryFromPrimitive)]
pub enum AccountState {
/// Account is not yet initialized
#[default]
Uninitialized,
/// Account is initialized; the account owner and/or delegate may perform
/// permitted operations on this account
Initialized,
/// Account has been frozen by the mint freeze authority. Neither the
/// account owner nor the delegate are able to perform operations on
/// this account.
Frozen,
}
- Here is the account structure definition of a solana token mint account. Please explain what does the field
mint_authoritystands for.
/// Mint data.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Mint {
/// Optional authority used to mint new tokens. The mint authority may only be provided during
/// mint creation. If no mint authority is present then the mint has a fixed supply and no
/// further tokens may be minted.
pub **mint_authority**: COption<Pubkey>,
/// **Total supply of tokens.**
pub **supply**: u64,
/// Number of base 10 digits to the right of the decimal place.
pub decimals: u8,
/// Is `true` if this structure has been initialized
pub is_initialized: bool,
/// Optional authority to freeze token accounts.
pub freeze_authority: COption<Pubkey>,
}
- What is the difference between
transferandtransfer_checkedinstruction of the token program?
accounts.push(AccountMeta::new(*source_pubkey, false));
accounts.push(AccountMeta::new(*destination_pubkey, false));
accounts.push(AccountMeta::new_readonly(
*authority_pubkey,
signer_pubkeys.is_empty(),
));
let data = TokenInstruction::Transfer { amount }.pack();
accounts.push(AccountMeta::new(*source_pubkey, false));
accounts.push(AccountMeta::new_readonly(*mint_pubkey, false));
accounts.push(AccountMeta::new(*destination_pubkey, false));
accounts.push(AccountMeta::new_readonly(
*authority_pubkey,
signer_pubkeys.is_empty(),
));
let data = TokenInstruction::TransferChecked { amount, decimals }.pack();
- What's token 2022 ? How do token 2022 extends the original token standard ?
Solana Programs
What is solana native program? What's the difference between normal program and native program?
Please enumerate several solana native progarm.
-
is BPF loader a native program ?
-
is system program (11111111111111111111111111111111) a native program ?
-
is token program a natvie program ?
-
is native loader (NativeLoader1111111111111111111111111111111) a natvie program ?
\
-
What's ebpf ? What's rbpf ? What's sbpf ?
-
What is a transaction ? What is an instruction ?
-
What is account data reloading ? Is it done by anchor automatically ? When should account data be realoaded ?
-
Can solana program call it-self? (self-recursion) Can soalan program call its caller (re-enter) ?
-
How is Call stack depth limited ? How is CPI call depth limited?
Please tell the difference between a Solana program:
- returning an Error (
Result<T, E>) - panics while executing (like DivisionByZero)
————
- Is there a maximum cap for the account number I can pass in to a program invocation ? Or is there any restrictions on the account number / account size I passed in ?
- When deploying a new program, which instructions are called ?
PDA
-
What is pda? What can it do ? Why solana program need pda ?
-
What is the difference between a pda and a normal account ? How can you differentiate a pda from normal account ?
-
What is the seed of a pda? What is the bump seed of a pda ? What is Canonical Bump Seed?
What is the difference between create_program_address and find_program_address functions?
pub fn find_program_address(seeds: &[&[u8]], program_id: &Pubkey) -> (Pubkey, u8)pub fn create_program_address(seeds: &[&[u8]], program_id: &Pubkey) -> Result<Pubkey, PubkeyError>
What's the difference between the following two anchor seed constraint group ?
#[account(
mut,
seeds = [b"12", b"3"],
bump
)]
pub a: Account<'info, NewAccount>,
#[account(
mut,
seeds = [b"1", b"23"],
bump
)]
pub a: Account<'info, NewAccount>,
-
What is Cross Program Invocation ?
-
What is the difference between an instruction in a transaction and CPI ?
-
What is
invoke()? What isinvoke_signed()? What's the difference ?
Anchor
Anchor is an all-on-one solana program development framework. Auditor should be famillar with anchor.
-
What's avm ? What will avm do when switching between different anchor versions ?
-
What happens when you run
anchor build. -
What is the differenct between
solana cargo-build-sbfandanchor build? -
What happens when you run
anchor test. -
What is the minimum size that you should alloc for the following UsdcLedger account ? (Anchor account size)
-
What is the output of
std::mem::size_of<UsdcLedger>()?
use anchor_lang::prelude::*;
#[account]
#[repr(C)]
pub struct UsdcLedger {
pub a: bool,
pub b: u128,
pub c: u8,
pub d: [UsdcHolder; 5],
pub e: Vec<UsdcHolderEnum>, // element number = 5
pub f: Option<String>,
}
#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
#[repr(C)]
pub struct UsdcHolder {
pub address: Pubkey,
pub base_amount: u64,
pub balance: f64,
}
#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
pub enum UsdcHolderEnum {
Usdc(u64),
Jlp(u128),
}
- What is a anchor
has_oneconstraint? What are the final output contraint of these rust attribute marcos?
#[account(mut, has_one = authority)]
pub data: Account<'info, MyData>,
pub authority: Signer<'info>
- Please compare anchor
tokenvsassociate_tokenconstraint. What are the final output contraint of these rust attribute marcos?
#[account(
init,
payer = payer,
token::mint = mint,
token::authority = payer,
)]
pub token: Account<'info, TokenAccount>,
#[account(
init,
payer = payer,
associated_token::mint = mint,
associated_token::authority = payer,
)]
pub token: Account<'info, TokenAccount>,
- What is the difference between
Option<Account<'info, T>>andAccount<'info, T>? If this account should be a None, what should pass in at this account position ?
pub token: Option<Account<'info, TokenAccount>>,
- What is the difference between
Box<Account<'info, T>>andAccount<'info, T>?
⭐ Please distinguish between the following different anchor account types, What are the final output contraint of these types enforced by anchor ?
* Account<'info, T>
* Program<'info, T>
* Signer<'info>
* SystemAccount<'info>
* Sysvar<'info, T>
* Interface<'info, T>
* InterfaceAccount<'info, T>
* UncheckedAccount<'info>
* AccountInfo<'info>
* AccountLoader<'info, T> (what is **Zero-copy deserialization**)
Does anchor AccountLoader::load_mut() check the account owner?
#[derive(Accounts)]
pub struct SetData<'info> {
#[account(mut)]
pub my_account: Account<'info, MyData>,
pub program: Interface<'info, MyProgram>,
pub my_account: InterfaceAccount<'info, MyData>
pub acc: UncheckedAccount<'info>,
pub oracle: AccountInfo<'info>,
pub bar: AccountLoader<'info, Bar>,
}
- What's the difference between Interface and InterfaceAccount? What's the difference between Owner and Owners trait.
- What's the difference between UncheckedAccount and AccountInfo ?
- Please illustrate the data structure layout that is passed into the solana program, which is then deserlized by anchor framework. Following is a short list, what does each field means?
————
- u64 - num_accounts
- num entries:
- u8 - dup_info
- u8 - is_signer
- u8 - is_writable
- u8 - executable
- u32 - original_data_len_offset
- Pubkey - key
- Pubkey - owner
- u64 - lamports
- u64 - data_len
data_len- dataMAX_PERMITTED_DATA_INCREASE- padding- align to 2**8 8个字节对齐
- u64 - rent_epoch
- u64 - instruction_data_len
instruction_data_len- ix data- Pubkey = program_id
————
- What does the following realloc constraint group means ? What are the final output contraint of these
reallocanchor attribute marcos?
#[derive(Accounts)]
#[instruction(len: u32)]
pub struct IncreaseUsdcLedgerCtx<'info> {
#[account(
mut,
realloc = len as usize,
realloc::zero = false,
realloc::payer = signer
)]
pub usdc_holder: AccountLoader<'info, UsdcLedger>,
-
The official solana-program create also has a realloc methold on AccountInfo. What's the difference between anchor realloc constraint group and the
AccountInfo::reallocmethod ? Is there extra checks ? -
Why reallocation over
MAX_PERMITTED_DATA_INCREASEis not allowed ? Please reason about it based on the solana program input parameter layout. -
What is solana sysvar? How do solana sysvars different from Ethereum global variables?
-
Can a solana
program Aaccess other instructions metadata in the transaction that do not interact withprogram A? How ? -
Function Signatures: what is the function selector for the
initializefunction that anchor compiles into ?
#[program]
pub mod defi {
use super::*;
pub fn initialize(ctx: Context<InitializeCtx>) -> Result<()> {
instructions::initialize(ctx)
}
}
- Account Discriminators: What is the account discriminator the anchor stroes in the first 8 bytes of the following account?
#[account(zero_copy(unsafe))]
#[repr(C)]
pub struct JlpLedger {
pub total_base_amount: u64,
...
}
Common Solana Vulnerabilities
Please illustrate the key points on the following common solana pitfalls. Does anchor completely or partially resolve these issues ?
- Account Type Confusion
- Missing Constraint
- Associated Token Account
- Signer
- Integer Overflow / Underflow
- Arbitrary signed program invocation
- Account Reloading
- Account Data Reallocation
- Bump Seed Canonicalization
- Seed Collisions
- Misuse of Anchor's ctx.remaining_accounts
Rust Basics
- If the following rust program compiles, what's its output ? (rust floating point number division)
fn main() {
let res = 1.0 / 0.0;
println!("{res}");
}
- If the following rust program compiles, what's its output ? (rust integer division)
fn main() {
f(1,0);
}
fn f(a: u64, b: u64) {
let res = a / b;
println!("{res}")
}
- What's the difference between debug build & release build? Which build profile does anchor use in default?
- Please explain how should a
Rc<RefCell<T>>type be used and why. For example, here is theAccountInfostruct definition. You can find that bothlamportsanddatafield areRc<RefCell<T>>
/// Account information
#[derive(Clone)]
#[repr(C)]
pub struct AccountInfo<'a> {
/// Public key of the account
pub key: &'a Pubkey,
/// The lamports in the account. Modifiable by programs.
pub lamports: Rc<RefCell<&'a mut u64>>,
/// The data held in this account. Modifiable by programs.
pub data: Rc<RefCell<&'a mut [u8]>>,
/// Program that owns this account
pub **owner**: &'a Pubkey,
/// The epoch at which this account will next owe rent
pub rent_epoch: Epoch,
/// Was the transaction signed by this account's public key?
pub is_signer: bool,
/// Is the account writable?
pub is_writable: bool,
/// This account's data contains a loaded program (and is now read-only)
pub executable: bool,
}
- Please tell the difference between the following two implementation (one uses the trait while the other not)
pub trait JlpHolderMath {
fn flush(&mut self);
}
impl JlpHolderMath for JlpHolder {
fn flush(&mut self) { }
}
impl JlpHolder {
fn flush(&mut self) { }
}