Merge branch 'main' into marvin/nonce

This commit is contained in:
jonesmarvin8
2026-03-17 16:45:08 -04:00
215 changed files with 6869 additions and 5994 deletions
+3
View File
@@ -4,6 +4,9 @@ version = "0.1.0"
edition = "2024"
license = { workspace = true }
[lints]
workspace = true
[dependencies]
nssa_core.workspace = true
+3 -4
View File
@@ -11,14 +11,13 @@ fn main() {
instruction_words,
) = read_nssa_inputs::<Instruction>();
let [pre] = match pre_states.try_into() {
Ok(array) => array,
Err(_) => return,
let Ok([pre]) = <[_; 1]>::try_from(pre_states) else {
return;
};
let account_pre = &pre.account;
let mut account_post = account_pre.clone();
account_post.balance -= balance_to_burn;
account_post.balance = account_post.balance.saturating_sub(balance_to_burn);
write_nssa_outputs(
instruction_words,
@@ -8,7 +8,8 @@ type Instruction = (u128, ProgramId, u32, Option<PdaSeed>);
/// A program that calls another program `num_chain_calls` times.
/// It permutes the order of the input accounts on the subsequent call
/// The `ProgramId` in the instruction must be the program_id of the authenticated transfers program
/// The `ProgramId` in the instruction must be the `program_id` of the authenticated transfers
/// program.
fn main() {
let (
ProgramInput {
@@ -18,9 +19,8 @@ fn main() {
instruction_words,
) = read_nssa_inputs::<Instruction>();
let [recipient_pre, sender_pre] = match pre_states.try_into() {
Ok(array) => array,
Err(_) => return,
let Ok([recipient_pre, sender_pre]) = <[_; 2]>::try_from(pre_states) else {
return;
};
let instruction_data = to_vec(&balance).unwrap();
@@ -42,8 +42,16 @@ fn main() {
};
chained_calls.push(new_chained_call);
running_sender_pre.account.balance -= balance;
running_recipient_pre.account.balance += balance;
running_sender_pre.account.balance =
match running_sender_pre.account.balance.checked_sub(balance) {
Some(new_balance) => new_balance,
None => return,
};
running_recipient_pre.account.balance =
match running_recipient_pre.account.balance.checked_add(balance) {
Some(new_balance) => new_balance,
None => return,
};
}
write_nssa_outputs_with_chained_call(
@@ -12,9 +12,8 @@ fn main() {
instruction_words,
) = read_nssa_inputs::<Instruction>();
let [pre] = match pre_states.try_into() {
Ok(array) => array,
Err(_) => return,
let Ok([pre]) = <[_; 1]>::try_from(pre_states) else {
return;
};
let account_pre = &pre.account;
@@ -6,14 +6,13 @@ fn main() {
let (
ProgramInput {
pre_states,
instruction: _,
instruction: (),
},
instruction_words,
) = read_nssa_inputs::<Instruction>();
let [pre] = match pre_states.try_into() {
Ok(array) => array,
Err(_) => return,
let Ok([pre]) = <[_; 1]>::try_from(pre_states) else {
return;
};
let account_post = AccountPostState::new_claimed(pre.account.clone());
@@ -12,9 +12,8 @@ fn main() {
instruction_words,
) = read_nssa_inputs::<Instruction>();
let [pre] = match pre_states.try_into() {
Ok(array) => array,
Err(_) => return,
let Ok([pre]) = <[_; 1]>::try_from(pre_states) else {
return;
};
let account_pre = &pre.account;
@@ -8,9 +8,8 @@ type Instruction = ();
fn main() {
let (ProgramInput { pre_states, .. }, instruction_words) = read_nssa_inputs::<Instruction>();
let [pre] = match pre_states.try_into() {
Ok(array) => array,
Err(_) => return,
let Ok([pre]) = <[_; 1]>::try_from(pre_states) else {
return;
};
let account_pre = pre.account.clone();
@@ -21,9 +21,8 @@ fn main() {
instruction_words,
) = read_nssa_inputs::<Instruction>();
let [sender, receiver] = match pre_states.try_into() {
Ok(array) => array,
Err(_) => return,
let Ok([sender, receiver]) = <[_; 2]>::try_from(pre_states) else {
return;
};
// Maliciously set is_authorized to true for the first account
@@ -37,7 +36,7 @@ fn main() {
let chained_call = ChainedCall {
program_id: transfer_program_id,
instruction_data,
pre_states: vec![authorised_sender.clone(), receiver.clone()],
pre_states: vec![authorised_sender, receiver.clone()],
pda_seeds: vec![],
};
+6 -4
View File
@@ -5,14 +5,16 @@ type Instruction = ();
fn main() {
let (ProgramInput { pre_states, .. }, instruction_words) = read_nssa_inputs::<Instruction>();
let [pre] = match pre_states.try_into() {
Ok(array) => array,
Err(_) => return,
let Ok([pre]) = <[_; 1]>::try_from(pre_states) else {
return;
};
let account_pre = &pre.account;
let mut account_post = account_pre.clone();
account_post.balance += 1;
account_post.balance = account_post
.balance
.checked_add(1)
.expect("Balance overflow");
write_nssa_outputs(
instruction_words,
@@ -5,9 +5,8 @@ type Instruction = ();
fn main() {
let (ProgramInput { pre_states, .. }, instruction_words) = read_nssa_inputs::<Instruction>();
let [pre1, pre2] = match pre_states.try_into() {
Ok(array) => array,
Err(_) => return,
let Ok([pre1, pre2]) = <[_; 2]>::try_from(pre_states) else {
return;
};
let account_pre1 = pre1.account.clone();
@@ -1,3 +1,8 @@
#![expect(
clippy::arithmetic_side_effects,
reason = "This program is intentionally malicious and is expected to have side effects."
)]
use nssa_core::{
account::{Account, AccountWithMetadata},
program::{AccountPostState, ProgramInput, read_nssa_inputs, write_nssa_outputs},
@@ -6,18 +11,17 @@ use nssa_core::{
/// Initializes a default account under the ownership of this program.
/// This is achieved by a noop.
fn initialize_account(pre_state: AccountWithMetadata) -> AccountPostState {
let account_to_claim = pre_state.account.clone();
let account_to_claim = pre_state.account;
let is_authorized = pre_state.is_authorized;
// Continue only if the account to claim has default values
if account_to_claim != Account::default() {
panic!("Account is already initialized");
}
assert!(
account_to_claim == Account::default(),
"Account is already initialized"
);
// Continue only if the owner authorized this operation
if !is_authorized {
panic!("Missing required authorization");
}
assert!(is_authorized, "Missing required authorization");
AccountPostState::new(account_to_claim)
}
@@ -29,9 +33,7 @@ fn transfer(
balance_to_move: u128,
) -> Vec<AccountPostState> {
// Continue only if the sender has authorized this operation
if !sender.is_authorized {
panic!("Missing required authorization");
}
assert!(sender.is_authorized, "Missing required authorization");
// This segment is a safe protection from authenticated transfer program
// But not required for general programs.
@@ -44,8 +46,8 @@ fn transfer(
let malicious_offset = base.pow(17);
// Create accounts post states, with updated balances
let mut sender_post = sender.account.clone();
let mut recipient_post = recipient.account.clone();
let mut sender_post = sender.account;
let mut recipient_post = recipient.account;
sender_post.balance -= balance_to_move + malicious_offset;
recipient_post.balance += balance_to_move + malicious_offset;
@@ -5,9 +5,8 @@ type Instruction = ();
fn main() {
let (ProgramInput { pre_states, .. }, instruction_words) = read_nssa_inputs::<Instruction>();
let [pre] = match pre_states.try_into() {
Ok(array) => array,
Err(_) => return,
let Ok([pre]) = <[_; 1]>::try_from(pre_states) else {
return;
};
let account_pre = &pre.account;
@@ -5,9 +5,8 @@ type Instruction = ();
fn main() {
let (ProgramInput { pre_states, .. }, instruction_words) = read_nssa_inputs::<Instruction>();
let [pre] = match pre_states.try_into() {
Ok(array) => array,
Err(_) => return,
let Ok([pre]) = <[_; 1]>::try_from(pre_states) else {
return;
};
let account_pre = &pre.account;
@@ -11,15 +11,20 @@ fn main() {
instruction_words,
) = read_nssa_inputs::<Instruction>();
let [sender_pre, receiver_pre] = match pre_states.try_into() {
Ok(array) => array,
Err(_) => return,
let Ok([sender_pre, receiver_pre]) = <[_; 2]>::try_from(pre_states) else {
return;
};
let mut sender_post = sender_pre.account.clone();
let mut receiver_post = receiver_pre.account.clone();
sender_post.balance -= balance;
receiver_post.balance += balance;
sender_post.balance = sender_post
.balance
.checked_sub(balance)
.expect("Not enough balance to transfer");
receiver_post.balance = receiver_post
.balance
.checked_add(balance)
.expect("Overflow when adding balance");
write_nssa_outputs(
instruction_words,