Skip to content

Commit

Permalink
✅ update fuzz_example3
Browse files Browse the repository at this point in the history
  • Loading branch information
lukacan committed Feb 15, 2024
1 parent 86b0af2 commit 0c78cf1
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 106 deletions.
27 changes: 25 additions & 2 deletions examples/fuzz_example3/Trdelnik.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,33 @@
validator_startup_timeout = 15000


# set for default values
[fuzz]
# Timeout in seconds (default: 10)
timeout = 10
iterations = 5000
# Number of fuzzing iterations (default: 0 [no limit])
iterations = 2000
# Number of concurrent fuzzing threads (default: 0 [number of CPUs / 2])
threads = 0
# Don't close children's stdin, stdout, stderr; can be noisy (default: false)
keep_output = false
# Disable ANSI console; use simple log output (default: false)
verbose = false
# Exit upon seeing the first crash (default: false)
exit_upon_crash = true
# Maximal number of mutations per one run (default: 6)
mutations_per_run = 6
# Target compilation directory, (default: "" ["trdelnik-tests/fuzz_tests/fuzzing/hfuzz_target"]).
# To not clash with cargo build's default target directory.
cargo_target_dir = ""
# Honggfuzz working directory, (default: "" ["trdelnik-tests/fuzz_tests/fuzzing/hfuzz_workspace"]).
hfuzz_workspace = ""
# Directory where crashes are saved to (default: "" [workspace directory])
crashdir = ""
# Input file extension (e.g. 'swf'), (default: "" ['fuzz'])
extension = ""
# Number of seconds this fuzzing session will last (default: 0 [no limit])
run_time = 0
# Maximal size of files processed by the fuzzer in bytes (default: 1048576 = 1MB)
max_file_size = 1048576
# Save all test-cases (not only the unique ones) by appending the current time-stamp to the filenames (default: false)
save_all = false
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
use anchor_spl::token::{Mint, Token, TokenAccount};
use fuzz_example3::state::Escrow;
use program_client::fuzz_example3_instruction::PROGRAM_ID;
use trdelnik_client::anchor_lang::solana_program::instruction::AccountMeta;
use trdelnik_client::anchor_lang::{self, prelude::*};
use trdelnik_client::fuzzing::{get_account_infos_option, FuzzingError};

pub struct InitVestingSnapshot<'info> {
pub sender: Option<Signer<'info>>,
pub sender_token_account: Option<Account<'info, TokenAccount>>,
pub sender: Signer<'info>,
pub sender_token_account: Account<'info, TokenAccount>,
pub escrow: Option<Account<'info, Escrow>>,
pub escrow_token_account: Option<Account<'info, TokenAccount>>,
pub mint: Option<Account<'info, Mint>>,
pub token_program: Option<Program<'info, Token>>,
pub system_program: Option<Program<'info, System>>,
pub escrow_token_account: Account<'info, TokenAccount>,
pub mint: Account<'info, Mint>,
pub token_program: Program<'info, Token>,
pub system_program: Program<'info, System>,
}
pub struct WithdrawUnlockedSnapshot<'info> {
pub recipient: Option<Signer<'info>>,
pub recipient_token_account: Option<Account<'info, TokenAccount>>,
pub recipient: Signer<'info>,
pub recipient_token_account: Account<'info, TokenAccount>,
pub escrow: Option<Account<'info, Escrow>>,
pub escrow_token_account: Option<Account<'info, TokenAccount>>,
pub escrow_pda_authority: Option<AccountInfo<'info>>,
pub mint: Option<Account<'info, Mint>>,
pub token_program: Option<Program<'info, Token>>,
pub system_program: Option<Program<'info, System>>,
pub escrow_token_account: Account<'info, TokenAccount>,
pub escrow_pda_authority: AccountInfo<'info>,
pub mint: Account<'info, Mint>,
pub token_program: Program<'info, Token>,
pub system_program: Program<'info, System>,
}
impl<'info> InitVestingSnapshot<'info> {
pub fn deserialize_option(
Expand All @@ -31,55 +31,73 @@ impl<'info> InitVestingSnapshot<'info> {
let accounts = get_account_infos_option(accounts, metas)
.map_err(|_| FuzzingError::NotAbleToObtainAccountInfos)?;
let mut accounts_iter = accounts.into_iter();

let sender: Option<Signer<'_>> = accounts_iter
let sender: Signer<'_> = accounts_iter
.next()
.ok_or(FuzzingError::DeserializeError("sender".to_string()))?
.ok_or(FuzzingError::NotEnoughAccounts("sender".to_string()))?
.map(|acc| anchor_lang::accounts::signer::Signer::try_from(&acc))
.transpose()
.unwrap_or(None);
let sender_token_account: Option<anchor_lang::accounts::account::Account<TokenAccount>> =
.ok_or(FuzzingError::AccountNotFound("sender".to_string()))?
.map_err(|_| FuzzingError::CannotDeserializeAccount("sender".to_string()))?;
let sender_token_account: anchor_lang::accounts::account::Account<TokenAccount> =
accounts_iter
.next()
.ok_or(FuzzingError::DeserializeError(
.ok_or(FuzzingError::NotEnoughAccounts(
"sender_token_account".to_string(),
))?
.map(|acc| anchor_lang::accounts::account::Account::try_from(&acc))
.transpose()
.unwrap_or(None);
.ok_or(FuzzingError::AccountNotFound(
"sender_token_account".to_string(),
))?
.map_err(|_| {
FuzzingError::CannotDeserializeAccount("sender_token_account".to_string())
})?;
let escrow: Option<anchor_lang::accounts::account::Account<Escrow>> = accounts_iter
.next()
.ok_or(FuzzingError::DeserializeError("escrow".to_string()))?
.map(|acc| anchor_lang::accounts::account::Account::try_from(&acc))
.ok_or(FuzzingError::NotEnoughAccounts("escrow".to_string()))?
.map(|acc| {
if acc.key() != PROGRAM_ID {
anchor_lang::accounts::account::Account::try_from(&acc)
.map_err(|_| FuzzingError::CannotDeserializeAccount("escrow".to_string()))
} else {
Err(FuzzingError::OptionalAccountNotProvided(
"escrow".to_string(),
))
}
})
.transpose()
.unwrap_or(None);
let escrow_token_account: Option<anchor_lang::accounts::account::Account<TokenAccount>> =
let escrow_token_account: anchor_lang::accounts::account::Account<TokenAccount> =
accounts_iter
.next()
.ok_or(FuzzingError::DeserializeError(
.ok_or(FuzzingError::NotEnoughAccounts(
"escrow_token_account".to_string(),
))?
.map(|acc| anchor_lang::accounts::account::Account::try_from(&acc))
.transpose()
.unwrap_or(None);
let mint: Option<anchor_lang::accounts::account::Account<Mint>> = accounts_iter
.ok_or(FuzzingError::AccountNotFound(
"escrow_token_account".to_string(),
))?
.map_err(|_| {
FuzzingError::CannotDeserializeAccount("escrow_token_account".to_string())
})?;
let mint: anchor_lang::accounts::account::Account<Mint> = accounts_iter
.next()
.ok_or(FuzzingError::DeserializeError("mint".to_string()))?
.ok_or(FuzzingError::NotEnoughAccounts("mint".to_string()))?
.map(|acc| anchor_lang::accounts::account::Account::try_from(&acc))
.transpose()
.unwrap_or(None);
let token_program: Option<anchor_lang::accounts::program::Program<Token>> = accounts_iter
.ok_or(FuzzingError::AccountNotFound("mint".to_string()))?
.map_err(|_| FuzzingError::CannotDeserializeAccount("mint".to_string()))?;
let token_program: anchor_lang::accounts::program::Program<Token> = accounts_iter
.next()
.ok_or(FuzzingError::DeserializeError("token_program".to_string()))?
.ok_or(FuzzingError::NotEnoughAccounts("token_program".to_string()))?
.map(|acc| anchor_lang::accounts::program::Program::try_from(&acc))
.transpose()
.unwrap_or(None);
let system_program: Option<anchor_lang::accounts::program::Program<System>> = accounts_iter
.ok_or(FuzzingError::AccountNotFound("token_program".to_string()))?
.map_err(|_| FuzzingError::CannotDeserializeAccount("token_program".to_string()))?;
let system_program: anchor_lang::accounts::program::Program<System> = accounts_iter
.next()
.ok_or(FuzzingError::DeserializeError("system_program".to_string()))?
.ok_or(FuzzingError::NotEnoughAccounts(
"system_program".to_string(),
))?
.map(|acc| anchor_lang::accounts::program::Program::try_from(&acc))
.transpose()
.unwrap_or(None);
.ok_or(FuzzingError::AccountNotFound("system_program".to_string()))?
.map_err(|_| FuzzingError::CannotDeserializeAccount("system_program".to_string()))?;
Ok(Self {
sender,
sender_token_account,
Expand All @@ -99,57 +117,81 @@ impl<'info> WithdrawUnlockedSnapshot<'info> {
let accounts = get_account_infos_option(accounts, metas)
.map_err(|_| FuzzingError::NotAbleToObtainAccountInfos)?;
let mut accounts_iter = accounts.into_iter();
let recipient: Option<Signer<'_>> = accounts_iter
let recipient: Signer<'_> = accounts_iter
.next()
.ok_or(FuzzingError::DeserializeError("recipient".to_string()))?
.ok_or(FuzzingError::NotEnoughAccounts("recipient".to_string()))?
.map(|acc| anchor_lang::accounts::signer::Signer::try_from(&acc))
.transpose()
.unwrap_or(None);
let recipient_token_account: Option<anchor_lang::accounts::account::Account<TokenAccount>> =
.ok_or(FuzzingError::AccountNotFound("recipient".to_string()))?
.map_err(|_| FuzzingError::CannotDeserializeAccount("recipient".to_string()))?;
let recipient_token_account: anchor_lang::accounts::account::Account<TokenAccount> =
accounts_iter
.next()
.ok_or(FuzzingError::DeserializeError(
.ok_or(FuzzingError::NotEnoughAccounts(
"recipient_token_account".to_string(),
))?
.map(|acc| anchor_lang::accounts::account::Account::try_from(&acc))
.transpose()
.unwrap_or(None);
.ok_or(FuzzingError::AccountNotFound(
"recipient_token_account".to_string(),
))?
.map_err(|_| {
FuzzingError::CannotDeserializeAccount("recipient_token_account".to_string())
})?;
let escrow: Option<anchor_lang::accounts::account::Account<Escrow>> = accounts_iter
.next()
.ok_or(FuzzingError::DeserializeError("escrow".to_string()))?
.map(|acc| anchor_lang::accounts::account::Account::try_from(&acc))
.ok_or(FuzzingError::NotEnoughAccounts("escrow".to_string()))?
.map(|acc| {
if acc.key() != PROGRAM_ID {
anchor_lang::accounts::account::Account::try_from(&acc)
.map_err(|_| FuzzingError::CannotDeserializeAccount("escrow".to_string()))
} else {
Err(FuzzingError::OptionalAccountNotProvided(
"escrow".to_string(),
))
}
})
.transpose()
.unwrap_or(None);
let escrow_token_account: Option<anchor_lang::accounts::account::Account<TokenAccount>> =
let escrow_token_account: anchor_lang::accounts::account::Account<TokenAccount> =
accounts_iter
.next()
.ok_or(FuzzingError::DeserializeError(
.ok_or(FuzzingError::NotEnoughAccounts(
"escrow_token_account".to_string(),
))?
.map(|acc| anchor_lang::accounts::account::Account::try_from(&acc))
.transpose()
.unwrap_or(None);
let escrow_pda_authority = accounts_iter.next().ok_or(FuzzingError::DeserializeError(
"escrow_pda_authority".to_string(),
))?;
let mint: Option<anchor_lang::accounts::account::Account<Mint>> = accounts_iter
.ok_or(FuzzingError::AccountNotFound(
"escrow_token_account".to_string(),
))?
.map_err(|_| {
FuzzingError::CannotDeserializeAccount("escrow_token_account".to_string())
})?;
let escrow_pda_authority = accounts_iter
.next()
.ok_or(FuzzingError::NotEnoughAccounts(
"escrow_pda_authority".to_string(),
))?
.ok_or(FuzzingError::AccountNotFound(
"escrow_pda_authority".to_string(),
))?;
let mint: anchor_lang::accounts::account::Account<Mint> = accounts_iter
.next()
.ok_or(FuzzingError::DeserializeError("mint".to_string()))?
.ok_or(FuzzingError::NotEnoughAccounts("mint".to_string()))?
.map(|acc| anchor_lang::accounts::account::Account::try_from(&acc))
.transpose()
.unwrap_or(None);
let token_program: Option<anchor_lang::accounts::program::Program<Token>> = accounts_iter
.ok_or(FuzzingError::AccountNotFound("mint".to_string()))?
.map_err(|_| FuzzingError::CannotDeserializeAccount("mint".to_string()))?;
let token_program: anchor_lang::accounts::program::Program<Token> = accounts_iter
.next()
.ok_or(FuzzingError::DeserializeError("token_program".to_string()))?
.ok_or(FuzzingError::NotEnoughAccounts("token_program".to_string()))?
.map(|acc| anchor_lang::accounts::program::Program::try_from(&acc))
.transpose()
.unwrap_or(None);
let system_program: Option<anchor_lang::accounts::program::Program<System>> = accounts_iter
.ok_or(FuzzingError::AccountNotFound("token_program".to_string()))?
.map_err(|_| FuzzingError::CannotDeserializeAccount("token_program".to_string()))?;
let system_program: anchor_lang::accounts::program::Program<System> = accounts_iter
.next()
.ok_or(FuzzingError::DeserializeError("system_program".to_string()))?
.ok_or(FuzzingError::NotEnoughAccounts(
"system_program".to_string(),
))?
.map(|acc| anchor_lang::accounts::program::Program::try_from(&acc))
.transpose()
.unwrap_or(None);
.ok_or(FuzzingError::AccountNotFound("system_program".to_string()))?
.map_err(|_| FuzzingError::CannotDeserializeAccount("system_program".to_string()))?;
Ok(Self {
recipient,
recipient_token_account,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,6 @@ pub mod fuzz_example3_fuzz_instructions {
}
.to_account_metas(None);

// let sender_only = &acc_meta[0];
// Ok((vec![sender], vec![sender_only.clone()]))
Ok((vec![sender], acc_meta))
}
}
Expand Down Expand Up @@ -251,38 +249,34 @@ pub mod fuzz_example3_fuzz_instructions {
_ix_data: Self::IxData,
) -> Result<(), FuzzingError> {
if let Some(escrow) = pre_ix.escrow {
let recipient = pre_ix.recipient.unwrap();
if let Some(recipient_token_account_pre) = pre_ix.recipient_token_account {
if let Some(recipient_token_account_post) = post_ix.recipient_token_account {
if escrow.recipient == *recipient.key {
if recipient_token_account_pre.amount
== recipient_token_account_post.amount
{
// INFO Recipient was not able to withdraw
// return Err("Recipient was not able to withdraw any funds");
return Err(FuzzingError::BalanceMismatch);
} else if recipient_token_account_pre.amount + escrow.amount
!= recipient_token_account_post.amount
{
if recipient_token_account_pre.amount + escrow.amount
> recipient_token_account_post.amount
{
// INFO The recipient was able to withdraw,
// but not as much as was initially intended.
// return Err("Recipient withdrew LESS");
return Err(FuzzingError::Custom(15));
} else {
// INFO The recipient was able to withdraw,
// but more as was initially intended.
// This option is possible because the program uses one token accout with corresponding mint
// across multiple Escrow Transactions, this means that we can actually withdraw more
// if prior to Withdraw call, was sufficient amount transferred to the escrow token account.
// (e.g. due to prior Initialization of different Escrow Transactions)
// For testing purposes inside debug use eprintln!()
// return Err("Recipient withdrew MORE");
return Err(FuzzingError::Custom(2));
}
}
let recipient = pre_ix.recipient;
let recipient_token_account_pre = pre_ix.recipient_token_account;
let recipient_token_account_post = post_ix.recipient_token_account;
if escrow.recipient == *recipient.key {
if recipient_token_account_pre.amount == recipient_token_account_post.amount {
// INFO Recipient was not able to withdraw
// return Err("Recipient was not able to withdraw any funds");
return Err(FuzzingError::BalanceMismatch);
} else if recipient_token_account_pre.amount + escrow.amount
!= recipient_token_account_post.amount
{
if recipient_token_account_pre.amount + escrow.amount
> recipient_token_account_post.amount
{
// INFO The recipient was able to withdraw,
// but not as much as was initially intended.
// return Err("Recipient withdrew LESS");
return Err(FuzzingError::Custom(15));
} else {
// INFO The recipient was able to withdraw,
// but more as was initially intended.
// This option is possible because the program uses one token accout with corresponding mint
// across multiple Escrow Transactions, this means that we can actually withdraw more
// if prior to Withdraw call, was sufficient amount transferred to the escrow token account.
// (e.g. due to prior Initialization of different Escrow Transactions)
// For testing purposes inside debug use eprintln!()
// return Err("Recipient withdrew MORE");
return Err(FuzzingError::Custom(2));
}
}
}
Expand Down

0 comments on commit 0c78cf1

Please sign in to comment.