diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e3b0b22..570ca37 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,7 +59,22 @@ jobs: ${{ runner.os }}-cargo- - name: Clippy - run: RISC0_SKIP_BUILD=1 cargo clippy --workspace --all-targets -- -D warnings + run: | + if rg -n -U --multiline '#\[(allow|expect)\([\s\S]*?reason\s*=\s*"(TODO|FIXME|fix later|later|temporary|hack)' token amm ata integration_tests tools -g '*.rs'; then + echo "Found non-actionable lint suppression reason" + exit 1 + fi + RISC0_SKIP_BUILD=1 cargo clippy --workspace --all-targets -- -D warnings + + - name: Guest Clippy + run: | + for manifest in \ + token/methods/guest/Cargo.toml \ + amm/methods/guest/Cargo.toml \ + ata/methods/guest/Cargo.toml + do + cargo clippy --manifest-path "$manifest" --all-targets -- -D warnings + done unit-tests: name: Unit Tests diff --git a/Cargo.toml b/Cargo.toml index 7021e21..fd2a224 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,3 +33,41 @@ borsh = { version = "1.0", features = ["derive"] } risc0-zkvm = { version = "=3.0.5" } serde_json = "1.0" tokio = { version = "1.28.2", features = ["net", "rt-multi-thread", "sync", "macros"] } + +[workspace.lints.rust] +rust_2018_idioms = { level = "deny", priority = -1 } +unsafe_code = "forbid" + +[workspace.lints.clippy] +all = { level = "deny", priority = -1 } + +# Generated-code / placeholder blockers. +dbg_macro = "deny" +todo = "deny" +unimplemented = "deny" +unwrap_used = "deny" + +# Lint suppression hygiene. +allow_attributes = "warn" +allow_attributes_without_reason = "deny" + +# Determinism, panic-safety, and arithmetic correctness. +arithmetic_side_effects = "deny" +indexing_slicing = "deny" +integer_division = "warn" + +# Cast discipline. +as_conversions = "deny" +cast_possible_truncation = "deny" +cast_possible_wrap = "deny" +cast_precision_loss = "warn" +cast_sign_loss = "deny" + +# API and enum evolution. +large_enum_variant = "deny" +match_wildcard_for_single_variants = "warn" +wildcard_enum_match_arm = "deny" + +# Too noisy for this codebase unless enforced selectively. +module_name_repetitions = "allow" +similar_names = "allow" diff --git a/amm/Cargo.toml b/amm/Cargo.toml index 04be123..5ca726b 100644 --- a/amm/Cargo.toml +++ b/amm/Cargo.toml @@ -3,6 +3,9 @@ name = "amm_program" version = "0.1.0" edition = "2021" +[lints] +workspace = true + [dependencies] nssa_core = { git = "https://github.com/logos-blockchain/logos-execution-zone.git", tag = "v0.2.0-rc1", features = ["host"] } amm_core = { path = "core" } diff --git a/amm/core/Cargo.toml b/amm/core/Cargo.toml index 16b08c6..ed217aa 100644 --- a/amm/core/Cargo.toml +++ b/amm/core/Cargo.toml @@ -3,6 +3,9 @@ name = "amm_core" version = "0.1.0" edition = "2021" +[lints] +workspace = true + [dependencies] nssa_core = { git = "https://github.com/logos-blockchain/logos-execution-zone.git", tag = "v0.2.0-rc1", features = ["host"] } token_core = { path = "../../token/core" } diff --git a/amm/core/src/lib.rs b/amm/core/src/lib.rs index f8b6871..b0cea1e 100644 --- a/amm/core/src/lib.rs +++ b/amm/core/src/lib.rs @@ -203,8 +203,9 @@ pub fn compute_pool_pda_seed( }; let mut bytes = [0; 64]; - bytes[0..32].copy_from_slice(&token_1.to_bytes()); - bytes[32..].copy_from_slice(&token_2.to_bytes()); + let (token_1_bytes, token_2_bytes) = bytes.split_at_mut(32); + token_1_bytes.copy_from_slice(&token_1.to_bytes()); + token_2_bytes.copy_from_slice(&token_2.to_bytes()); PdaSeed::new( Impl::hash_bytes(&bytes) @@ -229,8 +230,9 @@ pub fn compute_vault_pda_seed(pool_id: AccountId, definition_token_id: AccountId use risc0_zkvm::sha::{Impl, Sha256}; let mut bytes = [0; 64]; - bytes[0..32].copy_from_slice(&pool_id.to_bytes()); - bytes[32..].copy_from_slice(&definition_token_id.to_bytes()); + let (pool_bytes, definition_bytes) = bytes.split_at_mut(32); + pool_bytes.copy_from_slice(&pool_id.to_bytes()); + definition_bytes.copy_from_slice(&definition_token_id.to_bytes()); PdaSeed::new( Impl::hash_bytes(&bytes) @@ -248,8 +250,9 @@ pub fn compute_liquidity_token_pda_seed(pool_id: AccountId) -> PdaSeed { use risc0_zkvm::sha::{Impl, Sha256}; let mut bytes = [0; 64]; - bytes[0..32].copy_from_slice(&pool_id.to_bytes()); - bytes[32..].copy_from_slice(&LIQUIDITY_TOKEN_PDA_SEED); + let (pool_bytes, seed_bytes) = bytes.split_at_mut(32); + pool_bytes.copy_from_slice(&pool_id.to_bytes()); + seed_bytes.copy_from_slice(&LIQUIDITY_TOKEN_PDA_SEED); PdaSeed::new( Impl::hash_bytes(&bytes) @@ -267,8 +270,9 @@ pub fn compute_lp_lock_holding_pda_seed(pool_id: AccountId) -> PdaSeed { use risc0_zkvm::sha::{Impl, Sha256}; let mut bytes = [0; 64]; - bytes[0..32].copy_from_slice(&pool_id.to_bytes()); - bytes[32..].copy_from_slice(&LP_LOCK_HOLDING_PDA_SEED); + let (pool_bytes, seed_bytes) = bytes.split_at_mut(32); + pool_bytes.copy_from_slice(&pool_id.to_bytes()); + seed_bytes.copy_from_slice(&LP_LOCK_HOLDING_PDA_SEED); PdaSeed::new( Impl::hash_bytes(&bytes) diff --git a/amm/methods/Cargo.toml b/amm/methods/Cargo.toml index 5bc00df..1139347 100644 --- a/amm/methods/Cargo.toml +++ b/amm/methods/Cargo.toml @@ -3,6 +3,9 @@ name = "amm-methods" version = "0.1.0" edition = "2021" +[lints] +workspace = true + [build-dependencies] risc0-build = "=3.0.5" diff --git a/amm/methods/guest/Cargo.toml b/amm/methods/guest/Cargo.toml index fd7351d..a0eb84c 100644 --- a/amm/methods/guest/Cargo.toml +++ b/amm/methods/guest/Cargo.toml @@ -5,6 +5,32 @@ edition = "2021" [workspace] +[lints.rust] +rust_2018_idioms = { level = "deny", priority = -1 } +unsafe_code = "forbid" + +[lints.clippy] +all = { level = "deny", priority = -1 } +allow_attributes = "warn" +allow_attributes_without_reason = "deny" +arithmetic_side_effects = "deny" +as_conversions = "deny" +cast_possible_truncation = "deny" +cast_possible_wrap = "deny" +cast_precision_loss = "warn" +cast_sign_loss = "deny" +dbg_macro = "deny" +indexing_slicing = "deny" +integer_division = "warn" +large_enum_variant = "deny" +match_wildcard_for_single_variants = "warn" +module_name_repetitions = "allow" +similar_names = "allow" +todo = "deny" +unimplemented = "deny" +unwrap_used = "deny" +wildcard_enum_match_arm = "deny" + [[bin]] name = "amm" path = "src/bin/amm.rs" diff --git a/amm/methods/guest/src/bin/amm.rs b/amm/methods/guest/src/bin/amm.rs index 9e71954..4dcf941 100644 --- a/amm/methods/guest/src/bin/amm.rs +++ b/amm/methods/guest/src/bin/amm.rs @@ -1,4 +1,4 @@ -#![no_main] +#![cfg_attr(not(test), no_main)] use std::num::NonZeroU128; @@ -8,15 +8,27 @@ use nssa_core::{ program::ProgramId, }; +#[cfg(not(test))] risc0_zkvm::guest::entry!(main); #[lez_program(instruction = "amm_core::Instruction")] mod amm { - #[allow(unused_imports)] + #[expect( + unused_imports, + reason = "SPEL instruction macro requires importing parent-scope handler types" + )] use super::*; /// Initializes a new Pool (or re-initializes an existing zero-supply Pool). /// A fresh user LP holding must be explicitly authorized by the caller. + #[expect( + clippy::too_many_arguments, + reason = "instruction ABI exposes explicit pool, vault, mint, lock, and user accounts" + )] + #[expect( + deprecated, + reason = "AMM guest chained-call wrapper remains until auto-claim migration is scoped" + )] #[instruction] pub fn new_definition( pool: AccountWithMetadata, @@ -52,6 +64,14 @@ mod amm { } /// Adds liquidity to the Pool. + #[expect( + clippy::too_many_arguments, + reason = "instruction ABI exposes explicit pool, vault, and user accounts" + )] + #[expect( + deprecated, + reason = "AMM guest chained-call wrapper remains until auto-claim migration is scoped" + )] #[instruction] pub fn add_liquidity( pool: AccountWithMetadata, @@ -83,6 +103,14 @@ mod amm { } /// Removes liquidity from the Pool. + #[expect( + clippy::too_many_arguments, + reason = "instruction ABI exposes explicit pool, vault, and user accounts" + )] + #[expect( + deprecated, + reason = "AMM guest chained-call wrapper remains until auto-claim migration is scoped" + )] #[instruction] pub fn remove_liquidity( pool: AccountWithMetadata, @@ -115,6 +143,14 @@ mod amm { } /// Swap some quantity of tokens while maintaining the pool constant product. + #[expect( + clippy::too_many_arguments, + reason = "instruction ABI exposes explicit pool, vault, user accounts, and bounds" + )] + #[expect( + deprecated, + reason = "AMM guest chained-call wrapper remains until auto-claim migration is scoped" + )] #[instruction] pub fn swap_exact_input( pool: AccountWithMetadata, @@ -142,6 +178,14 @@ mod amm { } /// Swap tokens specifying the exact desired output amount. + #[expect( + clippy::too_many_arguments, + reason = "instruction ABI exposes explicit pool, vault, user accounts, and bounds" + )] + #[expect( + deprecated, + reason = "AMM guest chained-call wrapper remains until auto-claim migration is scoped" + )] #[instruction] pub fn swap_exact_output( pool: AccountWithMetadata, @@ -169,6 +213,10 @@ mod amm { } /// Sync pool reserves with current vault balances. + #[expect( + deprecated, + reason = "AMM guest chained-call wrapper remains until auto-claim migration is scoped" + )] #[instruction] pub fn sync_reserves( pool: AccountWithMetadata, diff --git a/amm/src/add.rs b/amm/src/add.rs index 1dff79e..96fa501 100644 --- a/amm/src/add.rs +++ b/amm/src/add.rs @@ -9,7 +9,10 @@ use nssa_core::{ program::{AccountPostState, ChainedCall}, }; -#[expect(clippy::too_many_arguments, reason = "TODO: Fix later")] +#[expect( + clippy::too_many_arguments, + reason = "instruction surface passes explicit pool, vault, and user accounts" +)] pub fn add_liquidity( pool: AccountWithMetadata, vault_a: AccountWithMetadata, @@ -67,12 +70,14 @@ pub fn add_liquidity( .reserve_a .checked_mul(max_amount_to_add_token_b) .expect("reserve_a * max_amount_b overflows u128") - / pool_def_data.reserve_b; + .checked_div(pool_def_data.reserve_b) + .expect("reserve_b must be nonzero after validation"); let ideal_b: u128 = pool_def_data .reserve_b .checked_mul(max_amount_to_add_token_a) .expect("reserve_b * max_amount_a overflows u128") - / pool_def_data.reserve_a; + .checked_div(pool_def_data.reserve_a) + .expect("reserve_a must be nonzero after validation"); let actual_amount_a = if ideal_a > max_amount_to_add_token_a { max_amount_to_add_token_a @@ -104,12 +109,14 @@ pub fn add_liquidity( .liquidity_pool_supply .checked_mul(actual_amount_a) .expect("liquidity_pool_supply * actual_amount_a overflows u128") - / pool_def_data.reserve_a, + .checked_div(pool_def_data.reserve_a) + .expect("reserve_a must be nonzero after validation"), pool_def_data .liquidity_pool_supply .checked_mul(actual_amount_b) .expect("liquidity_pool_supply * actual_amount_b overflows u128") - / pool_def_data.reserve_b, + .checked_div(pool_def_data.reserve_b) + .expect("reserve_b must be nonzero after validation"), ); assert!(delta_lp != 0, "Payable LP must be nonzero"); diff --git a/amm/src/new_definition.rs b/amm/src/new_definition.rs index b7a45cc..8c47a6a 100644 --- a/amm/src/new_definition.rs +++ b/amm/src/new_definition.rs @@ -12,7 +12,10 @@ use nssa_core::{ }; use token_core::TokenDefinition; -#[expect(clippy::too_many_arguments, reason = "TODO: Fix later")] +#[expect( + clippy::too_many_arguments, + reason = "instruction surface passes explicit pool, vault, mint, lock, and user accounts" +)] pub fn new_definition( pool: AccountWithMetadata, vault_a: AccountWithMetadata, @@ -94,7 +97,9 @@ pub fn new_definition( initial_lp > MINIMUM_LIQUIDITY, "Initial liquidity must exceed minimum liquidity lock" ); - let user_lp = initial_lp - MINIMUM_LIQUIDITY; + let user_lp = initial_lp + .checked_sub(MINIMUM_LIQUIDITY) + .expect("initial liquidity must exceed minimum liquidity after validation"); // Update pool account let mut pool_post = pool.account.clone(); diff --git a/amm/src/remove.rs b/amm/src/remove.rs index 951c639..e647a0a 100644 --- a/amm/src/remove.rs +++ b/amm/src/remove.rs @@ -9,7 +9,10 @@ use nssa_core::{ program::{AccountPostState, ChainedCall}, }; -#[expect(clippy::too_many_arguments, reason = "TODO: Fix later")] +#[expect( + clippy::too_many_arguments, + reason = "instruction surface passes explicit pool, vault, and user accounts" +)] pub fn remove_liquidity( pool: AccountWithMetadata, vault_a: AccountWithMetadata, @@ -91,7 +94,10 @@ pub fn remove_liquidity( pool_def_data.liquidity_pool_supply > MINIMUM_LIQUIDITY, "Pool only contains locked liquidity" ); - let unlocked_liquidity = pool_def_data.liquidity_pool_supply - MINIMUM_LIQUIDITY; + let unlocked_liquidity = pool_def_data + .liquidity_pool_supply + .checked_sub(MINIMUM_LIQUIDITY) + .expect("liquidity supply must be at least the locked minimum after validation"); // The remove instruction never sees the LP lock account directly, so we must still refuse any // request that would burn through the permanent floor even if ownership is already corrupted. assert!( @@ -103,12 +109,14 @@ pub fn remove_liquidity( .reserve_a .checked_mul(remove_liquidity_amount) .expect("reserve_a * remove_liquidity_amount overflows u128") - / pool_def_data.liquidity_pool_supply; + .checked_div(pool_def_data.liquidity_pool_supply) + .expect("liquidity supply must be nonzero after validation"); let withdraw_amount_b = pool_def_data .reserve_b .checked_mul(remove_liquidity_amount) .expect("reserve_b * remove_liquidity_amount overflows u128") - / pool_def_data.liquidity_pool_supply; + .checked_div(pool_def_data.liquidity_pool_supply) + .expect("liquidity supply must be nonzero after validation"); // 3. Validate and slippage check assert!( diff --git a/amm/src/swap.rs b/amm/src/swap.rs index 51c4d80..0676d87 100644 --- a/amm/src/swap.rs +++ b/amm/src/swap.rs @@ -46,7 +46,10 @@ fn validate_swap_setup( } /// Creates post-state and returns reserves after swap. -#[expect(clippy::too_many_arguments, reason = "TODO: Fix later")] +#[expect( + clippy::too_many_arguments, + reason = "post-state assembly keeps pool, vault, user account, and delta state explicit" +)] #[expect( clippy::needless_pass_by_value, reason = "consistent with codebase style" @@ -91,7 +94,10 @@ fn create_swap_post_states( ] } -#[expect(clippy::too_many_arguments, reason = "TODO: Fix later")] +#[expect( + clippy::too_many_arguments, + reason = "instruction surface passes explicit pool, vault, and user accounts" +)] #[must_use] pub fn swap_exact_input( pool: AccountWithMetadata, @@ -156,7 +162,10 @@ pub fn swap_exact_input( (post_states, chained_calls) } -#[expect(clippy::too_many_arguments, reason = "TODO: Fix later")] +#[expect( + clippy::too_many_arguments, + reason = "swap calculation keeps account context and pricing parameters explicit" +)] fn swap_logic( user_deposit: AccountWithMetadata, vault_deposit: AccountWithMetadata, @@ -169,10 +178,14 @@ fn swap_logic( reserve_withdraw_vault_amount: u128, pool_id: AccountId, ) -> (Vec, u128, u128) { + let fee_multiplier = FEE_BPS_DENOMINATOR + .checked_sub(fee_bps) + .expect("fee_bps exceeds fee denominator"); let effective_amount_in = swap_amount_in - .checked_mul(FEE_BPS_DENOMINATOR - fee_bps) + .checked_mul(fee_multiplier) .expect("swap_amount_in * (FEE_BPS_DENOMINATOR - fee_bps) overflows u128") - / FEE_BPS_DENOMINATOR; + .checked_div(FEE_BPS_DENOMINATOR) + .expect("fee denominator must be nonzero"); assert!( effective_amount_in != 0, "Effective swap amount should be nonzero" @@ -184,9 +197,12 @@ fn swap_logic( let withdraw_amount = reserve_withdraw_vault_amount .checked_mul(effective_amount_in) .expect("reserve * effective_amount_in overflows u128") - / reserve_deposit_vault_amount - .checked_add(effective_amount_in) - .expect("reserve + effective_amount_in overflows u128"); + .checked_div( + reserve_deposit_vault_amount + .checked_add(effective_amount_in) + .expect("reserve + effective_amount_in overflows u128"), + ) + .expect("reserve plus effective input must be nonzero"); // Slippage check assert!( @@ -230,7 +246,10 @@ fn swap_logic( (chained_calls, swap_amount_in, withdraw_amount) } -#[expect(clippy::too_many_arguments, reason = "TODO: Fix later")] +#[expect( + clippy::too_many_arguments, + reason = "instruction surface passes explicit pool, vault, and user accounts" +)] #[must_use] pub fn swap_exact_output( pool: AccountWithMetadata, @@ -295,7 +314,10 @@ pub fn swap_exact_output( (post_states, chained_calls) } -#[expect(clippy::too_many_arguments, reason = "TODO: Fix later")] +#[expect( + clippy::too_many_arguments, + reason = "swap calculation keeps account context and pricing parameters explicit" +)] fn exact_output_swap_logic( user_deposit: AccountWithMetadata, vault_deposit: AccountWithMetadata, diff --git a/amm/src/tests.rs b/amm/src/tests.rs index 5f7f433..7f673ad 100644 --- a/amm/src/tests.rs +++ b/amm/src/tests.rs @@ -1,4 +1,9 @@ #![cfg(test)] +#![expect( + clippy::arithmetic_side_effects, + clippy::integer_division, + reason = "test fixtures use fixed values to lock AMM math boundaries" +)] use std::num::NonZero; @@ -1398,7 +1403,7 @@ fn test_call_add_liquidity_vault_a_omitted() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::add_min_amount_lp()).expect("test setup should succeed"), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), ); @@ -1415,7 +1420,7 @@ fn test_call_add_liquidity_vault_b_omitted() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::add_min_amount_lp()).expect("test setup should succeed"), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), ); @@ -1432,7 +1437,7 @@ fn test_call_add_liquidity_lp_definition_mismatch() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::add_min_amount_lp()).expect("test setup should succeed"), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), ); @@ -1449,7 +1454,7 @@ fn test_call_add_liquidity_zero_balance_1() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::add_min_amount_lp()).expect("test setup should succeed"), 0, BalanceForTests::add_max_amount_b(), ); @@ -1466,7 +1471,7 @@ fn test_call_add_liquidity_zero_balance_2() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::add_min_amount_lp()).expect("test setup should succeed"), 0, BalanceForTests::add_max_amount_a(), ); @@ -1483,7 +1488,7 @@ fn test_call_add_liquidity_vault_a_balance_below_reserve() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::add_min_amount_lp()).expect("test setup should succeed"), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), ); @@ -1500,7 +1505,7 @@ fn test_call_add_liquidity_vault_b_balance_below_reserve() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::add_min_amount_lp()).expect("test setup should succeed"), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), ); @@ -1517,7 +1522,7 @@ fn test_call_add_liquidity_vault_insufficient_balance_1() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::add_min_amount_lp()).expect("test setup should succeed"), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), ); @@ -1534,7 +1539,7 @@ fn test_call_add_liquidity_vault_insufficient_balance_2() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::add_min_amount_lp()).expect("test setup should succeed"), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), ); @@ -1551,7 +1556,7 @@ fn test_call_add_liquidity_actual_amount_zero_1() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::add_min_amount_lp()).expect("test setup should succeed"), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), ); @@ -1568,7 +1573,7 @@ fn test_call_add_liquidity_actual_amount_zero_2() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::add_min_amount_lp()).expect("test setup should succeed"), BalanceForTests::add_max_amount_a_low(), BalanceForTests::add_max_amount_b_low(), ); @@ -1585,7 +1590,7 @@ fn test_call_add_liquidity_reserves_zero_1() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::add_min_amount_lp()).expect("test setup should succeed"), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), ); @@ -1602,7 +1607,7 @@ fn test_call_add_liquidity_reserves_zero_2() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::add_min_amount_lp()).expect("test setup should succeed"), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), ); @@ -1619,7 +1624,7 @@ fn test_call_add_liquidity_payable_lp_zero() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::add_min_amount_lp()).expect("test setup should succeed"), BalanceForTests::add_max_amount_a_low(), BalanceForTests::add_max_amount_b_low(), ); @@ -1635,7 +1640,7 @@ fn test_call_add_liquidity_chained_call_successsful() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::add_min_amount_lp()).expect("test setup should succeed"), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), ); @@ -1667,7 +1672,7 @@ fn test_call_remove_liquidity_vault_a_omitted() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::remove_amount_lp()).expect("test setup should succeed"), BalanceForTests::remove_min_amount_a(), BalanceForTests::remove_min_amount_b(), ); @@ -1684,7 +1689,7 @@ fn test_call_remove_liquidity_vault_b_omitted() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::remove_amount_lp()).expect("test setup should succeed"), BalanceForTests::remove_min_amount_a(), BalanceForTests::remove_min_amount_b(), ); @@ -1701,7 +1706,7 @@ fn test_call_remove_liquidity_lp_def_mismatch() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::remove_amount_lp()).expect("test setup should succeed"), BalanceForTests::remove_min_amount_a(), BalanceForTests::remove_min_amount_b(), ); @@ -1720,7 +1725,7 @@ fn test_call_remove_liquidity_insufficient_liquidity_amount() { AccountWithMetadataForTests::user_holding_a(), /* different token account than lp to * create desired * error */ - NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::remove_amount_lp()).expect("test setup should succeed"), BalanceForTests::remove_min_amount_a(), BalanceForTests::remove_min_amount_b(), ); @@ -1739,7 +1744,7 @@ fn test_call_remove_liquidity_insufficient_balance_1() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::remove_amount_lp_1()).unwrap(), + NonZero::new(BalanceForTests::remove_amount_lp_1()).expect("test setup should succeed"), BalanceForTests::remove_min_amount_a(), BalanceForTests::remove_min_amount_b(), ); @@ -1757,7 +1762,7 @@ fn test_call_remove_liquidity_pool_at_minimum_liquidity() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_with_balance(MINIMUM_LIQUIDITY), - NonZero::new(MINIMUM_LIQUIDITY).unwrap(), + NonZero::new(MINIMUM_LIQUIDITY).expect("test setup should succeed"), 1, 1, ); @@ -1777,7 +1782,7 @@ fn test_call_remove_liquidity_exceeds_unlocked_supply() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_with_balance(BalanceForTests::lp_supply_init()), - NonZero::new(BalanceForTests::lp_supply_init()).unwrap(), + NonZero::new(BalanceForTests::lp_supply_init()).expect("test setup should succeed"), 1, 1, ); @@ -1796,7 +1801,7 @@ fn test_call_remove_liquidity_insufficient_balance_2() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::remove_amount_lp()).expect("test setup should succeed"), BalanceForTests::remove_min_amount_a(), BalanceForTests::remove_min_amount_b(), ); @@ -1813,7 +1818,7 @@ fn test_call_remove_liquidity_min_bal_zero_1() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::remove_amount_lp()).expect("test setup should succeed"), 0, BalanceForTests::remove_min_amount_b(), ); @@ -1830,7 +1835,7 @@ fn test_call_remove_liquidity_min_bal_zero_2() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::remove_amount_lp()).expect("test setup should succeed"), BalanceForTests::remove_min_amount_a(), 0, ); @@ -1846,7 +1851,7 @@ fn test_call_remove_liquidity_chained_call_successful() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(), + NonZero::new(BalanceForTests::remove_amount_lp()).expect("test setup should succeed"), BalanceForTests::remove_min_amount_a(), BalanceForTests::remove_min_amount_b_low(), ); @@ -1880,7 +1885,7 @@ fn test_call_new_definition_with_zero_balance_1() { AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_uninit(), NonZero::new(0).expect("Balances must be nonzero"), - NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(), + NonZero::new(BalanceForTests::vault_b_reserve_init()).expect("test setup should succeed"), BalanceForTests::fee_tier(), AMM_PROGRAM_ID, ); @@ -1898,7 +1903,7 @@ fn test_call_new_definition_with_zero_balance_2() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_uninit(), - NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(), + NonZero::new(BalanceForTests::vault_a_reserve_init()).expect("test setup should succeed"), NonZero::new(0).expect("Balances must be nonzero"), BalanceForTests::fee_tier(), AMM_PROGRAM_ID, @@ -1917,8 +1922,8 @@ fn test_call_new_definition_same_token_definition() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_lp_uninit(), - NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(), - NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(), + NonZero::new(BalanceForTests::vault_a_reserve_init()).expect("test setup should succeed"), + NonZero::new(BalanceForTests::vault_b_reserve_init()).expect("test setup should succeed"), BalanceForTests::fee_tier(), AMM_PROGRAM_ID, ); @@ -1936,8 +1941,8 @@ fn test_call_new_definition_wrong_liquidity_id() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_uninit(), - NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(), - NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(), + NonZero::new(BalanceForTests::vault_a_reserve_init()).expect("test setup should succeed"), + NonZero::new(BalanceForTests::vault_b_reserve_init()).expect("test setup should succeed"), BalanceForTests::fee_tier(), AMM_PROGRAM_ID, ); @@ -1955,8 +1960,8 @@ fn test_call_new_definition_wrong_lp_lock_holding_id() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_uninit(), - NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(), - NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(), + NonZero::new(BalanceForTests::vault_a_reserve_init()).expect("test setup should succeed"), + NonZero::new(BalanceForTests::vault_b_reserve_init()).expect("test setup should succeed"), BalanceForTests::fee_tier(), AMM_PROGRAM_ID, ); @@ -1974,8 +1979,8 @@ fn test_call_new_definition_wrong_pool_id() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_uninit(), - NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(), - NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(), + NonZero::new(BalanceForTests::vault_a_reserve_init()).expect("test setup should succeed"), + NonZero::new(BalanceForTests::vault_b_reserve_init()).expect("test setup should succeed"), BalanceForTests::fee_tier(), AMM_PROGRAM_ID, ); @@ -1993,8 +1998,8 @@ fn test_call_new_definition_wrong_vault_id_1() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_uninit(), - NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(), - NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(), + NonZero::new(BalanceForTests::vault_a_reserve_init()).expect("test setup should succeed"), + NonZero::new(BalanceForTests::vault_b_reserve_init()).expect("test setup should succeed"), BalanceForTests::fee_tier(), AMM_PROGRAM_ID, ); @@ -2012,8 +2017,8 @@ fn test_call_new_definition_wrong_vault_id_2() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_uninit(), - NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(), - NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(), + NonZero::new(BalanceForTests::vault_a_reserve_init()).expect("test setup should succeed"), + NonZero::new(BalanceForTests::vault_b_reserve_init()).expect("test setup should succeed"), BalanceForTests::fee_tier(), AMM_PROGRAM_ID, ); @@ -2032,8 +2037,8 @@ fn test_call_new_definition_rejects_initialized_pool() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_uninit(), - NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(), - NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(), + NonZero::new(BalanceForTests::vault_a_reserve_init()).expect("test setup should succeed"), + NonZero::new(BalanceForTests::vault_b_reserve_init()).expect("test setup should succeed"), BalanceForTests::fee_tier(), AMM_PROGRAM_ID, ); @@ -2052,8 +2057,8 @@ fn test_call_new_definition_initial_lp_too_small() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_uninit(), - NonZero::new(MINIMUM_LIQUIDITY).unwrap(), - NonZero::new(MINIMUM_LIQUIDITY).unwrap(), + NonZero::new(MINIMUM_LIQUIDITY).expect("test setup should succeed"), + NonZero::new(MINIMUM_LIQUIDITY).expect("test setup should succeed"), BalanceForTests::fee_tier(), AMM_PROGRAM_ID, ); @@ -2070,8 +2075,8 @@ fn test_call_new_definition_chained_call_successful() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_uninit(), - NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(), - NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(), + NonZero::new(BalanceForTests::vault_a_reserve_init()).expect("test setup should succeed"), + NonZero::new(BalanceForTests::vault_b_reserve_init()).expect("test setup should succeed"), BalanceForTests::fee_tier(), AMM_PROGRAM_ID, ); @@ -2192,7 +2197,8 @@ fn test_call_swap_below_minimum_liquidity() { #[test] fn test_call_swap_rejects_unsupported_fee_tier() { let mut pool = AccountWithMetadataForTests::pool_definition_init(); - let mut pool_def = PoolDefinition::try_from(&pool.account.data).unwrap(); + let mut pool_def = + PoolDefinition::try_from(&pool.account.data).expect("test setup should succeed"); pool_def.fees = 2; pool.account.data = Data::from(&pool_def); @@ -2718,15 +2724,16 @@ fn test_new_definition_lp_asymmetric_amounts() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_uninit(), - NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(), - NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(), + NonZero::new(BalanceForTests::vault_a_reserve_init()).expect("test setup should succeed"), + NonZero::new(BalanceForTests::vault_b_reserve_init()).expect("test setup should succeed"), BalanceForTests::fee_tier(), AMM_PROGRAM_ID, ); // check the minted LP amount let pool_post = post_states[0].clone(); - let pool_def = PoolDefinition::try_from(&pool_post.account().data).unwrap(); + let pool_def = + PoolDefinition::try_from(&pool_post.account().data).expect("test setup should succeed"); assert_eq!( pool_def.liquidity_pool_supply, BalanceForTests::lp_supply_init() @@ -2755,14 +2762,15 @@ fn test_new_definition_lp_symmetric_amounts() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_uninit(), - NonZero::new(token_a_amount).unwrap(), - NonZero::new(token_b_amount).unwrap(), + NonZero::new(token_a_amount).expect("test setup should succeed"), + NonZero::new(token_b_amount).expect("test setup should succeed"), BalanceForTests::fee_tier(), AMM_PROGRAM_ID, ); let pool_post = post_states[0].clone(); - let pool_def = PoolDefinition::try_from(&pool_post.account().data).unwrap(); + let pool_def = + PoolDefinition::try_from(&pool_post.account().data).expect("test setup should succeed"); assert_eq!(pool_def.liquidity_pool_supply, expected_lp); let chained_call_lp_lock = chained_calls[0].clone(); @@ -2824,8 +2832,8 @@ fn test_minimum_liquidity_lock_and_remove_all_user_lp() { AccountForTests::user_holding_a(), AccountForTests::user_holding_b(), AccountForTests::user_holding_lp_uninit(), - NonZero::new(token_a_amount).unwrap(), - NonZero::new(token_b_amount).unwrap(), + NonZero::new(token_a_amount).expect("test setup should succeed"), + NonZero::new(token_b_amount).expect("test setup should succeed"), BalanceForTests::fee_tier(), AMM_PROGRAM_ID, ); @@ -2863,7 +2871,8 @@ fn test_minimum_liquidity_lock_and_remove_all_user_lp() { assert_eq!(chained_calls[0], expected_lock_call); assert_eq!(chained_calls[1], expected_user_call); - let pool_post = PoolDefinition::try_from(&post_states[0].account().data).unwrap(); + let pool_post = PoolDefinition::try_from(&post_states[0].account().data) + .expect("test setup should succeed"); assert_eq!(pool_post.liquidity_pool_supply, initial_lp); let pool_for_remove = AccountWithMetadata { @@ -2879,13 +2888,13 @@ fn test_minimum_liquidity_lock_and_remove_all_user_lp() { AccountForTests::user_holding_a(), AccountForTests::user_holding_b(), AccountForTests::user_holding_lp_with_balance(user_lp), - NonZero::new(user_lp).unwrap(), + NonZero::new(user_lp).expect("test setup should succeed"), 1, 1, ); - let pool_after_remove = - PoolDefinition::try_from(&remove_post_states[0].account().data).unwrap(); + let pool_after_remove = PoolDefinition::try_from(&remove_post_states[0].account().data) + .expect("test setup should succeed"); assert_eq!(pool_after_remove.liquidity_pool_supply, MINIMUM_LIQUIDITY); assert!(pool_after_remove.reserve_a > 0); assert!(pool_after_remove.reserve_b > 0); @@ -2902,7 +2911,7 @@ fn test_sync_reserves_with_donation() { balance: BalanceForTests::vault_a_reserve_init() + donation_a, }); - let pool_pre = PoolDefinition::try_from(&pool.account.data).unwrap(); + let pool_pre = PoolDefinition::try_from(&pool.account.data).expect("test setup should succeed"); assert_eq!(pool_pre.reserve_a, BalanceForTests::vault_a_reserve_init()); let (post_states, chained_calls) = sync_reserves( @@ -2912,7 +2921,8 @@ fn test_sync_reserves_with_donation() { ); assert!(chained_calls.is_empty()); - let pool_post = PoolDefinition::try_from(&post_states[0].account().data).unwrap(); + let pool_post = PoolDefinition::try_from(&post_states[0].account().data) + .expect("test setup should succeed"); assert_eq!( pool_post.reserve_a, BalanceForTests::vault_a_reserve_init() + donation_a @@ -2969,11 +2979,12 @@ fn test_donation_then_add_liquidity_sync_mitigates_mispricing() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(1).unwrap(), + NonZero::new(1).expect("test setup should succeed"), 100, 50, ); - let unsynced_pool_post = PoolDefinition::try_from(&post_unsynced[0].account().data).unwrap(); + let unsynced_pool_post = PoolDefinition::try_from(&post_unsynced[0].account().data) + .expect("test setup should succeed"); let unsynced_delta_lp = unsynced_pool_post.liquidity_pool_supply - BalanceForTests::lp_supply_init(); @@ -2999,14 +3010,15 @@ fn test_donation_then_add_liquidity_sync_mitigates_mispricing() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(1).unwrap(), + NonZero::new(1).expect("test setup should succeed"), 100, 50, ); - let synced_pool_post = PoolDefinition::try_from(&post_synced[0].account().data).unwrap(); + let synced_pool_post = PoolDefinition::try_from(&post_synced[0].account().data) + .expect("test setup should succeed"); let synced_delta_lp = synced_pool_post.liquidity_pool_supply - PoolDefinition::try_from(&sync_post[0].account().data) - .unwrap() + .expect("test setup should succeed") .liquidity_pool_supply; assert!(synced_delta_lp < unsynced_delta_lp); @@ -3026,8 +3038,8 @@ fn new_definition_overflow_protection() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_uninit(), - NonZero::new(large_amount).unwrap(), - NonZero::new(2).unwrap(), + NonZero::new(large_amount).expect("test setup should succeed"), + NonZero::new(2).expect("test setup should succeed"), BalanceForTests::fee_tier(), AMM_PROGRAM_ID, ); @@ -3096,7 +3108,7 @@ fn add_liquidity_overflow_protection() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), - NonZero::new(1).unwrap(), + NonZero::new(1).expect("test setup should succeed"), 500, 2, // max_amount_b=2 → reserve_a * 2 overflows ); @@ -3180,7 +3192,8 @@ fn remove_liquidity_overflow_protection() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), user_lp, - NonZero::new(2).unwrap(), // remove_amount=2 → reserve_a * 2 overflows + NonZero::new(2).expect("test setup should succeed"), /* remove_amount=2 → reserve_a * 2 + * overflows */ 1, 1, ); @@ -3273,14 +3286,17 @@ fn test_new_definition_supports_all_fee_tiers() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_uninit(), - NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(), - NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(), + NonZero::new(BalanceForTests::vault_a_reserve_init()) + .expect("test setup should succeed"), + NonZero::new(BalanceForTests::vault_b_reserve_init()) + .expect("test setup should succeed"), fees, AMM_PROGRAM_ID, ); let pool_post = post_states[0].clone(); - let pool_def = PoolDefinition::try_from(&pool_post.account().data).unwrap(); + let pool_def = + PoolDefinition::try_from(&pool_post.account().data).expect("test setup should succeed"); assert_eq!(pool_def.fees, fees); } } @@ -3297,8 +3313,8 @@ fn test_new_definition_rejects_unsupported_fee_tier() { AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_uninit(), - NonZero::new(BalanceForTests::vault_a_reserve_init()).unwrap(), - NonZero::new(BalanceForTests::vault_b_reserve_init()).unwrap(), + NonZero::new(BalanceForTests::vault_a_reserve_init()).expect("test setup should succeed"), + NonZero::new(BalanceForTests::vault_b_reserve_init()).expect("test setup should succeed"), 2, AMM_PROGRAM_ID, ); diff --git a/ata/Cargo.toml b/ata/Cargo.toml index 51babec..6f615ea 100644 --- a/ata/Cargo.toml +++ b/ata/Cargo.toml @@ -3,6 +3,9 @@ name = "ata_program" version = "0.1.0" edition = "2021" +[lints] +workspace = true + [dependencies] nssa_core = { git = "https://github.com/logos-blockchain/logos-execution-zone.git", tag = "v0.2.0-rc1", features = ["host"] } ata_core = { path = "core" } diff --git a/ata/core/Cargo.toml b/ata/core/Cargo.toml index 0e2fd3e..a9197a2 100644 --- a/ata/core/Cargo.toml +++ b/ata/core/Cargo.toml @@ -3,6 +3,9 @@ name = "ata_core" version = "0.1.0" edition = "2021" +[lints] +workspace = true + [dependencies] nssa_core = { git = "https://github.com/logos-blockchain/logos-execution-zone.git", tag = "v0.2.0-rc1", features = ["host"] } borsh = { version = "1.5", features = ["derive"] } diff --git a/ata/core/src/lib.rs b/ata/core/src/lib.rs index 4ea46bf..138dc05 100644 --- a/ata/core/src/lib.rs +++ b/ata/core/src/lib.rs @@ -50,8 +50,9 @@ pub enum Instruction { pub fn compute_ata_seed(owner_id: AccountId, definition_id: AccountId) -> PdaSeed { use risc0_zkvm::sha::{Impl, Sha256}; let mut bytes = [0u8; 64]; - bytes[0..32].copy_from_slice(&owner_id.to_bytes()); - bytes[32..64].copy_from_slice(&definition_id.to_bytes()); + let (owner_bytes, definition_bytes) = bytes.split_at_mut(32); + owner_bytes.copy_from_slice(&owner_id.to_bytes()); + definition_bytes.copy_from_slice(&definition_id.to_bytes()); PdaSeed::new( Impl::hash_bytes(&bytes) .as_bytes() diff --git a/ata/methods/Cargo.toml b/ata/methods/Cargo.toml index 09d4849..6bb49b0 100644 --- a/ata/methods/Cargo.toml +++ b/ata/methods/Cargo.toml @@ -3,6 +3,9 @@ name = "ata-methods" version = "0.1.0" edition = "2021" +[lints] +workspace = true + [build-dependencies] risc0-build = "=3.0.5" diff --git a/ata/methods/guest/Cargo.toml b/ata/methods/guest/Cargo.toml index f203c7c..399ea6f 100644 --- a/ata/methods/guest/Cargo.toml +++ b/ata/methods/guest/Cargo.toml @@ -5,6 +5,32 @@ edition = "2021" [workspace] +[lints.rust] +rust_2018_idioms = { level = "deny", priority = -1 } +unsafe_code = "forbid" + +[lints.clippy] +all = { level = "deny", priority = -1 } +allow_attributes = "warn" +allow_attributes_without_reason = "deny" +arithmetic_side_effects = "deny" +as_conversions = "deny" +cast_possible_truncation = "deny" +cast_possible_wrap = "deny" +cast_precision_loss = "warn" +cast_sign_loss = "deny" +dbg_macro = "deny" +indexing_slicing = "deny" +integer_division = "warn" +large_enum_variant = "deny" +match_wildcard_for_single_variants = "warn" +module_name_repetitions = "allow" +similar_names = "allow" +todo = "deny" +unimplemented = "deny" +unwrap_used = "deny" +wildcard_enum_match_arm = "deny" + [[bin]] name = "ata" path = "src/bin/ata.rs" diff --git a/ata/methods/guest/src/bin/ata.rs b/ata/methods/guest/src/bin/ata.rs index ad8a950..f82a4f0 100644 --- a/ata/methods/guest/src/bin/ata.rs +++ b/ata/methods/guest/src/bin/ata.rs @@ -1,17 +1,25 @@ -#![no_main] +#![cfg_attr(not(test), no_main)] use spel_framework::prelude::*; use nssa_core::{account::AccountWithMetadata, program::ProgramId}; +#[cfg(not(test))] risc0_zkvm::guest::entry!(main); #[lez_program(instruction = "ata_core::Instruction")] mod ata { - #[allow(unused_imports)] + #[expect( + unused_imports, + reason = "SPEL instruction macro requires importing parent-scope handler types" + )] use super::*; /// Create the Associated Token Account for (owner, definition). /// Idempotent: no-op if the account already exists. + #[expect( + deprecated, + reason = "ATA guest chained-call wrapper remains until auto-claim migration is scoped" + )] #[instruction] pub fn create( owner: AccountWithMetadata, @@ -30,6 +38,10 @@ mod ata { /// Transfer tokens FROM owner's ATA to a recipient token holding account. /// The recipient holding account must already be initialized. + #[expect( + deprecated, + reason = "ATA guest chained-call wrapper remains until auto-claim migration is scoped" + )] #[instruction] pub fn transfer( owner: AccountWithMetadata, @@ -50,6 +62,10 @@ mod ata { } /// Burn tokens FROM owner's ATA. + #[expect( + deprecated, + reason = "ATA guest chained-call wrapper remains until auto-claim migration is scoped" + )] #[instruction] pub fn burn( owner: AccountWithMetadata, diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 0000000..a2fcc9a --- /dev/null +++ b/clippy.toml @@ -0,0 +1,11 @@ +msrv = "1.94.0" + +avoid-breaking-exported-api = false +check-private-items = true +warn-on-all-wildcard-imports = true + +allow-dbg-in-tests = false +allow-expect-in-tests = true +allow-indexing-slicing-in-tests = true +allow-print-in-tests = true +allow-unwrap-in-tests = false diff --git a/integration_tests/Cargo.toml b/integration_tests/Cargo.toml index 3254cdc..5f85b31 100644 --- a/integration_tests/Cargo.toml +++ b/integration_tests/Cargo.toml @@ -3,6 +3,9 @@ name = "integration_tests" version = "0.1.0" edition = "2021" +[lints] +workspace = true + [dependencies] nssa = { workspace = true } nssa_core = { workspace = true, features = ["host"] } diff --git a/integration_tests/tests/amm.rs b/integration_tests/tests/amm.rs index ff3791a..cf9c6d6 100644 --- a/integration_tests/tests/amm.rs +++ b/integration_tests/tests/amm.rs @@ -1,3 +1,8 @@ +#![expect( + clippy::arithmetic_side_effects, + reason = "integration fixtures use fixed balances to assert AMM state transitions" +)] + use amm_core::{ PoolDefinition, FEE_TIER_BPS_1, FEE_TIER_BPS_100, FEE_TIER_BPS_30, FEE_TIER_BPS_5, MINIMUM_LIQUIDITY, @@ -995,7 +1000,7 @@ fn try_execute_new_definition( }, instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = if authorize_user_lp { public_transaction::WitnessSet::for_message( @@ -1011,7 +1016,7 @@ fn try_execute_new_definition( } fn execute_new_definition(state: &mut V03State, fees: u128) { - try_execute_new_definition(state, fees, true).unwrap(); + try_execute_new_definition(state, fees, true).expect("test setup should succeed"); } fn execute_swap_a_to_b(state: &mut V03State, swap_amount_in: u128, min_amount_out: u128) { @@ -1034,12 +1039,14 @@ fn execute_swap_a_to_b(state: &mut V03State, swap_amount_in: u128, min_amount_ou vec![current_nonce(state, Ids::user_a())], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::user_a()]); let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx, 0, 0).unwrap(); + state + .transition_from_public_transaction(&tx, 0, 0) + .expect("test setup should succeed"); } fn execute_swap_b_to_a(state: &mut V03State, swap_amount_in: u128, min_amount_out: u128) { @@ -1062,12 +1069,14 @@ fn execute_swap_b_to_a(state: &mut V03State, swap_amount_in: u128, min_amount_ou vec![current_nonce(state, Ids::user_b())], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::user_b()]); let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx, 0, 0).unwrap(); + state + .transition_from_public_transaction(&tx, 0, 0) + .expect("test setup should succeed"); } fn execute_add_liquidity( @@ -1100,13 +1109,15 @@ fn execute_add_liquidity( ], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::user_a(), &Keys::user_b()]); let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx, 0, 0).unwrap(); + state + .transition_from_public_transaction(&tx, 0, 0) + .expect("test setup should succeed"); } fn execute_remove_liquidity( @@ -1136,12 +1147,14 @@ fn execute_remove_liquidity( vec![current_nonce(state, Ids::user_lp())], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::user_lp()]); let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx, 0, 0).unwrap(); + state + .transition_from_public_transaction(&tx, 0, 0) + .expect("test setup should succeed"); } fn fungible_balance(account: &Account) -> u128 { @@ -1200,12 +1213,14 @@ fn amm_remove_liquidity() { vec![Nonce(0)], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::user_lp()]); let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx, 0, 0).unwrap(); + state + .transition_from_public_transaction(&tx, 0, 0) + .expect("test setup should succeed"); assert_eq!( state.get_account_by_id(Ids::pool_definition()), @@ -1263,7 +1278,7 @@ fn amm_remove_liquidity_insufficient_user_lp_fails() { vec![Nonce(0)], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::user_lp()]); @@ -1359,7 +1374,8 @@ fn amm_new_definition_precreated_zero_balance_user_lp() { state.force_insert_account(Ids::vault_a(), Accounts::vault_a_reinitializable()); state.force_insert_account(Ids::vault_b(), Accounts::vault_b_reinitializable()); - try_execute_new_definition(&mut state, Balances::fee_tier(), false).unwrap(); + try_execute_new_definition(&mut state, Balances::fee_tier(), false) + .expect("test setup should succeed"); assert_eq!( state.get_account_by_id(Ids::pool_definition()), @@ -1488,13 +1504,15 @@ fn amm_add_liquidity() { vec![Nonce(0), Nonce(0)], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::user_a(), &Keys::user_b()]); let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx, 0, 0).unwrap(); + state + .transition_from_public_transaction(&tx, 0, 0) + .expect("test setup should succeed"); assert_eq!( state.get_account_by_id(Ids::pool_definition()), @@ -1549,12 +1567,14 @@ fn amm_swap_b_to_a() { vec![Nonce(0)], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::user_b()]); let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx, 0, 0).unwrap(); + state + .transition_from_public_transaction(&tx, 0, 0) + .expect("test setup should succeed"); assert_eq!( state.get_account_by_id(Ids::pool_definition()), @@ -1601,12 +1621,14 @@ fn amm_swap_a_to_b() { vec![Nonce(0)], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::user_a()]); let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx, 0, 0).unwrap(); + state + .transition_from_public_transaction(&tx, 0, 0) + .expect("test setup should succeed"); assert_eq!( state.get_account_by_id(Ids::pool_definition()), @@ -1707,7 +1729,7 @@ fn amm_swap_rejects_expired_deadline() { vec![Nonce(0)], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::user_a()]); let tx = PublicTransaction::new(message, witness_set); @@ -1743,7 +1765,7 @@ fn amm_swap_exact_output_rejects_expired_deadline() { vec![current_nonce(&state, Ids::user_a())], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::user_a()]); let tx = PublicTransaction::new(message, witness_set); @@ -1784,7 +1806,7 @@ fn amm_add_liquidity_rejects_expired_deadline() { ], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::user_a(), &Keys::user_b()]); @@ -1823,7 +1845,7 @@ fn amm_remove_liquidity_rejects_expired_deadline() { vec![current_nonce(&state, Ids::user_lp())], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::user_lp()]); let tx = PublicTransaction::new(message, witness_set); @@ -1867,7 +1889,7 @@ fn amm_new_definition_rejects_expired_deadline() { ], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message( &message, diff --git a/integration_tests/tests/ata.rs b/integration_tests/tests/ata.rs index dd2eef7..a4f7fbd 100644 --- a/integration_tests/tests/ata.rs +++ b/integration_tests/tests/ata.rs @@ -154,12 +154,14 @@ fn ata_create() { vec![Nonce(0)], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::owner_key()]); let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx, 0, 0).unwrap(); + state + .transition_from_public_transaction(&tx, 0, 0) + .expect("test setup should succeed"); assert_eq!( state.get_account_by_id(Ids::owner_ata()), @@ -189,12 +191,14 @@ fn ata_create_is_idempotent() { vec![Nonce(0)], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::owner_key()]); let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx, 0, 0).unwrap(); + state + .transition_from_public_transaction(&tx, 0, 0) + .expect("test setup should succeed"); // Already initialized — should remain unchanged assert_eq!( @@ -226,12 +230,14 @@ fn ata_transfer() { vec![Nonce(0)], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::owner_key()]); let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx, 0, 0).unwrap(); + state + .transition_from_public_transaction(&tx, 0, 0) + .expect("test setup should succeed"); assert_eq!( state.get_account_by_id(Ids::owner_ata()), @@ -275,12 +281,14 @@ fn ata_burn() { vec![Nonce(0)], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::owner_key()]); let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx, 0, 0).unwrap(); + state + .transition_from_public_transaction(&tx, 0, 0) + .expect("test setup should succeed"); assert_eq!( state.get_account_by_id(Ids::owner_ata()), @@ -340,15 +348,18 @@ fn ata_create_from_private_owner() { let instruction = ata_core::Instruction::Create { ata_program_id: Ids::ata_program(), }; - let instruction_data = Program::serialize_instruction(instruction).unwrap(); + let instruction_data = + Program::serialize_instruction(instruction).expect("test setup should succeed"); // Ephemeral key for encrypting the private owner's post-state let esk: Scalar = [3u8; 32]; let shared_secret = SharedSecretKey::new(&esk, &owner_vpk); let epk = EphemeralPublicKey::from_scalar(esk); - let ata_program = Program::new(ata_methods::ATA_ELF.to_vec()).unwrap(); - let token_program = Program::new(token_methods::TOKEN_ELF.to_vec()).unwrap(); + let ata_program = + Program::new(ata_methods::ATA_ELF.to_vec()).expect("test setup should succeed"); + let token_program = + Program::new(token_methods::TOKEN_ELF.to_vec()).expect("test setup should succeed"); let program_with_deps = ProgramWithDependencies::new( ata_program, HashMap::from([(Ids::token_program(), token_program)]), @@ -364,7 +375,7 @@ fn ata_create_from_private_owner() { vec![None], // no membership proof: owner is being created, not spending &program_with_deps, ) - .unwrap(); + .expect("test setup should succeed"); let message = Message::try_from_circuit_output( vec![Ids::token_definition(), owner_ata_id], @@ -372,13 +383,13 @@ fn ata_create_from_private_owner() { vec![(owner_npk, owner_vpk, epk)], output, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = WitnessSet::for_message(&message, proof, &[]); let tx = PrivacyPreservingTransaction::new(message, witness_set); state .transition_from_privacy_preserving_transaction(&tx, 0, 0) - .unwrap(); + .expect("test setup should succeed"); assert_eq!( state.get_account_by_id(owner_ata_id), diff --git a/integration_tests/tests/token.rs b/integration_tests/tests/token.rs index aed4d8a..65a5015 100644 --- a/integration_tests/tests/token.rs +++ b/integration_tests/tests/token.rs @@ -129,7 +129,7 @@ fn token_new_fungible_definition() { vec![Nonce(0), Nonce(0)], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message( &message, @@ -137,7 +137,9 @@ fn token_new_fungible_definition() { ); let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx, 0, 0).unwrap(); + state + .transition_from_public_transaction(&tx, 0, 0) + .expect("test setup should succeed"); assert_eq!( state.get_account_by_id(Ids::token_definition()), @@ -181,12 +183,14 @@ fn token_transfer() { vec![Nonce(0)], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::holder_key()]); let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx, 0, 0).unwrap(); + state + .transition_from_public_transaction(&tx, 0, 0) + .expect("test setup should succeed"); assert_eq!( state.get_account_by_id(Ids::holder()), @@ -229,7 +233,7 @@ fn token_transfer_fresh_public_recipient_requires_authorization() { vec![Nonce(0)], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::holder_key()]); @@ -260,7 +264,7 @@ fn token_transfer_fresh_authorized_public_recipient() { vec![Nonce(0), Nonce(0)], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message( &message, @@ -268,7 +272,9 @@ fn token_transfer_fresh_authorized_public_recipient() { ); let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx, 0, 0).unwrap(); + state + .transition_from_public_transaction(&tx, 0, 0) + .expect("test setup should succeed"); assert_eq!( state.get_account_by_id(Ids::holder()), @@ -311,12 +317,14 @@ fn token_burn() { vec![Nonce(0)], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::holder_key()]); let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx, 0, 0).unwrap(); + state + .transition_from_public_transaction(&tx, 0, 0) + .expect("test setup should succeed"); assert_eq!( state.get_account_by_id(Ids::token_definition()), @@ -360,12 +368,14 @@ fn token_mint() { vec![Nonce(0)], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::def_key()]); let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx, 0, 0).unwrap(); + state + .transition_from_public_transaction(&tx, 0, 0) + .expect("test setup should succeed"); assert_eq!( state.get_account_by_id(Ids::token_definition()), @@ -409,7 +419,7 @@ fn token_mint_fresh_public_recipient_requires_authorization() { vec![Nonce(0)], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::def_key()]); @@ -440,7 +450,7 @@ fn token_mint_fresh_authorized_public_recipient() { vec![Nonce(0), Nonce(0)], instruction, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = public_transaction::WitnessSet::for_message( &message, @@ -448,7 +458,9 @@ fn token_mint_fresh_authorized_public_recipient() { ); let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx, 0, 0).unwrap(); + state + .transition_from_public_transaction(&tx, 0, 0) + .expect("test setup should succeed"); assert_eq!( state.get_account_by_id(Ids::token_definition()), @@ -539,14 +551,14 @@ fn shielded_token_transfer(amount: u128, state: &mut V03State) -> Account { }; let (output, proof) = execute_and_prove( vec![sender, recipient], - Program::serialize_instruction(instruction).unwrap(), + Program::serialize_instruction(instruction).expect("test setup should succeed"), vec![0, 2], vec![(PrivateKeys::recipient_npk(), shared_secret)], vec![], vec![None], &token_program().into(), ) - .unwrap(); + .expect("test setup should succeed"); let message = Message::try_from_circuit_output( vec![sender_id], @@ -558,13 +570,13 @@ fn shielded_token_transfer(amount: u128, state: &mut V03State) -> Account { )], output, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = WitnessSet::for_message(&message, proof, &[&Keys::holder_key()]); let tx = PrivacyPreservingTransaction::new(message, witness_set); state .transition_from_privacy_preserving_transaction(&tx, 0, 0) - .unwrap(); + .expect("test setup should succeed"); Account { program_owner: Ids::token_program(), @@ -636,7 +648,7 @@ fn token_private_transfer() { }; let (output, proof) = execute_and_prove( vec![sender_pre, new_recipient_pre], - Program::serialize_instruction(instruction).unwrap(), + Program::serialize_instruction(instruction).expect("test setup should succeed"), vec![1, 2], vec![ (sender_npk.clone(), shared_secret_1), @@ -646,7 +658,7 @@ fn token_private_transfer() { vec![state.get_proof_for_commitment(&sender_commitment), None], &token_program().into(), ) - .unwrap(); + .expect("test setup should succeed"); let message = Message::try_from_circuit_output( vec![], @@ -657,13 +669,13 @@ fn token_private_transfer() { ], output, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = WitnessSet::for_message(&message, proof, &[]); let tx = PrivacyPreservingTransaction::new(message, witness_set); state .transition_from_privacy_preserving_transaction(&tx, 0, 0) - .unwrap(); + .expect("test setup should succeed"); let sender_nonce_after = Nonce::private_account_nonce_init(&sender_npk).private_account_nonce_increment(&sender_nsk); @@ -725,14 +737,14 @@ fn token_deshielded_transfer() { }; let (output, proof) = execute_and_prove( vec![sender_pre, public_recipient_pre], - Program::serialize_instruction(instruction).unwrap(), + Program::serialize_instruction(instruction).expect("test setup should succeed"), vec![1, 0], vec![(sender_npk.clone(), shared_secret)], vec![sender_nsk], vec![state.get_proof_for_commitment(&sender_commitment)], &token_program().into(), ) - .unwrap(); + .expect("test setup should succeed"); let message = Message::try_from_circuit_output( vec![public_recipient_id], @@ -740,13 +752,13 @@ fn token_deshielded_transfer() { vec![(sender_npk.clone(), sender_vpk, epk)], output, ) - .unwrap(); + .expect("test setup should succeed"); let witness_set = WitnessSet::for_message(&message, proof, &[]); let tx = PrivacyPreservingTransaction::new(message, witness_set); state .transition_from_privacy_preserving_transaction(&tx, 0, 0) - .unwrap(); + .expect("test setup should succeed"); assert_eq!( state.get_account_by_id(public_recipient_id), diff --git a/token/Cargo.toml b/token/Cargo.toml index bce7726..af45654 100644 --- a/token/Cargo.toml +++ b/token/Cargo.toml @@ -3,6 +3,9 @@ name = "token_program" version = "0.1.0" edition = "2021" +[lints] +workspace = true + [dependencies] nssa_core = { git = "https://github.com/logos-blockchain/logos-execution-zone.git", tag = "v0.2.0-rc1", features = ["host"] } token_core = { path = "core" } diff --git a/token/core/Cargo.toml b/token/core/Cargo.toml index 5eb50b3..1b96621 100644 --- a/token/core/Cargo.toml +++ b/token/core/Cargo.toml @@ -3,6 +3,9 @@ name = "token_core" version = "0.1.0" edition = "2021" +[lints] +workspace = true + [dependencies] nssa_core = { git = "https://github.com/logos-blockchain/logos-execution-zone.git", tag = "v0.2.0-rc1", features = ["host"] } borsh = { version = "1.5", features = ["derive"] } diff --git a/token/methods/Cargo.toml b/token/methods/Cargo.toml index a4897fb..e7007e2 100644 --- a/token/methods/Cargo.toml +++ b/token/methods/Cargo.toml @@ -3,6 +3,9 @@ name = "token-methods" version = "0.1.0" edition = "2021" +[lints] +workspace = true + [build-dependencies] risc0-build = "=3.0.5" diff --git a/token/methods/guest/Cargo.toml b/token/methods/guest/Cargo.toml index c1c412e..45f07d1 100644 --- a/token/methods/guest/Cargo.toml +++ b/token/methods/guest/Cargo.toml @@ -5,6 +5,32 @@ edition = "2021" [workspace] +[lints.rust] +rust_2018_idioms = { level = "deny", priority = -1 } +unsafe_code = "forbid" + +[lints.clippy] +all = { level = "deny", priority = -1 } +allow_attributes = "warn" +allow_attributes_without_reason = "deny" +arithmetic_side_effects = "deny" +as_conversions = "deny" +cast_possible_truncation = "deny" +cast_possible_wrap = "deny" +cast_precision_loss = "warn" +cast_sign_loss = "deny" +dbg_macro = "deny" +indexing_slicing = "deny" +integer_division = "warn" +large_enum_variant = "deny" +match_wildcard_for_single_variants = "warn" +module_name_repetitions = "allow" +similar_names = "allow" +todo = "deny" +unimplemented = "deny" +unwrap_used = "deny" +wildcard_enum_match_arm = "deny" + [[bin]] name = "token" path = "src/bin/token.rs" diff --git a/token/methods/guest/src/bin/token.rs b/token/methods/guest/src/bin/token.rs index 73ae46a..11be540 100644 --- a/token/methods/guest/src/bin/token.rs +++ b/token/methods/guest/src/bin/token.rs @@ -1,17 +1,25 @@ -#![no_main] +#![cfg_attr(not(test), no_main)] use spel_framework::prelude::*; use nssa_core::account::AccountWithMetadata; +#[cfg(not(test))] risc0_zkvm::guest::entry!(main); #[lez_program(instruction = "token_core::Instruction")] mod token { - #[allow(unused_imports)] + #[expect( + unused_imports, + reason = "SPEL instruction macro requires importing parent-scope handler types" + )] use super::*; /// Transfer tokens from sender to recipient. /// Fresh public recipients must be explicitly authorized in the same transaction. + #[expect( + deprecated, + reason = "token guest states-only wrapper remains until auto-claim migration is scoped" + )] #[instruction] pub fn transfer( sender: AccountWithMetadata, @@ -27,6 +35,10 @@ mod token { /// Create a new fungible token definition without metadata. /// Definition and holding targets must be uninitialized and authorized. + #[expect( + deprecated, + reason = "token guest states-only wrapper remains until auto-claim migration is scoped" + )] #[instruction] pub fn new_fungible_definition( definition_target_account: AccountWithMetadata, @@ -46,6 +58,14 @@ mod token { /// Create a new fungible or non-fungible token definition with metadata. /// Definition, holding, and metadata targets must be uninitialized and authorized. + #[expect( + clippy::boxed_local, + reason = "boxed metadata keeps the generated instruction ABI size bounded" + )] + #[expect( + deprecated, + reason = "token guest states-only wrapper remains until auto-claim migration is scoped" + )] #[instruction] pub fn new_definition_with_metadata( definition_target_account: AccountWithMetadata, @@ -67,6 +87,10 @@ mod token { /// Initialize a token holding account for a given token definition. /// The holding target must be uninitialized and authorized. + #[expect( + deprecated, + reason = "token guest states-only wrapper remains until auto-claim migration is scoped" + )] #[instruction] pub fn initialize_account( definition_account: AccountWithMetadata, @@ -81,6 +105,10 @@ mod token { } /// Burn tokens from the holder's account. + #[expect( + deprecated, + reason = "token guest states-only wrapper remains until auto-claim migration is scoped" + )] #[instruction] pub fn burn( definition_account: AccountWithMetadata, @@ -96,6 +124,10 @@ mod token { /// Mint new tokens to the holder's account. /// Fresh public holders must be explicitly authorized in the same transaction. + #[expect( + deprecated, + reason = "token guest states-only wrapper remains until auto-claim migration is scoped" + )] #[instruction] pub fn mint( definition_account: AccountWithMetadata, @@ -111,6 +143,10 @@ mod token { /// Print a new NFT from the master copy. /// The printed copy target must be uninitialized and authorized. + #[expect( + deprecated, + reason = "token guest states-only wrapper remains until auto-claim migration is scoped" + )] #[instruction] pub fn print_nft( master_account: AccountWithMetadata, diff --git a/token/src/print_nft.rs b/token/src/print_nft.rs index 837fe48..c45e6ad 100644 --- a/token/src/print_nft.rs +++ b/token/src/print_nft.rs @@ -40,7 +40,9 @@ pub fn print_nft( *print_balance > 1, "Insufficient balance to print another NFT copy" ); - *print_balance -= 1; + *print_balance = print_balance + .checked_sub(1) + .expect("print balance must be greater than one after validation"); let mut master_account_post = master_account.account; master_account_post.data = Data::from(&master_account_data); diff --git a/token/src/tests.rs b/token/src/tests.rs index 532787e..9dfa2ab 100644 --- a/token/src/tests.rs +++ b/token/src/tests.rs @@ -1,4 +1,8 @@ #![cfg(test)] +#![expect( + clippy::arithmetic_side_effects, + reason = "test fixtures use fixed values to lock boundary behavior" +)] use nssa_core::{ account::{Account, AccountId, AccountWithMetadata, Data, Nonce}, @@ -635,7 +639,8 @@ fn test_new_definition_with_valid_inputs_succeeds() { BalanceForTests::init_supply(), ); - let [definition_account, holding_account] = post_states.try_into().unwrap(); + let [definition_account, holding_account] = + post_states.try_into().expect("test setup should succeed"); assert_eq!( *definition_account.account(), AccountForTests::definition_account_unclaimed().account @@ -679,7 +684,7 @@ fn test_transfer_with_valid_inputs_succeeds() { let sender = AccountForTests::holding_account_init(); let recipient = AccountForTests::holding_account2_init(); let post_states = transfer(sender, recipient, BalanceForTests::transfer_amount()); - let [sender_post, recipient_post] = post_states.try_into().unwrap(); + let [sender_post, recipient_post] = post_states.try_into().expect("test setup should succeed"); assert_eq!( *sender_post.account(), @@ -714,7 +719,7 @@ fn test_transfer_with_master_nft_success() { let sender = AccountForTests::holding_account_master_nft(); let recipient = AccountForTests::holding_account_uninit(); let post_states = transfer(sender, recipient, BalanceForTests::printable_copies()); - let [sender_post, recipient_post] = post_states.try_into().unwrap(); + let [sender_post, recipient_post] = post_states.try_into().expect("test setup should succeed"); assert_eq!( *sender_post.account(), @@ -731,7 +736,7 @@ fn test_transfer_with_default_recipient_claims_recipient() { let sender = AccountForTests::holding_account_init(); let recipient = AccountForTests::holding_account_uninit(); let post_states = transfer(sender, recipient, BalanceForTests::transfer_amount()); - let [sender_post, recipient_post] = post_states.try_into().unwrap(); + let [sender_post, recipient_post] = post_states.try_into().expect("test setup should succeed"); assert_eq!( *sender_post.account(), @@ -758,7 +763,8 @@ fn test_token_initialize_account_succeeds() { let definition_account = AccountForTests::definition_account_auth(); let holding_account = AccountForTests::holding_account_uninit_auth(); let post_states = initialize_account(definition_account, holding_account); - let [definition_post, holding_post] = post_states.try_into().unwrap(); + let [definition_post, holding_post] = + post_states.try_into().expect("test setup should succeed"); assert_eq!( *definition_post.account(), @@ -847,7 +853,7 @@ fn test_burn_success() { BalanceForTests::burn_success(), ); - let [def_post, holding_post] = post_states.try_into().unwrap(); + let [def_post, holding_post] = post_states.try_into().expect("test setup should succeed"); assert_eq!( *def_post.account(), @@ -917,7 +923,7 @@ fn test_mint_success() { BalanceForTests::mint_success(), ); - let [def_post, holding_post] = post_states.try_into().unwrap(); + let [def_post, holding_post] = post_states.try_into().expect("test setup should succeed"); assert_eq!( *def_post.account(), @@ -941,7 +947,7 @@ fn test_mint_uninit_holding_success() { BalanceForTests::mint_success(), ); - let [def_post, holding_post] = post_states.try_into().unwrap(); + let [def_post, holding_post] = post_states.try_into().expect("test setup should succeed"); assert_eq!( *def_post.account(), @@ -1013,7 +1019,8 @@ fn test_new_definition_with_metadata_success() { new_definition, metadata, ); - let [definition_post, holding_post, metadata_post] = post_states.try_into().unwrap(); + let [definition_post, holding_post, metadata_post] = + post_states.try_into().expect("test setup should succeed"); assert_eq!(definition_post.required_claim(), Some(Claim::Authorized)); assert_eq!(holding_post.required_claim(), Some(Claim::Authorized)); @@ -1246,7 +1253,8 @@ fn test_print_nft_success() { let printed_account = AccountForTests::holding_account_uninit_auth(); let post_states = print_nft(master_account, printed_account); - let [post_master_nft, post_printed] = post_states.try_into().unwrap(); + let [post_master_nft, post_printed] = + post_states.try_into().expect("test setup should succeed"); assert_eq!( *post_master_nft.account(), diff --git a/tools/idl-gen/Cargo.toml b/tools/idl-gen/Cargo.toml index 71dab24..1c54618 100644 --- a/tools/idl-gen/Cargo.toml +++ b/tools/idl-gen/Cargo.toml @@ -3,6 +3,9 @@ name = "idl-gen" version = "0.1.0" edition = "2021" +[lints] +workspace = true + [[bin]] name = "idl-gen" path = "src/main.rs" diff --git a/tools/idl-gen/src/main.rs b/tools/idl-gen/src/main.rs index f1abee5..6e3f632 100644 --- a/tools/idl-gen/src/main.rs +++ b/tools/idl-gen/src/main.rs @@ -10,7 +10,13 @@ fn main() { }; match spel_framework_core::idl_gen::generate_idl_from_file(&path) { - Ok(idl) => println!("{}", serde_json::to_string_pretty(&idl).unwrap()), + Ok(idl) => match serde_json::to_string_pretty(&idl) { + Ok(json) => println!("{json}"), + Err(e) => { + eprintln!("Error serializing IDL to JSON: {e}"); + process::exit(1); + } + }, Err(e) => { eprintln!("Error: {e}"); process::exit(1);