Skip to content

Latest commit

 

History

History
433 lines (282 loc) · 12.2 KB

File metadata and controls

433 lines (282 loc) · 12.2 KB

Rust Solana Analyzer Report

This report was generated by Rust Solana Analyzer, a static analysis tool for Solana smart contracts. This report is not a substitute for manual audit or security review. It should not be relied upon for any purpose other than to assist in the identification of potential security vulnerabilities.

Table of Contents

Summary

Files Summary

Key Value
.rs Files 1
Total Issues 11

Files Details

Filepath Issues
lib.rs 11
Total 11

Issue Summary

Category No. of Issues
High 2
Medium 3
Low 6
Informational 0

High Issues

H-1: Missing Signer Check in 'VulnerableDuplicateMutable'

Detects Anchor account fields that may need signer verification

1 Found Instance
  • Found in lib.rs [Line: 50]

     #[derive(Accounts)]
     pub struct VulnerableDuplicateMutable<'info> {
         /// CHECK: This account is vulnerable to duplicate account attacks
         #[account(mut)]
         pub account1: AccountInfo<'info>,
         
         /// CHECK: This account is vulnerable to duplicate account attacks
         #[account(mut)]
         pub account2: AccountInfo<'info>,
         
         pub authority: Signer<'info>,
     }
Recommendations
  1. Add signer constraint to account fields that should be signed: #[account(signer)]
  2. Use Signer<'info> type for accounts that must be signers of the transaction
  3. Verify account ownership and signer status in instruction logic when needed
  4. Consider using #[account(constraint = account.key() == signer.key())] for explicit signer validation
  5. Review all account fields to ensure proper authorization and access control

H-2: Missing Signer Check in 'TransferFunds'

Detects Anchor account fields that may need signer verification

1 Found Instance
  • Found in lib.rs [Line: 85]

     #[derive(Accounts)]
     pub struct TransferFunds<'info> {
         /// CHECK: The source account != destination account
         #[account(
             mut,
             owner = system_program::ID,
             constraint = source.key() != destination.key() @ ErrorCode::SameAccount
         )]
         pub source: AccountInfo<'info>,
         
         /// CHECK: The destination account is verified by the owner constraint
         #[account(
             mut,
             owner = system_program::ID
         )]
         pub destination: AccountInfo<'info>,
         
         pub authority: Signer<'info>,
         
         pub system_program: Program<'info, System>,
     }
Recommendations
  1. Add signer constraint to account fields that should be signed: #[account(signer)]
  2. Use Signer<'info> type for accounts that must be signers of the transaction
  3. Verify account ownership and signer status in instruction logic when needed
  4. Consider using #[account(constraint = account.key() == signer.key())] for explicit signer validation
  5. Review all account fields to ensure proper authorization and access control

Medium Issues

M-1: Duplicate Mutable Accounts in 'VulnerableDuplicateMutable'

Detects account structs with multiple mutable references to the same account type, which can lead to unexpected behavior

1 Found Instance
  • Found in lib.rs [Line: 50]

     #[derive(Accounts)]
     pub struct VulnerableDuplicateMutable<'info> {
         /// CHECK: This account is vulnerable to duplicate account attacks
         #[account(mut)]
         pub account1: AccountInfo<'info>,
         
         /// CHECK: This account is vulnerable to duplicate account attacks
         #[account(mut)]
         pub account2: AccountInfo<'info>,
         
         pub authority: Signer<'info>,
     }
Recommendations
  1. Add constraints to ensure accounts are different: #[account(constraint = account1.key() != account2.key())]
  2. Use a single mutable account reference instead of multiple ones when possible
  3. Implement explicit validation in your instruction handler to prevent the same account being passed multiple times
  4. Consider using Anchor's constraint system to enforce account uniqueness at the framework level

M-2: Owner Check Validation in 'TransferFunds'

Detects structs that properly implement owner checks for account validation

1 Found Instance
  • Found in lib.rs [Line: 85]

     #[derive(Accounts)]
     pub struct TransferFunds<'info> {
         /// CHECK: The source account != destination account
         #[account(
             mut,
             owner = system_program::ID,
             constraint = source.key() != destination.key() @ ErrorCode::SameAccount
         )]
         pub source: AccountInfo<'info>,
         
         /// CHECK: The destination account is verified by the owner constraint
         #[account(
             mut,
             owner = system_program::ID
         )]
         pub destination: AccountInfo<'info>,
         
         pub authority: Signer<'info>,
         
         pub system_program: Program<'info, System>,
     }
Recommendations
  1. Add explicit owner validation in your account struct using #[account(constraint = account.owner == expected_owner)] or similar patterns
  2. Use Anchor's built-in Account<'info, T> wrapper which automatically validates the account owner
  3. Implement manual owner checks in your instruction handler before processing the account
  4. Consider using Anchor's #[account(owner = program_id)] constraint for program-owned accounts

M-3: Division Without Zero Check in 'vulnerable_division'

Detects division operations without zero verification

1 Found Instance
  • Found in lib.rs [Line: 38]

     pub fn vulnerable_division(ctx: Context<Initialize>, divisor: u64) -> Result<()> {
             //TODO
             let a = 100;
             let _result = a / divisor;
             
             Ok(())
         }
Recommendations
  1. Add explicit zero checks before division operations: if divisor == 0 { return Err(...) }
  2. Use checked division methods: checked_div() which returns Option
  3. Implement proper error handling for division by zero cases
  4. Consider using safe arithmetic operations provided by Anchor or custom error types
  5. Validate input parameters at the beginning of instruction handlers

Low Issues

L-1: Anchor Instructions Detection in 'vulnerable_division'

Detects functions that are Anchor program instructions (public functions with Context parameter)

1 Found Instance
  • Found in lib.rs [Line: 38]

     pub fn vulnerable_division(ctx: Context<Initialize>, divisor: u64) -> Result<()> {
             //TODO
             let a = 100;
             let _result = a / divisor;
             
             Ok(())
         }
Recommendations
  1. Ensure all instruction handlers return Result<()> for proper error handling
  2. Add proper account validation using constraints in your Context struct
  3. Consider adding access control checks at the beginning of instruction handlers
  4. Use #[access_control] attribute for complex authorization logic
  5. Document instruction parameters and expected account states

L-2: Anchor Instructions Detection in 'vulnerable_duplicate_accounts'

Detects functions that are Anchor program instructions (public functions with Context parameter)

1 Found Instance
  • Found in lib.rs [Line: 63]

     pub fn vulnerable_duplicate_accounts(ctx: Context<VulnerableDuplicateMutable>) -> Result<()> {
         **ctx.accounts.account1.lamports.borrow_mut() -= 100;
         **ctx.accounts.account2.lamports.borrow_mut() += 100;
     
         Ok(())
     }
Recommendations
  1. Ensure all instruction handlers return Result<()> for proper error handling
  2. Add proper account validation using constraints in your Context struct
  3. Consider adding access control checks at the beginning of instruction handlers
  4. Use #[access_control] attribute for complex authorization logic
  5. Document instruction parameters and expected account states

L-3: Anchor Instructions Detection in 'initialize'

Detects functions that are Anchor program instructions (public functions with Context parameter)

1 Found Instance
  • Found in lib.rs [Line: 18]

     pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
             msg!("Greetings from: {:?}", ctx.program_id);
             Ok(())
         }
Recommendations
  1. Ensure all instruction handlers return Result<()> for proper error handling
  2. Add proper account validation using constraints in your Context struct
  3. Consider adding access control checks at the beginning of instruction handlers
  4. Use #[access_control] attribute for complex authorization logic
  5. Document instruction parameters and expected account states

L-4: Missing Error Handling in Public Functions in 'validate_account_name'

Detects public functions that don't return Result and may fail silently. In Solana contracts, proper error handling is essential for security and debugging.

1 Found Instance
  • Found in lib.rs [Line: 77]

     pub fn validate_account_name(name: String) {
         // This function performs validation but doesn't return Result
         if name.len() > 32 {
             panic!("Name too long");  // Bad error handling
         }
         println!("Account name is valid: {}", name);
     }
Recommendations
  1. Change function return type to Result<T, YourErrorType> to handle potential failures
  2. Use Anchor's Result<()> for instruction handlers to properly propagate errors
  3. Implement custom error types using #[error_code] for better error reporting
  4. Add proper error handling with ? operator or explicit error returns
  5. Consider using anchor_lang::Result for Anchor-specific error handling

L-5: Missing Error Handling in Public Functions in 'calculate_fee'

Detects public functions that don't return Result and may fail silently. In Solana contracts, proper error handling is essential for security and debugging.

1 Found Instance
  • Found in lib.rs [Line: 71]

     pub fn calculate_fee(amount: u64) -> u64 {
         // This function could fail but doesn't return Result
         amount * 5 / 100  // Could panic on overflow
     }
Recommendations
  1. Change function return type to Result<T, YourErrorType> to handle potential failures
  2. Use Anchor's Result<()> for instruction handlers to properly propagate errors
  3. Implement custom error types using #[error_code] for better error reporting
  4. Add proper error handling with ? operator or explicit error returns
  5. Consider using anchor_lang::Result for Anchor-specific error handling

L-6: Anchor Instructions Detection in 'transfer_funds'

Detects functions that are Anchor program instructions (public functions with Context parameter)

1 Found Instance
  • Found in lib.rs [Line: 23]

     pub fn transfer_funds(ctx: Context<TransferFunds>, amount: u64) -> Result<()> {
             if **ctx.accounts.source.lamports.borrow() < amount {
                 return Err(error!(ErrorCode::InsufficientFunds));
             }
             
             **ctx.accounts.source.lamports.borrow_mut() -= amount;
             **ctx.accounts.destination.lamports.borrow_mut() += amount;
             
             let x = 200;
             let y = 2;
             let _result = x / y; 
             
             Ok(())
         }
Recommendations
  1. Ensure all instruction handlers return Result<()> for proper error handling
  2. Add proper account validation using constraints in your Context struct
  3. Consider adding access control checks at the beginning of instruction handlers
  4. Use #[access_control] attribute for complex authorization logic
  5. Document instruction parameters and expected account states