Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 118 additions & 31 deletions program/src/entrypoint-runtime-verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1168,7 +1168,7 @@ fn test_process_initialize_multisig(
let instruction_data: &[u8; 1] = instruction_data.last_chunk().unwrap();

// ^ FIXME: totally arbitrary for the tests
// cheatcode_is_spl_multisig(&accounts[0]);
cheatcode_is_spl_multisig(&accounts[0]);
cheatcode_is_spl_rent(&accounts[1]);
Comment on lines -1171 to 1172
Copy link
Collaborator

@dkcumming dkcumming Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should cheatcode_is_spl_multisig be uncommented? Not sure just wondering

cheatcode_is_spl_account(&accounts[2]); // Signer
cheatcode_is_spl_account(&accounts[3]); // Signer
Expand Down Expand Up @@ -1329,7 +1329,7 @@ fn test_process_mint_to_checked_multisig(
} else if amount == 0 && accounts[1].owner != &crate::id() {
assert_eq!(result, Err(ProgramError::IncorrectProgramId));
return result;
} else if amount != 0 && u64::MAX - amount < initial_supply {
} else if amount != 0 && amount.checked_add(initial_supply).is_none() {
assert_eq!(result, Err(ProgramError::Custom(14)));
return result;
}
Expand Down Expand Up @@ -1508,6 +1508,12 @@ fn test_process_transfer(
let old_src_delgated_amount = get_account(&accounts[0]).delegated_amount();
let maybe_multisig_is_initialised = None;

#[cfg(feature = "assumptions")]
// Avoid potential overflow in destination account; assuming total supply stays within u64
if accounts[0].key != accounts[1].key && dst_initial_amount.checked_add(amount).is_none() {
return Err(ProgramError::Custom(99));
}

//-Process Instruction-----------------------------------------------------
let result = Processor::process(program_id, accounts, instruction_data_with_discriminator);

Expand Down Expand Up @@ -1576,11 +1582,15 @@ fn test_process_transfer(
// Not sure how to fund native mint
assert_eq!(result, Err(ProgramError::Custom(14)));
return result;
} else if accounts[0].key != accounts[1].key && amount != 0 && get_account(&accounts[0]).is_native() && u64::MAX - amount < dst_initial_lamports {
} else if accounts[0].key != accounts[1].key && amount != 0 && get_account(&accounts[0]).is_native() && dst_initial_lamports.checked_add(amount).is_none() {
// Not sure how to fund native mint
assert_eq!(result, Err(ProgramError::Custom(14)));
return result;
} else if accounts[0].key != accounts[1].key && amount != 0 {
}

assert!(result.is_ok());

if accounts[0].key != accounts[1].key && amount != 0 {
assert_eq!(get_account(&accounts[0]).amount(), src_initial_amount - amount);
assert_eq!(get_account(&accounts[1]).amount(), dst_initial_amount + amount);

Expand All @@ -1590,8 +1600,6 @@ fn test_process_transfer(
}
}

assert!(result.is_ok());

// Delegate updates
if old_src_delgate == Some(*accounts[2].key) && accounts[0].key != accounts[1].key {
assert_eq!(get_account(&accounts[0]).delegated_amount(), old_src_delgated_amount - amount);
Expand Down Expand Up @@ -1715,7 +1723,7 @@ fn test_process_transfer_multisig(
// Not sure how to fund native mint
assert_eq!(result, Err(ProgramError::Custom(14)));
return result;
} else if accounts[0].key != accounts[1].key && amount != 0 && get_account(&accounts[0]).is_native() && u64::MAX - amount < dst_initial_lamports {
} else if accounts[0].key != accounts[1].key && amount != 0 && get_account(&accounts[0]).is_native() && dst_initial_lamports.checked_add(amount).is_none() {
// Not sure how to fund native mint
assert_eq!(result, Err(ProgramError::Custom(14)));
return result;
Expand Down Expand Up @@ -1887,7 +1895,7 @@ fn test_process_transfer_checked_multisig(
// Not sure how to fund native mint
assert_eq!(result, Err(ProgramError::Custom(14)));
return result;
} else if src_new.is_native() && u64::MAX - amount < dst_initial_lamports {
} else if src_new.is_native() && dst_initial_lamports.checked_add(amount).is_none() {
// Not sure how to fund native mint
assert_eq!(result, Err(ProgramError::Custom(14)));
return result;
Expand Down Expand Up @@ -2794,6 +2802,26 @@ fn test_process_mint_to(
let dst_init_state = get_account(&accounts[1]).account_state();
let maybe_multisig_is_initialised = None;

#[cfg(feature = "assumptions")]
{
// Skip cases that would overflow the destination balance assuming total supply fits in u64
let amount =
u64::from_le_bytes([instruction_data[0], instruction_data[1], instruction_data[2], instruction_data[3], instruction_data[4], instruction_data[5], instruction_data[6], instruction_data[7]]);
if initial_amount.checked_add(amount).is_none() {
return Err(ProgramError::Custom(99));
}
}

#[cfg(feature = "assumptions")]
{
// Skip cases that would overflow the destination balance assuming total supply fits in u64
let amount =
u64::from_le_bytes([instruction_data[0], instruction_data[1], instruction_data[2], instruction_data[3], instruction_data[4], instruction_data[5], instruction_data[6], instruction_data[7]]);
if initial_amount.checked_add(amount).is_none() {
return Err(ProgramError::Custom(99));
}
}
Comment on lines +2805 to +2823
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicated?

Suggested change
#[cfg(feature = "assumptions")]
{
// Skip cases that would overflow the destination balance assuming total supply fits in u64
let amount =
u64::from_le_bytes([instruction_data[0], instruction_data[1], instruction_data[2], instruction_data[3], instruction_data[4], instruction_data[5], instruction_data[6], instruction_data[7]]);
if initial_amount.checked_add(amount).is_none() {
return Err(ProgramError::Custom(99));
}
}
#[cfg(feature = "assumptions")]
{
// Skip cases that would overflow the destination balance assuming total supply fits in u64
let amount =
u64::from_le_bytes([instruction_data[0], instruction_data[1], instruction_data[2], instruction_data[3], instruction_data[4], instruction_data[5], instruction_data[6], instruction_data[7]]);
if initial_amount.checked_add(amount).is_none() {
return Err(ProgramError::Custom(99));
}
}
#[cfg(feature = "assumptions")]
{
// Skip cases that would overflow the destination balance assuming total supply fits in u64
let amount =
u64::from_le_bytes([instruction_data[0], instruction_data[1], instruction_data[2], instruction_data[3], instruction_data[4], instruction_data[5], instruction_data[6], instruction_data[7]]);
if initial_amount.checked_add(amount).is_none() {
return Err(ProgramError::Custom(99));
}
}


//-Process Instruction-----------------------------------------------------
let result = Processor::process(program_id, accounts, instruction_data_with_discriminator);

Expand Down Expand Up @@ -2854,7 +2882,7 @@ fn test_process_mint_to(
} else if amount == 0 && accounts[1].owner != &crate::id() {
assert_eq!(result, Err(ProgramError::IncorrectProgramId));
return result;
} else if amount != 0 && u64::MAX - amount < initial_supply {
} else if amount != 0 && amount.checked_add(initial_supply).is_none() {
assert_eq!(result, Err(ProgramError::Custom(14)));
return result;
}
Expand Down Expand Up @@ -2966,7 +2994,7 @@ fn test_process_mint_to_multisig(
} else if amount == 0 && accounts[1].owner != &crate::id() {
assert_eq!(result, Err(ProgramError::IncorrectProgramId));
return result;
} else if amount != 0 && u64::MAX - amount < initial_supply {
} else if amount != 0 && amount.checked_add(initial_supply).is_none() {
assert_eq!(result, Err(ProgramError::Custom(14)));
return result;
}
Expand Down Expand Up @@ -3027,6 +3055,12 @@ fn test_process_burn(
let maybe_multisig_is_initialised = None;
let tx_signers: &[AccountInfo] = &accounts[3..];

#[cfg(feature = "assumptions")]
// Assume balances stay within u64 so processing cannot overflow
if !(src_init_amount <= mint_init_supply && old_src_delgated_amount <= src_init_amount) {
return Err(ProgramError::Custom(99));
}

//-Process Instruction-----------------------------------------------------
let result = Processor::process(program_id, accounts, instruction_data_with_discriminator);

Expand Down Expand Up @@ -3178,7 +3212,7 @@ fn test_process_close_account(
} else if accounts[1].key != &INCINERATOR_ID {
assert_eq!(result, Err(ProgramError::InvalidAccountData));
return result;
} else if u64::MAX - dst_init_lamports < src_init_lamports {
} else if dst_init_lamports.checked_add(src_init_lamports).is_none() {
assert_eq!(result, Err(ProgramError::Custom(14)));
return result;
}
Expand Down Expand Up @@ -3268,7 +3302,7 @@ fn test_process_close_account_multisig(
} else if accounts[1].key != &INCINERATOR_ID {
assert_eq!(result, Err(ProgramError::InvalidAccountData));
return result;
} else if u64::MAX - dst_init_lamports < src_init_lamports {
} else if dst_init_lamports.checked_add(src_init_lamports).is_none() {
assert_eq!(result, Err(ProgramError::Custom(14)));
return result;
}
Expand Down Expand Up @@ -3662,6 +3696,12 @@ fn test_process_transfer_checked(
&[]
};

#[cfg(feature = "assumptions")]
// Avoid potential overflow in destination account; assuming total supply stays within u64
if accounts[0].key != accounts[2].key && dst_initial_amount.checked_add(amount).is_none() {
return Err(ProgramError::Custom(99));
}

//-Process Instruction-----------------------------------------------------
let result = Processor::process(program_id, accounts, instruction_data_with_discriminator);

Expand Down Expand Up @@ -3741,12 +3781,18 @@ fn test_process_transfer_checked(
} else if (accounts[0].key == accounts[2].key || amount == 0) && accounts[2].owner != &crate::id() {
assert_eq!(result, Err(ProgramError::IncorrectProgramId));
return result;
} else if accounts[0].key != accounts[2].key && amount != 0 {
}

assert!(result.is_ok());

if accounts[0].key != accounts[2].key && amount != 0 {
if get_account(&accounts[0]).is_native() && src_initial_lamports < amount {
// Not sure how to fund native mint
assert_eq!(result, Err(ProgramError::Custom(14)));
return result;
} else if get_account(&accounts[0]).is_native() && u64::MAX - amount < dst_initial_lamports {
} else if get_account(&accounts[0]).is_native()
&& dst_initial_lamports.checked_add(amount).is_none()
{
// Not sure how to fund native mint
assert_eq!(result, Err(ProgramError::Custom(14)));
return result;
Expand All @@ -3761,7 +3807,6 @@ fn test_process_transfer_checked(
}
}

assert!(result.is_ok());
// Delegate updates
if old_src_delgate == Some(*accounts[3].key) && accounts[0].key != accounts[2].key {
assert_eq!(get_account(&accounts[0]).delegated_amount(), old_src_delgated_amount - amount);
Expand Down Expand Up @@ -3959,7 +4004,7 @@ fn test_process_mint_to_checked(
} else if amount == 0 && accounts[1].owner != &crate::id() {
assert_eq!(result, Err(ProgramError::IncorrectProgramId));
return result;
} else if amount != 0 && u64::MAX - amount < initial_supply {
} else if amount != 0 && amount.checked_add(initial_supply).is_none() {
assert_eq!(result, Err(ProgramError::Custom(14)));
return result;
}
Expand Down Expand Up @@ -4020,6 +4065,12 @@ fn test_process_burn_checked(
let maybe_multisig_is_initialised = None;
let tx_signers: &[AccountInfo] = &accounts[3..];

#[cfg(feature = "assumptions")]
// Assume balances stay within u64 so processing cannot overflow
if !(src_init_amount <= mint_init_supply && old_src_delgated_amount <= src_init_amount) {
return Err(ProgramError::Custom(99));
}

//-Process Instruction-----------------------------------------------------
let result = Processor::process(program_id, accounts, instruction_data_with_discriminator);

Expand Down Expand Up @@ -4121,7 +4172,7 @@ fn test_process_withdraw_excess_lamports_multisig_multisig(
let instruction_data_with_discriminator = &instruction_data.clone();
let instruction_data: &[u8; 0] = instruction_data.last_chunk().unwrap();

// cheatcode_is_spl_multisig(&accounts[0]); // Source Account (Multisig)
cheatcode_is_spl_multisig(&accounts[0]); // Source Account (Multisig)
cheatcode_is_spl_account(&accounts[1]); // Destination
cheatcode_is_spl_multisig(&accounts[2]); // Authority

Expand Down Expand Up @@ -4158,13 +4209,19 @@ fn test_process_withdraw_excess_lamports_multisig_multisig(
if src_init_lamports < minimum_balance {
assert_eq!(result, Err(ProgramError::Custom(0)));
return result;
} else if u64::MAX - src_init_lamports + minimum_balance < dst_init_lamports {
} else if dst_init_lamports
.checked_add(src_init_lamports - minimum_balance)
.is_none()
{
assert_eq!(result, Err(ProgramError::Custom(0)));
return result;
}

assert_eq!(accounts[0].lamports(), minimum_balance);
assert_eq!(accounts[1].lamports(), dst_init_lamports + src_init_lamports - minimum_balance);
assert_eq!(
accounts[1].lamports(),
dst_init_lamports + (src_init_lamports - minimum_balance)
);
assert!(result.is_ok())
}

Expand Down Expand Up @@ -4413,7 +4470,7 @@ fn test_process_initialize_multisig2(
let instruction_data: &[u8; 1] = instruction_data.last_chunk().unwrap();

// ^ FIXME: totally arbitrary for the tests
// cheatcode_is_spl_multisig(&accounts[0]);
cheatcode_is_spl_multisig(&accounts[0]);
cheatcode_is_spl_account(&accounts[1]); // Signer
cheatcode_is_spl_account(&accounts[2]); // Signer
cheatcode_is_spl_account(&accounts[3]); // Signer
Expand Down Expand Up @@ -4906,13 +4963,19 @@ fn test_process_withdraw_excess_lamports_account(
if src_init_lamports < minimum_balance {
assert_eq!(result, Err(ProgramError::Custom(0)));
return result;
} else if u64::MAX - src_init_lamports + minimum_balance < dst_init_lamports {
} else if dst_init_lamports
.checked_add(src_init_lamports - minimum_balance)
.is_none()
{
assert_eq!(result, Err(ProgramError::Custom(0)));
return result;
}

assert_eq!(accounts[0].lamports(), minimum_balance);
assert_eq!(accounts[1].lamports(), dst_init_lamports + src_init_lamports - minimum_balance);
assert_eq!(
accounts[1].lamports(),
dst_init_lamports + (src_init_lamports - minimum_balance)
);
assert!(result.is_ok())
}
}
Expand Down Expand Up @@ -4991,13 +5054,19 @@ fn test_process_withdraw_excess_lamports_account_multisig(
if src_init_lamports < minimum_balance {
assert_eq!(result, Err(ProgramError::Custom(0)));
return result;
} else if u64::MAX - src_init_lamports + minimum_balance < dst_init_lamports {
} else if dst_init_lamports
.checked_add(src_init_lamports - minimum_balance)
.is_none()
{
assert_eq!(result, Err(ProgramError::Custom(0)));
return result;
}

assert_eq!(accounts[0].lamports(), minimum_balance);
assert_eq!(accounts[1].lamports(), dst_init_lamports + src_init_lamports - minimum_balance);
assert_eq!(
accounts[1].lamports(),
dst_init_lamports + (src_init_lamports - minimum_balance)
);
assert!(result.is_ok())
}
}
Expand Down Expand Up @@ -5079,13 +5148,19 @@ fn test_process_withdraw_excess_lamports_mint(
else if src_init_lamports < minimum_balance {
assert_eq!(result, Err(ProgramError::Custom(0)));
return result;
} else if u64::MAX - src_init_lamports + minimum_balance < dst_init_lamports {
} else if dst_init_lamports
.checked_add(src_init_lamports - minimum_balance)
.is_none()
{
assert_eq!(result, Err(ProgramError::Custom(0)));
return result;
}

assert_eq!(accounts[0].lamports(), minimum_balance);
assert_eq!(accounts[1].lamports(), dst_init_lamports + src_init_lamports - minimum_balance);
assert_eq!(
accounts[1].lamports(),
dst_init_lamports + (src_init_lamports - minimum_balance)
);
assert!(result.is_ok())
}
}
Expand Down Expand Up @@ -5167,13 +5242,19 @@ fn test_process_withdraw_excess_lamports_mint_multisig(
else if src_init_lamports < minimum_balance {
assert_eq!(result, Err(ProgramError::Custom(0)));
return result;
} else if u64::MAX - src_init_lamports + minimum_balance < dst_init_lamports {
} else if dst_init_lamports
.checked_add(src_init_lamports - minimum_balance)
.is_none()
{
assert_eq!(result, Err(ProgramError::Custom(0)));
return result;
}

assert_eq!(accounts[0].lamports(), minimum_balance);
assert_eq!(accounts[1].lamports(), dst_init_lamports + src_init_lamports - minimum_balance);
assert_eq!(
accounts[1].lamports(),
dst_init_lamports + (src_init_lamports - minimum_balance)
);
assert!(result.is_ok())
}
}
Expand Down Expand Up @@ -5204,7 +5285,7 @@ fn test_process_withdraw_excess_lamports_multisig(
let instruction_data_with_discriminator = &instruction_data.clone();
let instruction_data: &[u8; 0] = instruction_data.last_chunk().unwrap();

// cheatcode_is_spl_multisig(&accounts[0]); // Source Account (Multisig)
cheatcode_is_spl_multisig(&accounts[0]); // Source Account (Multisig)
cheatcode_is_spl_account(&accounts[1]); // Destination
cheatcode_is_spl_account(&accounts[2]); // Authority

Expand Down Expand Up @@ -5241,13 +5322,19 @@ fn test_process_withdraw_excess_lamports_multisig(
if src_init_lamports < minimum_balance {
assert_eq!(result, Err(ProgramError::Custom(0)));
return result;
} else if u64::MAX - src_init_lamports + minimum_balance < dst_init_lamports {
} else if dst_init_lamports
.checked_add(src_init_lamports - minimum_balance)
.is_none()
{
assert_eq!(result, Err(ProgramError::Custom(0)));
return result;
}

assert_eq!(accounts[0].lamports(), minimum_balance);
assert_eq!(accounts[1].lamports(), dst_init_lamports + src_init_lamports - minimum_balance);
assert_eq!(
accounts[1].lamports(),
dst_init_lamports + (src_init_lamports - minimum_balance)
);
assert!(result.is_ok())
}

Expand Down