From 9444d72c6020bd6a7b5e07eac56c1b197c6ece35 Mon Sep 17 00:00:00 2001 From: r4bbit <445106+0x-r4bbit@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:35:30 +0200 Subject: [PATCH 1/2] feat(amm): route user deposits and LP burns through ATA program Add `owner` and `ata_program_id` parameters to `add_liquidity`, `remove_liquidity`, `swap_exact_input`, and `swap_exact_output`. User deposit-side transfers now emit `ATA::Transfer` chained calls instead of `Token::Transfer` directly, and LP burns emit `ATA::Burn` instead of `Token::Burn`. Vault withdrawal chained calls are unchanged. - Add `ata_program_id` field to `AddLiquidity`, `RemoveLiquidity`, `SwapExactInput`, and `SwapExactOutput` instruction variants in `amm_core` - Add `ata_core` dependency to `amm_program` and guest crates - Update guest binary, unit tests, and integration tests to supply the new `owner` account and `ata_program_id` at every call site - Regenerate `artifacts/amm-idl.json` Closes #11 --- Cargo.lock | 1 + amm/Cargo.toml | 1 + amm/core/src/lib.rs | 30 +++-- amm/methods/guest/Cargo.lock | 12 ++ amm/methods/guest/Cargo.toml | 1 + amm/methods/guest/src/bin/amm.rs | 16 +++ amm/src/add.rs | 31 +++-- amm/src/remove.rs | 34 ++--- amm/src/swap.rs | 48 +++++-- amm/src/tests.rs | 212 ++++++++++++++++++++++++++----- artifacts/amm-idl.json | 42 ++++++ integration_tests/tests/amm.rs | 13 ++ 12 files changed, 359 insertions(+), 82 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9732e53..7cdfff4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,6 +54,7 @@ name = "amm_program" version = "0.1.0" dependencies = [ "amm_core", + "ata_core", "nssa_core", "token_core", ] diff --git a/amm/Cargo.toml b/amm/Cargo.toml index 04be123..92224e0 100644 --- a/amm/Cargo.toml +++ b/amm/Cargo.toml @@ -6,4 +6,5 @@ edition = "2021" [dependencies] nssa_core = { git = "https://github.com/logos-blockchain/logos-execution-zone.git", tag = "v0.2.0-rc1", features = ["host"] } amm_core = { path = "core" } +ata_core = { path = "../ata/core" } token_core = { path = "../token/core" } diff --git a/amm/core/src/lib.rs b/amm/core/src/lib.rs index eeac604..9a29fb4 100644 --- a/amm/core/src/lib.rs +++ b/amm/core/src/lib.rs @@ -44,13 +44,15 @@ pub enum Instruction { /// - Vault Holding Account for Token A (initialized) /// - Vault Holding Account for Token B (initialized) /// - Pool Liquidity Token Definition (initialized) - /// - User Holding Account for Token A (authorized) - /// - User Holding Account for Token B (authorized) - /// - User Holding Account for Pool Liquidity + /// - Owner account (authorized) + /// - User ATA for Token A + /// - User ATA for Token B + /// - User ATA for Pool Liquidity AddLiquidity { min_amount_liquidity: u128, max_amount_to_add_token_a: u128, max_amount_to_add_token_b: u128, + ata_program_id: ProgramId, }, /// Removes liquidity from the Pool @@ -60,13 +62,15 @@ pub enum Instruction { /// - Vault Holding Account for Token A (initialized) /// - Vault Holding Account for Token B (initialized) /// - Pool Liquidity Token Definition (initialized) - /// - User Holding Account for Token A (initialized) - /// - User Holding Account for Token B (initialized) - /// - User Holding Account for Pool Liquidity (authorized) + /// - Owner account (authorized) + /// - User ATA for Token A (initialized) + /// - User ATA for Token B (initialized) + /// - User ATA for Pool Liquidity RemoveLiquidity { remove_liquidity_amount: u128, min_amount_to_remove_token_a: u128, min_amount_to_remove_token_b: u128, + ata_program_id: ProgramId, }, /// Swap some quantity of Tokens (either Token A or Token B) @@ -76,13 +80,14 @@ pub enum Instruction { /// - AMM Pool (initialized) /// - Vault Holding Account for Token A (initialized) /// - Vault Holding Account for Token B (initialized) - /// - User Holding Account for Token A - /// - User Holding Account for Token B Either User Holding Account for Token A or Token B is - /// authorized. + /// - Owner account (authorized) + /// - User ATA for Token A + /// - User ATA for Token B SwapExactInput { swap_amount_in: u128, min_amount_out: u128, token_definition_id_in: AccountId, + ata_program_id: ProgramId, }, /// Swap tokens specifying the exact desired output amount, @@ -92,13 +97,14 @@ pub enum Instruction { /// - AMM Pool (initialized) /// - Vault Holding Account for Token A (initialized) /// - Vault Holding Account for Token B (initialized) - /// - User Holding Account for Token A - /// - User Holding Account for Token B Either User Holding Account for Token A or Token B is - /// authorized. + /// - Owner account (authorized) + /// - User ATA for Token A + /// - User ATA for Token B SwapExactOutput { exact_amount_out: u128, max_amount_in: u128, token_definition_id_in: AccountId, + ata_program_id: ProgramId, }, /// Sync pool reserves with current vault balances. diff --git a/amm/methods/guest/Cargo.lock b/amm/methods/guest/Cargo.lock index cc8d9a8..a2475c2 100644 --- a/amm/methods/guest/Cargo.lock +++ b/amm/methods/guest/Cargo.lock @@ -35,6 +35,7 @@ version = "0.1.0" dependencies = [ "amm_core", "amm_program", + "ata_core", "borsh", "nssa_core", "risc0-zkvm", @@ -59,6 +60,7 @@ name = "amm_program" version = "0.1.0" dependencies = [ "amm_core", + "ata_core", "nssa_core", "token_core", ] @@ -304,6 +306,16 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "ata_core" +version = "0.1.0" +dependencies = [ + "borsh", + "nssa_core", + "risc0-zkvm", + "serde", +] + [[package]] name = "atomic-waker" version = "1.1.2" diff --git a/amm/methods/guest/Cargo.toml b/amm/methods/guest/Cargo.toml index 385c4ac..5572d1c 100644 --- a/amm/methods/guest/Cargo.toml +++ b/amm/methods/guest/Cargo.toml @@ -14,6 +14,7 @@ spel-framework = { git = "https://github.com/logos-co/spel.git", tag = "v0.2.0-r nssa_core = { git = "https://github.com/logos-blockchain/logos-execution-zone.git", tag = "v0.2.0-rc1" } risc0-zkvm = { version = "=3.0.5", default-features = false } amm_core = { path = "../../core" } +ata_core = { path = "../../../ata/core" } amm_program = { path = "../..", package = "amm_program" } token_core = { path = "../../../token/core" } serde = { version = "1.0", features = ["derive"] } diff --git a/amm/methods/guest/src/bin/amm.rs b/amm/methods/guest/src/bin/amm.rs index 17db95d..62c1cbc 100644 --- a/amm/methods/guest/src/bin/amm.rs +++ b/amm/methods/guest/src/bin/amm.rs @@ -56,24 +56,28 @@ mod amm { vault_a: AccountWithMetadata, vault_b: AccountWithMetadata, pool_definition_lp: AccountWithMetadata, + owner: AccountWithMetadata, user_holding_a: AccountWithMetadata, user_holding_b: AccountWithMetadata, user_holding_lp: AccountWithMetadata, min_amount_liquidity: u128, max_amount_to_add_token_a: u128, max_amount_to_add_token_b: u128, + ata_program_id: ProgramId, ) -> SpelResult { let (post_states, chained_calls) = amm_program::add::add_liquidity( pool, vault_a, vault_b, pool_definition_lp, + owner, user_holding_a, user_holding_b, user_holding_lp, NonZeroU128::new(min_amount_liquidity).expect("min_amount_liquidity must be nonzero"), max_amount_to_add_token_a, max_amount_to_add_token_b, + ata_program_id, ); Ok(SpelOutput::with_chained_calls(post_states, chained_calls)) } @@ -85,18 +89,21 @@ mod amm { vault_a: AccountWithMetadata, vault_b: AccountWithMetadata, pool_definition_lp: AccountWithMetadata, + owner: AccountWithMetadata, user_holding_a: AccountWithMetadata, user_holding_b: AccountWithMetadata, user_holding_lp: AccountWithMetadata, remove_liquidity_amount: u128, min_amount_to_remove_token_a: u128, min_amount_to_remove_token_b: u128, + ata_program_id: ProgramId, ) -> SpelResult { let (post_states, chained_calls) = amm_program::remove::remove_liquidity( pool, vault_a, vault_b, pool_definition_lp, + owner, user_holding_a, user_holding_b, user_holding_lp, @@ -104,6 +111,7 @@ mod amm { .expect("remove_liquidity_amount must be nonzero"), min_amount_to_remove_token_a, min_amount_to_remove_token_b, + ata_program_id, ); Ok(SpelOutput::with_chained_calls(post_states, chained_calls)) } @@ -114,21 +122,25 @@ mod amm { pool: AccountWithMetadata, vault_a: AccountWithMetadata, vault_b: AccountWithMetadata, + owner: AccountWithMetadata, user_holding_a: AccountWithMetadata, user_holding_b: AccountWithMetadata, swap_amount_in: u128, min_amount_out: u128, token_definition_id_in: AccountId, + ata_program_id: ProgramId, ) -> SpelResult { let (post_states, chained_calls) = amm_program::swap::swap_exact_input( pool, vault_a, vault_b, + owner, user_holding_a, user_holding_b, swap_amount_in, min_amount_out, token_definition_id_in, + ata_program_id, ); Ok(SpelOutput::with_chained_calls(post_states, chained_calls)) } @@ -139,21 +151,25 @@ mod amm { pool: AccountWithMetadata, vault_a: AccountWithMetadata, vault_b: AccountWithMetadata, + owner: AccountWithMetadata, user_holding_a: AccountWithMetadata, user_holding_b: AccountWithMetadata, exact_amount_out: u128, max_amount_in: u128, token_definition_id_in: AccountId, + ata_program_id: ProgramId, ) -> SpelResult { let (post_states, chained_calls) = amm_program::swap::swap_exact_output( pool, vault_a, vault_b, + owner, user_holding_a, user_holding_b, exact_amount_out, max_amount_in, token_definition_id_in, + ata_program_id, ); Ok(SpelOutput::with_chained_calls(post_states, chained_calls)) } diff --git a/amm/src/add.rs b/amm/src/add.rs index 1dff79e..3d84329 100644 --- a/amm/src/add.rs +++ b/amm/src/add.rs @@ -6,7 +6,7 @@ use amm_core::{ }; use nssa_core::{ account::{AccountWithMetadata, Data}, - program::{AccountPostState, ChainedCall}, + program::{AccountPostState, ChainedCall, ProgramId}, }; #[expect(clippy::too_many_arguments, reason = "TODO: Fix later")] @@ -15,12 +15,14 @@ pub fn add_liquidity( vault_a: AccountWithMetadata, vault_b: AccountWithMetadata, pool_definition_lp: AccountWithMetadata, + owner: AccountWithMetadata, user_holding_a: AccountWithMetadata, user_holding_b: AccountWithMetadata, user_holding_lp: AccountWithMetadata, min_amount_liquidity: NonZeroU128, max_amount_to_add_token_a: u128, max_amount_to_add_token_b: u128, + ata_program_id: ProgramId, ) -> (Vec, Vec) { // 1. Fetch Pool state let pool_def_data = PoolDefinition::try_from(&pool.account.data) @@ -138,25 +140,27 @@ pub fn add_liquidity( }; pool_post.data = Data::from(&pool_post_definition); - let token_program_id = user_holding_a.account.program_owner; + let token_program_id = vault_a.account.program_owner; - // Chain call for Token A (UserHoldingA -> Vault_A) + // Chain call for Token A (owner's ATA -> Vault_A via ATA program) let call_token_a = ChainedCall::new( - token_program_id, - vec![user_holding_a.clone(), vault_a.clone()], - &token_core::Instruction::Transfer { - amount_to_transfer: actual_amount_a, + ata_program_id, + vec![owner.clone(), user_holding_a.clone(), vault_a.clone()], + &ata_core::Instruction::Transfer { + ata_program_id, + amount: actual_amount_a, }, ); - // Chain call for Token B (UserHoldingB -> Vault_B) + // Chain call for Token B (owner's ATA -> Vault_B via ATA program) let call_token_b = ChainedCall::new( - token_program_id, - vec![user_holding_b.clone(), vault_b.clone()], - &token_core::Instruction::Transfer { - amount_to_transfer: actual_amount_b, + ata_program_id, + vec![owner.clone(), user_holding_b.clone(), vault_b.clone()], + &ata_core::Instruction::Transfer { + ata_program_id, + amount: actual_amount_b, }, ); - // Chain call for LP (mint new tokens for user_holding_lp) + // Chain call for LP (mint new tokens for user's LP ATA) let mut pool_definition_lp_auth = pool_definition_lp.clone(); pool_definition_lp_auth.is_authorized = true; let call_token_lp = ChainedCall::new( @@ -175,6 +179,7 @@ pub fn add_liquidity( AccountPostState::new(vault_a.account.clone()), AccountPostState::new(vault_b.account.clone()), AccountPostState::new(pool_definition_lp.account.clone()), + AccountPostState::new(owner.account.clone()), AccountPostState::new(user_holding_a.account.clone()), AccountPostState::new(user_holding_b.account.clone()), AccountPostState::new(user_holding_lp.account.clone()), diff --git a/amm/src/remove.rs b/amm/src/remove.rs index 951c639..8146be3 100644 --- a/amm/src/remove.rs +++ b/amm/src/remove.rs @@ -1,12 +1,11 @@ use std::num::NonZeroU128; use amm_core::{ - assert_supported_fee_tier, compute_liquidity_token_pda_seed, compute_vault_pda_seed, - PoolDefinition, MINIMUM_LIQUIDITY, + assert_supported_fee_tier, compute_vault_pda_seed, PoolDefinition, MINIMUM_LIQUIDITY, }; use nssa_core::{ account::{AccountWithMetadata, Data}, - program::{AccountPostState, ChainedCall}, + program::{AccountPostState, ChainedCall, ProgramId}, }; #[expect(clippy::too_many_arguments, reason = "TODO: Fix later")] @@ -15,12 +14,14 @@ pub fn remove_liquidity( vault_a: AccountWithMetadata, vault_b: AccountWithMetadata, pool_definition_lp: AccountWithMetadata, + owner: AccountWithMetadata, user_holding_a: AccountWithMetadata, user_holding_b: AccountWithMetadata, user_holding_lp: AccountWithMetadata, remove_liquidity_amount: NonZeroU128, min_amount_to_remove_token_a: u128, min_amount_to_remove_token_b: u128, + ata_program_id: ProgramId, ) -> (Vec, Vec) { let remove_liquidity_amount: u128 = remove_liquidity_amount.into(); @@ -143,9 +144,9 @@ pub fn remove_liquidity( pool_post.data = Data::from(&pool_post_definition); - let token_program_id = user_holding_a.account.program_owner; + let token_program_id = vault_a.account.program_owner; - // Chaincall for Token A withdraw + // Chaincall for Token A withdraw (vault PDA -> user's ATA) let call_token_a = ChainedCall::new( token_program_id, vec![running_vault_a, user_holding_a.clone()], @@ -157,7 +158,7 @@ pub fn remove_liquidity( pool.account_id, pool_def_data.definition_token_a_id, )]); - // Chaincall for Token B withdraw + // Chaincall for Token B withdraw (vault PDA -> user's ATA) let call_token_b = ChainedCall::new( token_program_id, vec![running_vault_b, user_holding_b.clone()], @@ -169,17 +170,19 @@ pub fn remove_liquidity( pool.account_id, pool_def_data.definition_token_b_id, )]); - // Chaincall for LP adjustment - let mut pool_definition_lp_auth = pool_definition_lp.clone(); - pool_definition_lp_auth.is_authorized = true; + // Chaincall for LP burn (owner's LP ATA -> burn via ATA program) let call_token_lp = ChainedCall::new( - token_program_id, - vec![pool_definition_lp_auth, user_holding_lp.clone()], - &token_core::Instruction::Burn { - amount_to_burn: delta_lp, + ata_program_id, + vec![ + owner.clone(), + user_holding_lp.clone(), + pool_definition_lp.clone(), + ], + &ata_core::Instruction::Burn { + ata_program_id, + amount: delta_lp, }, - ) - .with_pda_seeds(vec![compute_liquidity_token_pda_seed(pool.account_id)]); + ); let chained_calls = vec![call_token_lp, call_token_b, call_token_a]; @@ -188,6 +191,7 @@ pub fn remove_liquidity( AccountPostState::new(vault_a.account.clone()), AccountPostState::new(vault_b.account.clone()), AccountPostState::new(pool_definition_lp.account.clone()), + AccountPostState::new(owner.account.clone()), AccountPostState::new(user_holding_a.account.clone()), AccountPostState::new(user_holding_b.account.clone()), AccountPostState::new(user_holding_lp.account.clone()), diff --git a/amm/src/swap.rs b/amm/src/swap.rs index 51c4d80..196824f 100644 --- a/amm/src/swap.rs +++ b/amm/src/swap.rs @@ -4,7 +4,7 @@ use amm_core::{ pub use amm_core::{compute_liquidity_token_pda_seed, compute_vault_pda_seed, PoolDefinition}; use nssa_core::{ account::{AccountId, AccountWithMetadata, Data}, - program::{AccountPostState, ChainedCall}, + program::{AccountPostState, ChainedCall, ProgramId}, }; /// Validates swap setup: checks pool liquidity is ready, vaults match, and reserves are sufficient. @@ -56,6 +56,7 @@ fn create_swap_post_states( pool_def_data: PoolDefinition, vault_a: AccountWithMetadata, vault_b: AccountWithMetadata, + owner: AccountWithMetadata, user_holding_a: AccountWithMetadata, user_holding_b: AccountWithMetadata, deposit_a: u128, @@ -86,6 +87,7 @@ fn create_swap_post_states( AccountPostState::new(pool_post), AccountPostState::new(vault_a.account), AccountPostState::new(vault_b.account), + AccountPostState::new(owner.account), AccountPostState::new(user_holding_a.account), AccountPostState::new(user_holding_b.account), ] @@ -97,17 +99,20 @@ pub fn swap_exact_input( pool: AccountWithMetadata, vault_a: AccountWithMetadata, vault_b: AccountWithMetadata, + owner: AccountWithMetadata, user_holding_a: AccountWithMetadata, user_holding_b: AccountWithMetadata, swap_amount_in: u128, min_amount_out: u128, token_in_id: AccountId, + ata_program_id: ProgramId, ) -> (Vec, Vec) { let pool_def_data = validate_swap_setup(&pool, &vault_a, &vault_b); let (chained_calls, [deposit_a, withdraw_a], [deposit_b, withdraw_b]) = if token_in_id == pool_def_data.definition_token_a_id { let (chained_calls, deposit_a, withdraw_b) = swap_logic( + owner.clone(), user_holding_a.clone(), vault_a.clone(), vault_b.clone(), @@ -118,11 +123,13 @@ pub fn swap_exact_input( pool_def_data.reserve_a, pool_def_data.reserve_b, pool.account_id, + ata_program_id, ); (chained_calls, [deposit_a, 0], [0, withdraw_b]) } else if token_in_id == pool_def_data.definition_token_b_id { let (chained_calls, deposit_b, withdraw_a) = swap_logic( + owner.clone(), user_holding_b.clone(), vault_b.clone(), vault_a.clone(), @@ -133,6 +140,7 @@ pub fn swap_exact_input( pool_def_data.reserve_b, pool_def_data.reserve_a, pool.account_id, + ata_program_id, ); (chained_calls, [0, withdraw_a], [deposit_b, 0]) @@ -145,6 +153,7 @@ pub fn swap_exact_input( pool_def_data, vault_a, vault_b, + owner, user_holding_a, user_holding_b, deposit_a, @@ -158,6 +167,7 @@ pub fn swap_exact_input( #[expect(clippy::too_many_arguments, reason = "TODO: Fix later")] fn swap_logic( + owner: AccountWithMetadata, user_deposit: AccountWithMetadata, vault_deposit: AccountWithMetadata, vault_withdraw: AccountWithMetadata, @@ -168,6 +178,7 @@ fn swap_logic( reserve_deposit_vault_amount: u128, reserve_withdraw_vault_amount: u128, pool_id: AccountId, + ata_program_id: ProgramId, ) -> (Vec, u128, u128) { let effective_amount_in = swap_amount_in .checked_mul(FEE_BPS_DENOMINATOR - fee_bps) @@ -195,14 +206,16 @@ fn swap_logic( ); assert!(withdraw_amount != 0, "Withdraw amount should be nonzero"); - let token_program_id = user_deposit.account.program_owner; + let token_program_id = vault_withdraw.account.program_owner; let mut chained_calls = Vec::new(); + // Deposit: owner's ATA -> vault via ATA program chained_calls.push(ChainedCall::new( - token_program_id, - vec![user_deposit, vault_deposit], - &token_core::Instruction::Transfer { - amount_to_transfer: swap_amount_in, + ata_program_id, + vec![owner, user_deposit, vault_deposit], + &ata_core::Instruction::Transfer { + ata_program_id, + amount: swap_amount_in, }, )); @@ -216,6 +229,7 @@ fn swap_logic( .definition_id(), ); + // Withdrawal: vault PDA -> user's ATA (no ATA auth needed for recipient) chained_calls.push( ChainedCall::new( token_program_id, @@ -236,17 +250,20 @@ pub fn swap_exact_output( pool: AccountWithMetadata, vault_a: AccountWithMetadata, vault_b: AccountWithMetadata, + owner: AccountWithMetadata, user_holding_a: AccountWithMetadata, user_holding_b: AccountWithMetadata, exact_amount_out: u128, max_amount_in: u128, token_in_id: AccountId, + ata_program_id: ProgramId, ) -> (Vec, Vec) { let pool_def_data = validate_swap_setup(&pool, &vault_a, &vault_b); let (chained_calls, [deposit_a, withdraw_a], [deposit_b, withdraw_b]) = if token_in_id == pool_def_data.definition_token_a_id { let (chained_calls, deposit_a, withdraw_b) = exact_output_swap_logic( + owner.clone(), user_holding_a.clone(), vault_a.clone(), vault_b.clone(), @@ -257,11 +274,13 @@ pub fn swap_exact_output( pool_def_data.reserve_b, pool_def_data.fees, pool.account_id, + ata_program_id, ); (chained_calls, [deposit_a, 0], [0, withdraw_b]) } else if token_in_id == pool_def_data.definition_token_b_id { let (chained_calls, deposit_b, withdraw_a) = exact_output_swap_logic( + owner.clone(), user_holding_b.clone(), vault_b.clone(), vault_a.clone(), @@ -272,6 +291,7 @@ pub fn swap_exact_output( pool_def_data.reserve_a, pool_def_data.fees, pool.account_id, + ata_program_id, ); (chained_calls, [0, withdraw_a], [deposit_b, 0]) @@ -284,6 +304,7 @@ pub fn swap_exact_output( pool_def_data, vault_a, vault_b, + owner, user_holding_a, user_holding_b, deposit_a, @@ -297,6 +318,7 @@ pub fn swap_exact_output( #[expect(clippy::too_many_arguments, reason = "TODO: Fix later")] fn exact_output_swap_logic( + owner: AccountWithMetadata, user_deposit: AccountWithMetadata, vault_deposit: AccountWithMetadata, vault_withdraw: AccountWithMetadata, @@ -307,6 +329,7 @@ fn exact_output_swap_logic( reserve_withdraw_vault_amount: u128, fee_bps: u128, pool_id: AccountId, + ata_program_id: ProgramId, ) -> (Vec, u128, u128) { // Guard: exact_amount_out must be nonzero assert_ne!(exact_amount_out, 0, "Exact amount out must be nonzero"); @@ -346,14 +369,16 @@ fn exact_output_swap_logic( "Required input exceeds maximum amount in" ); - let token_program_id = user_deposit.account.program_owner; + let token_program_id = vault_withdraw.account.program_owner; let mut chained_calls = Vec::new(); + // Deposit: owner's ATA -> vault via ATA program chained_calls.push(ChainedCall::new( - token_program_id, - vec![user_deposit, vault_deposit], - &token_core::Instruction::Transfer { - amount_to_transfer: deposit_amount, + ata_program_id, + vec![owner, user_deposit, vault_deposit], + &ata_core::Instruction::Transfer { + ata_program_id, + amount: deposit_amount, }, )); @@ -367,6 +392,7 @@ fn exact_output_swap_logic( .definition_id(), ); + // Withdrawal: vault PDA -> user's ATA (no ATA auth needed for recipient) chained_calls.push( ChainedCall::new( token_program_id, diff --git a/amm/src/tests.rs b/amm/src/tests.rs index 5f7f433..43bae96 100644 --- a/amm/src/tests.rs +++ b/amm/src/tests.rs @@ -24,6 +24,7 @@ use crate::{ const TOKEN_PROGRAM_ID: ProgramId = [15; 8]; const AMM_PROGRAM_ID: ProgramId = [42; 8]; +const ATA_PROGRAM_ID: ProgramId = [99; 8]; struct BalanceForTests; struct ChainedCallForTests; @@ -224,13 +225,15 @@ impl BalanceForTests { impl ChainedCallForTests { fn cc_swap_token_a_test_1() -> ChainedCall { ChainedCall::new( - TOKEN_PROGRAM_ID, + ATA_PROGRAM_ID, vec![ + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::vault_a_init(), ], - &token_core::Instruction::Transfer { - amount_to_transfer: BalanceForTests::add_max_amount_a(), + &ata_core::Instruction::Transfer { + ata_program_id: ATA_PROGRAM_ID, + amount: BalanceForTests::add_max_amount_a(), }, ) } @@ -275,13 +278,15 @@ impl ChainedCallForTests { fn cc_swap_token_b_test_2() -> ChainedCall { ChainedCall::new( - TOKEN_PROGRAM_ID, + ATA_PROGRAM_ID, vec![ + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::vault_b_init(), ], - &token_core::Instruction::Transfer { - amount_to_transfer: BalanceForTests::add_max_amount_b(), + &ata_core::Instruction::Transfer { + ata_program_id: ATA_PROGRAM_ID, + amount: BalanceForTests::add_max_amount_b(), }, ) } @@ -293,13 +298,15 @@ impl ChainedCallForTests { let swap_amount: u128 = 500; ChainedCall::new( - TOKEN_PROGRAM_ID, + ATA_PROGRAM_ID, vec![ + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::vault_a_init(), ], - &token_core::Instruction::Transfer { - amount_to_transfer: swap_amount, + &ata_core::Instruction::Transfer { + ata_program_id: ATA_PROGRAM_ID, + amount: swap_amount, }, ) } @@ -349,26 +356,30 @@ impl ChainedCallForTests { let swap_amount: u128 = 201; ChainedCall::new( - TOKEN_PROGRAM_ID, + ATA_PROGRAM_ID, vec![ + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::vault_b_init(), ], - &token_core::Instruction::Transfer { - amount_to_transfer: swap_amount, + &ata_core::Instruction::Transfer { + ata_program_id: ATA_PROGRAM_ID, + amount: swap_amount, }, ) } fn cc_swap_rounding_boundary_token_a_in() -> ChainedCall { ChainedCall::new( - TOKEN_PROGRAM_ID, + ATA_PROGRAM_ID, vec![ + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::vault_a_init(), ], - &token_core::Instruction::Transfer { - amount_to_transfer: 3, + &ata_core::Instruction::Transfer { + ata_program_id: ATA_PROGRAM_ID, + amount: 3, }, ) } @@ -392,26 +403,30 @@ impl ChainedCallForTests { fn cc_add_token_a() -> ChainedCall { ChainedCall::new( - TOKEN_PROGRAM_ID, + ATA_PROGRAM_ID, vec![ + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::vault_a_init(), ], - &token_core::Instruction::Transfer { - amount_to_transfer: BalanceForTests::add_successful_amount_a(), + &ata_core::Instruction::Transfer { + ata_program_id: ATA_PROGRAM_ID, + amount: BalanceForTests::add_successful_amount_a(), }, ) } fn cc_add_token_b() -> ChainedCall { ChainedCall::new( - TOKEN_PROGRAM_ID, + ATA_PROGRAM_ID, vec![ + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::vault_b_init(), ], - &token_core::Instruction::Transfer { - amount_to_transfer: BalanceForTests::add_successful_amount_b(), + &ata_core::Instruction::Transfer { + ata_program_id: ATA_PROGRAM_ID, + amount: BalanceForTests::add_successful_amount_b(), }, ) } @@ -470,22 +485,18 @@ impl ChainedCallForTests { } fn cc_remove_pool_lp() -> ChainedCall { - let mut pool_lp_auth = AccountWithMetadataForTests::pool_lp_init(); - pool_lp_auth.is_authorized = true; - ChainedCall::new( - TOKEN_PROGRAM_ID, + ATA_PROGRAM_ID, vec![ - pool_lp_auth, + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_lp_init(), + AccountWithMetadataForTests::pool_lp_init(), ], - &token_core::Instruction::Burn { - amount_to_burn: BalanceForTests::remove_amount_lp(), + &ata_core::Instruction::Burn { + ata_program_id: ATA_PROGRAM_ID, + amount: BalanceForTests::remove_amount_lp(), }, ) - .with_pda_seeds(vec![compute_liquidity_token_pda_seed( - IdForTests::pool_definition_id(), - )]) } fn cc_new_definition_token_a() -> ChainedCall { @@ -611,6 +622,10 @@ impl IdForTests { IdForTests::token_b_definition_id(), ) } + + fn owner_id() -> AccountId { + AccountId::new([48; 32]) + } } impl AccountWithMetadataForTests { @@ -1370,6 +1385,19 @@ impl AccountWithMetadataForTests { account_id: IdForTests::pool_definition_id(), } } + + fn owner() -> AccountWithMetadata { + AccountWithMetadata { + account: Account { + program_owner: ProgramId::default(), + balance: 0u128, + data: Data::default(), + nonce: Nonce(0), + }, + is_authorized: true, + account_id: IdForTests::owner_id(), + } + } } #[test] @@ -1395,12 +1423,14 @@ fn test_call_add_liquidity_vault_a_omitted() { AccountWithMetadataForTests::vault_a_with_wrong_id(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), + ATA_PROGRAM_ID, ); } @@ -1412,12 +1442,14 @@ fn test_call_add_liquidity_vault_b_omitted() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_with_wrong_id(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), + ATA_PROGRAM_ID, ); } @@ -1429,12 +1461,14 @@ fn test_call_add_liquidity_lp_definition_mismatch() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_with_wrong_id(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), + ATA_PROGRAM_ID, ); } @@ -1446,12 +1480,14 @@ fn test_call_add_liquidity_zero_balance_1() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), 0, BalanceForTests::add_max_amount_b(), + ATA_PROGRAM_ID, ); } @@ -1463,12 +1499,14 @@ fn test_call_add_liquidity_zero_balance_2() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), 0, BalanceForTests::add_max_amount_a(), + ATA_PROGRAM_ID, ); } @@ -1480,12 +1518,14 @@ fn test_call_add_liquidity_vault_a_balance_below_reserve() { AccountWithMetadataForTests::vault_a_init_low(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), + ATA_PROGRAM_ID, ); } @@ -1497,12 +1537,14 @@ fn test_call_add_liquidity_vault_b_balance_below_reserve() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init_low(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), + ATA_PROGRAM_ID, ); } @@ -1514,12 +1556,14 @@ fn test_call_add_liquidity_vault_insufficient_balance_1() { AccountWithMetadataForTests::vault_a_init_zero(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), + ATA_PROGRAM_ID, ); } @@ -1531,12 +1575,14 @@ fn test_call_add_liquidity_vault_insufficient_balance_2() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init_zero(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), + ATA_PROGRAM_ID, ); } @@ -1548,12 +1594,14 @@ fn test_call_add_liquidity_actual_amount_zero_1() { AccountWithMetadataForTests::vault_a_init_low(), AccountWithMetadataForTests::vault_b_init_high(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), + ATA_PROGRAM_ID, ); } @@ -1565,12 +1613,14 @@ fn test_call_add_liquidity_actual_amount_zero_2() { AccountWithMetadataForTests::vault_a_init_high(), AccountWithMetadataForTests::vault_b_init_low(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), BalanceForTests::add_max_amount_a_low(), BalanceForTests::add_max_amount_b_low(), + ATA_PROGRAM_ID, ); } @@ -1582,12 +1632,14 @@ fn test_call_add_liquidity_reserves_zero_1() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), + ATA_PROGRAM_ID, ); } @@ -1599,12 +1651,14 @@ fn test_call_add_liquidity_reserves_zero_2() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), + ATA_PROGRAM_ID, ); } @@ -1616,12 +1670,14 @@ fn test_call_add_liquidity_payable_lp_zero() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), BalanceForTests::add_max_amount_a_low(), BalanceForTests::add_max_amount_b_low(), + ATA_PROGRAM_ID, ); } @@ -1632,12 +1688,14 @@ fn test_call_add_liquidity_chained_call_successsful() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::add_min_amount_lp()).unwrap(), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_b(), + ATA_PROGRAM_ID, ); let pool_post = post_states[0].clone(); @@ -1664,12 +1722,14 @@ fn test_call_remove_liquidity_vault_a_omitted() { AccountWithMetadataForTests::vault_a_with_wrong_id(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(), BalanceForTests::remove_min_amount_a(), BalanceForTests::remove_min_amount_b(), + ATA_PROGRAM_ID, ); } @@ -1681,12 +1741,14 @@ fn test_call_remove_liquidity_vault_b_omitted() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_with_wrong_id(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(), BalanceForTests::remove_min_amount_a(), BalanceForTests::remove_min_amount_b(), + ATA_PROGRAM_ID, ); } @@ -1698,12 +1760,14 @@ fn test_call_remove_liquidity_lp_def_mismatch() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_with_wrong_id(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(), BalanceForTests::remove_min_amount_a(), BalanceForTests::remove_min_amount_b(), + ATA_PROGRAM_ID, ); } @@ -1715,6 +1779,7 @@ fn test_call_remove_liquidity_insufficient_liquidity_amount() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_a(), /* different token account than lp to @@ -1723,6 +1788,7 @@ fn test_call_remove_liquidity_insufficient_liquidity_amount() { NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(), BalanceForTests::remove_min_amount_a(), BalanceForTests::remove_min_amount_b(), + ATA_PROGRAM_ID, ); } @@ -1736,12 +1802,14 @@ fn test_call_remove_liquidity_insufficient_balance_1() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::remove_amount_lp_1()).unwrap(), BalanceForTests::remove_min_amount_a(), BalanceForTests::remove_min_amount_b(), + ATA_PROGRAM_ID, ); } @@ -1754,12 +1822,14 @@ fn test_call_remove_liquidity_pool_at_minimum_liquidity() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_with_balance(MINIMUM_LIQUIDITY), NonZero::new(MINIMUM_LIQUIDITY).unwrap(), 1, 1, + ATA_PROGRAM_ID, ); } @@ -1774,12 +1844,14 @@ fn test_call_remove_liquidity_exceeds_unlocked_supply() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), 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(), 1, 1, + ATA_PROGRAM_ID, ); } @@ -1793,12 +1865,14 @@ fn test_call_remove_liquidity_insufficient_balance_2() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(), BalanceForTests::remove_min_amount_a(), BalanceForTests::remove_min_amount_b(), + ATA_PROGRAM_ID, ); } @@ -1810,12 +1884,14 @@ fn test_call_remove_liquidity_min_bal_zero_1() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(), 0, BalanceForTests::remove_min_amount_b(), + ATA_PROGRAM_ID, ); } @@ -1827,12 +1903,14 @@ fn test_call_remove_liquidity_min_bal_zero_2() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(), BalanceForTests::remove_min_amount_a(), 0, + ATA_PROGRAM_ID, ); } @@ -1843,12 +1921,14 @@ fn test_call_remove_liquidity_chained_call_successful() { AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(BalanceForTests::remove_amount_lp()).unwrap(), BalanceForTests::remove_min_amount_a(), BalanceForTests::remove_min_amount_b_low(), + ATA_PROGRAM_ID, ); let pool_post = post_states[0].clone(); @@ -2105,11 +2185,13 @@ fn test_call_swap_incorrect_token_type() { AccountWithMetadataForTests::pool_definition_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), BalanceForTests::add_max_amount_a(), BalanceForTests::min_amount_out(), IdForTests::token_lp_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2120,11 +2202,13 @@ fn test_call_swap_vault_a_omitted() { AccountWithMetadataForTests::pool_definition_init(), AccountWithMetadataForTests::vault_a_with_wrong_id(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), BalanceForTests::add_max_amount_a(), BalanceForTests::min_amount_out(), IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2135,11 +2219,13 @@ fn test_call_swap_vault_b_omitted() { AccountWithMetadataForTests::pool_definition_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_with_wrong_id(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), BalanceForTests::add_max_amount_a(), BalanceForTests::min_amount_out(), IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2150,11 +2236,13 @@ fn test_call_swap_reserves_vault_mismatch_1() { AccountWithMetadataForTests::pool_definition_init(), AccountWithMetadataForTests::vault_a_init_low(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), BalanceForTests::add_max_amount_a(), BalanceForTests::min_amount_out(), IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2165,11 +2253,13 @@ fn test_call_swap_reserves_vault_mismatch_2() { AccountWithMetadataForTests::pool_definition_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init_low(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), BalanceForTests::add_max_amount_a(), BalanceForTests::min_amount_out(), IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2180,11 +2270,13 @@ fn test_call_swap_below_minimum_liquidity() { AccountWithMetadataForTests::pool_definition_below_minimum_liquidity(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), BalanceForTests::add_max_amount_a(), BalanceForTests::min_amount_out(), IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2200,11 +2292,13 @@ fn test_call_swap_rejects_unsupported_fee_tier() { pool, AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_a_low(), IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2215,11 +2309,13 @@ fn test_call_swap_below_min_out() { AccountWithMetadataForTests::pool_definition_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), BalanceForTests::add_max_amount_a(), BalanceForTests::min_amount_out_too_high(), IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2230,11 +2326,13 @@ fn test_call_swap_effective_amount_zero() { AccountWithMetadataForTests::pool_definition_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), 1, 0, IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2245,11 +2343,13 @@ fn test_call_swap_output_rounds_to_zero() { AccountWithMetadataForTests::pool_definition_init_low_balances(), AccountWithMetadataForTests::vault_a_init_low(), AccountWithMetadataForTests::vault_b_init_low(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), 2, 0, IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2260,11 +2360,13 @@ fn test_call_swap_exact_input_rejects_amount_that_rounds_down_below_target_outpu AccountWithMetadataForTests::pool_definition_swap_rounding_boundary_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), 2, 1, IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2274,11 +2376,13 @@ fn test_call_swap_exact_input_accepts_smallest_amount_for_rounded_boundary() { AccountWithMetadataForTests::pool_definition_swap_rounding_boundary_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), 3, 1, IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); let pool_post = post_states[0].clone(); @@ -2307,11 +2411,13 @@ fn test_call_swap_chained_call_successful_1() { AccountWithMetadataForTests::pool_definition_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), BalanceForTests::add_max_amount_a(), BalanceForTests::add_max_amount_a_low(), IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); let pool_post = post_states[0].clone(); @@ -2339,11 +2445,13 @@ fn test_call_swap_chained_call_successful_2() { AccountWithMetadataForTests::pool_definition_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), BalanceForTests::add_max_amount_b(), BalanceForTests::min_amount_out(), IdForTests::token_b_definition_id(), + ATA_PROGRAM_ID, ); let pool_post = post_states[0].clone(); @@ -2372,11 +2480,13 @@ fn call_swap_exact_output_incorrect_token_type() { AccountWithMetadataForTests::pool_definition_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), BalanceForTests::add_max_amount_a(), BalanceForTests::max_amount_in(), IdForTests::token_lp_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2387,11 +2497,13 @@ fn call_swap_exact_output_vault_a_omitted() { AccountWithMetadataForTests::pool_definition_init(), AccountWithMetadataForTests::vault_a_with_wrong_id(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), BalanceForTests::add_max_amount_a(), BalanceForTests::max_amount_in(), IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2402,11 +2514,13 @@ fn call_swap_exact_output_vault_b_omitted() { AccountWithMetadataForTests::pool_definition_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_with_wrong_id(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), BalanceForTests::add_max_amount_a(), BalanceForTests::max_amount_in(), IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2417,11 +2531,13 @@ fn call_swap_exact_output_reserves_vault_mismatch_1() { AccountWithMetadataForTests::pool_definition_init(), AccountWithMetadataForTests::vault_a_init_low(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), BalanceForTests::add_max_amount_a(), BalanceForTests::max_amount_in(), IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2432,11 +2548,13 @@ fn call_swap_exact_output_reserves_vault_mismatch_2() { AccountWithMetadataForTests::pool_definition_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init_low(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), BalanceForTests::add_max_amount_a(), BalanceForTests::max_amount_in(), IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2447,11 +2565,13 @@ fn call_swap_exact_output_below_minimum_liquidity() { AccountWithMetadataForTests::pool_definition_below_minimum_liquidity(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), BalanceForTests::add_max_amount_a(), BalanceForTests::max_amount_in(), IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2462,11 +2582,13 @@ fn call_swap_exact_output_exceeds_max_in() { AccountWithMetadataForTests::pool_definition_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), 166_u128, 100_u128, IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2477,11 +2599,13 @@ fn call_swap_exact_output_zero() { AccountWithMetadataForTests::pool_definition_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), 0_u128, 500_u128, IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2492,11 +2616,13 @@ fn call_swap_exact_output_exceeds_reserve() { AccountWithMetadataForTests::pool_definition_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), BalanceForTests::vault_b_reserve_init(), BalanceForTests::max_amount_in(), IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2506,11 +2632,13 @@ fn call_swap_exact_output_chained_call_successful() { AccountWithMetadataForTests::pool_definition_swap_exact_output_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), BalanceForTests::max_amount_in(), BalanceForTests::vault_b_reserve_init(), IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); let pool_post = post_states[0].clone(); @@ -2539,11 +2667,13 @@ fn call_swap_exact_output_chained_call_successful_2() { AccountWithMetadataForTests::pool_definition_swap_exact_output_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), 285, 300, IdForTests::token_b_definition_id(), + ATA_PROGRAM_ID, ); let pool_post = post_states[0].clone(); @@ -2575,11 +2705,13 @@ fn call_swap_exact_output_fee_enforced() { AccountWithMetadataForTests::pool_definition_swap_exact_output_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), 166_u128, // exact_amount_out: token_b 499_u128, // max_amount_in: still one short after fee rounding IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2593,11 +2725,13 @@ fn call_swap_exact_output_rejects_max_in_that_rounds_down_below_target_output() AccountWithMetadataForTests::pool_definition_swap_rounding_boundary_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), 1, 2, IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2607,11 +2741,13 @@ fn call_swap_exact_output_accepts_smallest_max_in_for_rounded_boundary() { AccountWithMetadataForTests::pool_definition_swap_rounding_boundary_init(), AccountWithMetadataForTests::vault_a_init(), AccountWithMetadataForTests::vault_b_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), 1, 3, IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); let pool_post = post_states[0].clone(); @@ -2698,12 +2834,14 @@ fn swap_exact_output_overflow_protection() { pool, vault_a, vault_b, + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), 2, // exact_amount_out: small, valid (< reserve_b) 1, // max_amount_in: tiny — real deposit would be enormous, but // overflow wraps it to 0, making 0 <= 1 pass silently IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } @@ -2876,12 +3014,14 @@ fn test_minimum_liquidity_lock_and_remove_all_user_lp() { AccountForTests::vault_a_init(), AccountForTests::vault_b_init(), AccountForTests::pool_lp_init(), + AccountForTests::owner(), AccountForTests::user_holding_a(), AccountForTests::user_holding_b(), AccountForTests::user_holding_lp_with_balance(user_lp), NonZero::new(user_lp).unwrap(), 1, 1, + ATA_PROGRAM_ID, ); let pool_after_remove = @@ -2966,12 +3106,14 @@ fn test_donation_then_add_liquidity_sync_mitigates_mispricing() { donated_vault_a.clone(), donated_vault_b.clone(), AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(1).unwrap(), 100, 50, + ATA_PROGRAM_ID, ); let unsynced_pool_post = PoolDefinition::try_from(&post_unsynced[0].account().data).unwrap(); let unsynced_delta_lp = @@ -2996,12 +3138,14 @@ fn test_donation_then_add_liquidity_sync_mitigates_mispricing() { donated_vault_a_for_synced_add, donated_vault_b_for_synced_add, AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(1).unwrap(), 100, 50, + ATA_PROGRAM_ID, ); let synced_pool_post = PoolDefinition::try_from(&post_synced[0].account().data).unwrap(); let synced_delta_lp = synced_pool_post.liquidity_pool_supply @@ -3093,12 +3237,14 @@ fn add_liquidity_overflow_protection() { vault_a, vault_b, AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), AccountWithMetadataForTests::user_holding_lp_init(), NonZero::new(1).unwrap(), 500, 2, // max_amount_b=2 → reserve_a * 2 overflows + ATA_PROGRAM_ID, ); } @@ -3177,12 +3323,14 @@ fn remove_liquidity_overflow_protection() { vault_a, vault_b, AccountWithMetadataForTests::pool_lp_init(), + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), user_lp, NonZero::new(2).unwrap(), // remove_amount=2 → reserve_a * 2 overflows 1, 1, + ATA_PROGRAM_ID, ); } @@ -3248,11 +3396,13 @@ fn swap_exact_input_overflow_protection() { pool, vault_a, vault_b, + AccountWithMetadataForTests::owner(), AccountWithMetadataForTests::user_holding_a(), AccountWithMetadataForTests::user_holding_b(), 3, 1, IdForTests::token_a_definition_id(), + ATA_PROGRAM_ID, ); } diff --git a/artifacts/amm-idl.json b/artifacts/amm-idl.json index 3003f2f..ffbd256 100644 --- a/artifacts/amm-idl.json +++ b/artifacts/amm-idl.json @@ -1,3 +1,5 @@ + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.53s + Running `target/debug/idl-gen amm/methods/guest/src/bin/amm.rs` { "version": "0.1.0", "name": "amm", @@ -100,6 +102,12 @@ "signer": false, "init": false }, + { + "name": "owner", + "writable": false, + "signer": false, + "init": false + }, { "name": "user_holding_a", "writable": false, @@ -131,6 +139,10 @@ { "name": "max_amount_to_add_token_b", "type": "u128" + }, + { + "name": "ata_program_id", + "type": "program_id" } ] }, @@ -161,6 +173,12 @@ "signer": false, "init": false }, + { + "name": "owner", + "writable": false, + "signer": false, + "init": false + }, { "name": "user_holding_a", "writable": false, @@ -192,6 +210,10 @@ { "name": "min_amount_to_remove_token_b", "type": "u128" + }, + { + "name": "ata_program_id", + "type": "program_id" } ] }, @@ -216,6 +238,12 @@ "signer": false, "init": false }, + { + "name": "owner", + "writable": false, + "signer": false, + "init": false + }, { "name": "user_holding_a", "writable": false, @@ -241,6 +269,10 @@ { "name": "token_definition_id_in", "type": "account_id" + }, + { + "name": "ata_program_id", + "type": "program_id" } ] }, @@ -265,6 +297,12 @@ "signer": false, "init": false }, + { + "name": "owner", + "writable": false, + "signer": false, + "init": false + }, { "name": "user_holding_a", "writable": false, @@ -290,6 +328,10 @@ { "name": "token_definition_id_in", "type": "account_id" + }, + { + "name": "ata_program_id", + "type": "program_id" } ] }, diff --git a/integration_tests/tests/amm.rs b/integration_tests/tests/amm.rs index d121029..87ad3ef 100644 --- a/integration_tests/tests/amm.rs +++ b/integration_tests/tests/amm.rs @@ -38,6 +38,10 @@ impl Ids { amm_methods::AMM_ID } + fn ata_program() -> nssa_core::program::ProgramId { + ata_methods::ATA_ID + } + fn token_a_definition() -> AccountId { AccountId::new([3; 32]) } @@ -1018,6 +1022,7 @@ fn execute_swap_a_to_b(state: &mut V03State, swap_amount_in: u128, min_amount_ou swap_amount_in, min_amount_out, token_definition_id_in: Ids::token_a_definition(), + ata_program_id: Ids::ata_program(), }; let message = public_transaction::Message::try_new( @@ -1045,6 +1050,7 @@ fn execute_swap_b_to_a(state: &mut V03State, swap_amount_in: u128, min_amount_ou swap_amount_in, min_amount_out, token_definition_id_in: Ids::token_b_definition(), + ata_program_id: Ids::ata_program(), }; let message = public_transaction::Message::try_new( @@ -1077,6 +1083,7 @@ fn execute_add_liquidity( min_amount_liquidity, max_amount_to_add_token_a, max_amount_to_add_token_b, + ata_program_id: Ids::ata_program(), }; let message = public_transaction::Message::try_new( @@ -1115,6 +1122,7 @@ fn execute_remove_liquidity( remove_liquidity_amount, min_amount_to_remove_token_a, min_amount_to_remove_token_b, + ata_program_id: Ids::ata_program(), }; let message = public_transaction::Message::try_new( @@ -1178,6 +1186,7 @@ fn amm_remove_liquidity() { remove_liquidity_amount: Balances::remove_lp(), min_amount_to_remove_token_a: Balances::remove_min_a(), min_amount_to_remove_token_b: Balances::remove_min_b(), + ata_program_id: Ids::ata_program(), }; let message = public_transaction::Message::try_new( @@ -1240,6 +1249,7 @@ fn amm_remove_liquidity_insufficient_user_lp_fails() { remove_liquidity_amount: Balances::remove_lp(), min_amount_to_remove_token_a: Balances::remove_min_a(), min_amount_to_remove_token_b: Balances::remove_min_b(), + ata_program_id: Ids::ata_program(), }; let message = public_transaction::Message::try_new( @@ -1464,6 +1474,7 @@ fn amm_add_liquidity() { min_amount_liquidity: Balances::add_min_lp(), max_amount_to_add_token_a: Balances::add_max_a(), max_amount_to_add_token_b: Balances::add_max_b(), + ata_program_id: Ids::ata_program(), }; let message = public_transaction::Message::try_new( @@ -1526,6 +1537,7 @@ fn amm_swap_b_to_a() { swap_amount_in: Balances::swap_amount_in(), min_amount_out: Balances::swap_min_out(), token_definition_id_in: Ids::token_b_definition(), + ata_program_id: Ids::ata_program(), }; let message = public_transaction::Message::try_new( @@ -1577,6 +1589,7 @@ fn amm_swap_a_to_b() { swap_amount_in: Balances::swap_amount_in(), min_amount_out: Balances::swap_min_out(), token_definition_id_in: Ids::token_a_definition(), + ata_program_id: Ids::ata_program(), }; let message = public_transaction::Message::try_new( From e41d8476670e62c05ffb1b237d69ba87c41fcf50 Mon Sep 17 00:00:00 2001 From: Ricardo Guilherme Schmidt <3esmit@gmail.com> Date: Thu, 23 Apr 2026 11:28:10 -0300 Subject: [PATCH 2/2] Add malicious ATA methods and corresponding integration tests - Introduced a new Cargo.toml for the malicious ATA guest program. - Implemented malicious ATA methods in `malicious_ata.rs`, including create, transfer, and burn functions that simulate malicious behavior. - Updated the integration test suite to include tests for the malicious ATA program, ensuring it is rejected in various value paths. - Enhanced existing tests to accommodate the new malicious ATA program and verify that it does not affect the expected state of the AMM. --- Cargo.lock | 10 + Cargo.toml | 2 + integration_tests/Cargo.toml | 1 + .../malicious_ata_methods/Cargo.toml | 14 + .../malicious_ata_methods/build.rs | 3 + .../malicious_ata_methods/guest/Cargo.lock | 4020 +++++++++++++++++ .../malicious_ata_methods/guest/Cargo.toml | 18 + .../guest/src/bin/malicious_ata.rs | 78 + .../malicious_ata_methods/src/lib.rs | 1 + integration_tests/tests/amm.rs | 445 +- 10 files changed, 4576 insertions(+), 16 deletions(-) create mode 100644 integration_tests/malicious_ata_methods/Cargo.toml create mode 100644 integration_tests/malicious_ata_methods/build.rs create mode 100644 integration_tests/malicious_ata_methods/guest/Cargo.lock create mode 100644 integration_tests/malicious_ata_methods/guest/Cargo.toml create mode 100644 integration_tests/malicious_ata_methods/guest/src/bin/malicious_ata.rs create mode 100644 integration_tests/malicious_ata_methods/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 7cdfff4..e2f96c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1595,6 +1595,7 @@ dependencies = [ "amm_core", "ata-methods", "ata_core", + "malicious-ata-methods", "nssa", "nssa_core", "token-methods", @@ -1758,6 +1759,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "malicious-ata-methods" +version = "0.1.0" +dependencies = [ + "ata_core", + "risc0-build", + "risc0-zkvm", +] + [[package]] name = "malloc_buf" version = "0.0.6" diff --git a/Cargo.toml b/Cargo.toml index 7021e21..ccceac4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,12 +10,14 @@ members = [ "ata", "ata/methods", "integration_tests", + "integration_tests/malicious_ata_methods", "tools/idl-gen", ] exclude = [ "token/methods/guest", "amm/methods/guest", "ata/methods/guest", + "integration_tests/malicious_ata_methods/guest", ] resolver = "2" diff --git a/integration_tests/Cargo.toml b/integration_tests/Cargo.toml index 3254cdc..cafe0aa 100644 --- a/integration_tests/Cargo.toml +++ b/integration_tests/Cargo.toml @@ -12,3 +12,4 @@ ata_core = { workspace = true } token-methods = { path = "../token/methods" } amm-methods = { path = "../amm/methods" } ata-methods = { path = "../ata/methods" } +malicious-ata-methods = { path = "malicious_ata_methods" } diff --git a/integration_tests/malicious_ata_methods/Cargo.toml b/integration_tests/malicious_ata_methods/Cargo.toml new file mode 100644 index 0000000..dd1d16b --- /dev/null +++ b/integration_tests/malicious_ata_methods/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "malicious-ata-methods" +version = "0.1.0" +edition = "2021" + +[build-dependencies] +risc0-build = "=3.0.5" + +[dependencies] +risc0-zkvm = { version = "=3.0.5", features = ["std"] } +ata_core = { path = "../../ata/core" } + +[package.metadata.risc0] +methods = ["guest"] diff --git a/integration_tests/malicious_ata_methods/build.rs b/integration_tests/malicious_ata_methods/build.rs new file mode 100644 index 0000000..08a8a4e --- /dev/null +++ b/integration_tests/malicious_ata_methods/build.rs @@ -0,0 +1,3 @@ +fn main() { + risc0_build::embed_methods(); +} diff --git a/integration_tests/malicious_ata_methods/guest/Cargo.lock b/integration_tests/malicious_ata_methods/guest/Cargo.lock new file mode 100644 index 0000000..acea6cc --- /dev/null +++ b/integration_tests/malicious_ata_methods/guest/Cargo.lock @@ -0,0 +1,4020 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "ark-bn254" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d69eab57e8d2663efa5c63135b2af4f396d66424f88954c21104125ab6b3e6bc" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-r1cs-std", + "ark-std", +] + +[[package]] +name = "ark-crypto-primitives" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0c292754729c8a190e50414fd1a37093c786c709899f29c9f7daccecfa855e" +dependencies = [ + "ahash", + "ark-crypto-primitives-macros", + "ark-ec", + "ark-ff", + "ark-relations", + "ark-serialize", + "ark-snark", + "ark-std", + "blake2", + "derivative", + "digest", + "fnv", + "merlin", + "sha2", +] + +[[package]] +name = "ark-crypto-primitives-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e89fe77d1f0f4fe5b96dfc940923d88d17b6a773808124f21e764dfb063c6a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-ec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" +dependencies = [ + "ahash", + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "educe", + "fnv", + "hashbrown 0.15.5", + "itertools 0.13.0", + "num-bigint", + "num-integer", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "arrayvec", + "digest", + "educe", + "itertools 0.13.0", + "num-bigint", + "num-traits", + "paste", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-ff-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-groth16" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88f1d0f3a534bb54188b8dcc104307db6c56cdae574ddc3212aec0625740fc7e" +dependencies = [ + "ark-crypto-primitives", + "ark-ec", + "ark-ff", + "ark-poly", + "ark-relations", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-poly" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579305839da207f02b89cd1679e50e67b4331e2f9294a57693e5051b7703fe27" +dependencies = [ + "ahash", + "ark-ff", + "ark-serialize", + "ark-std", + "educe", + "fnv", + "hashbrown 0.15.5", +] + +[[package]] +name = "ark-r1cs-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "941551ef1df4c7a401de7068758db6503598e6f01850bdb2cfdb614a1f9dbea1" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-relations", + "ark-std", + "educe", + "num-bigint", + "num-integer", + "num-traits", + "tracing", +] + +[[package]] +name = "ark-relations" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec46ddc93e7af44bcab5230937635b06fb5744464dd6a7e7b083e80ebd274384" +dependencies = [ + "ark-ff", + "ark-std", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "ark-serialize" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "arrayvec", + "digest", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-snark" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d368e2848c2d4c129ce7679a7d0d2d612b6a274d3ea6a13bad4445d61b381b88" +dependencies = [ + "ark-ff", + "ark-relations", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" +dependencies = [ + "num-traits", + "rand 0.8.6", +] + +[[package]] +name = "arraydeque" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "ata_core" +version = "0.1.0" +dependencies = [ + "borsh", + "nssa_core", + "risc0-zkvm", + "serde", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base58" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "bonsai-sdk" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a381a5f681e536070483826412fcfcd6f6637921717c6aa0a3759926899ee9c2" +dependencies = [ + "duplicate", + "maybe-async", + "reqwest", + "serde", + "thiserror 2.0.18", +] + +[[package]] +name = "borsh" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" +dependencies = [ + "borsh-derive", + "bytes", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" +dependencies = [ + "once_cell", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +dependencies = [ + "serde", +] + +[[package]] +name = "bytesize" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bd91ee7b2422bcb158d90ef4d14f75ef67f340943fc4149891dcce8f8b972a3" +dependencies = [ + "serde_core", +] + +[[package]] +name = "camino" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror 2.0.18", +] + +[[package]] +name = "cc" +version = "1.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures 0.3.0", +] + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "num-traits", + "serde", + "windows-link", +] + +[[package]] +name = "cipher" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e34d8227fe1ba289043aeb13792056ff80fd6de1a9f49137a5f499de8e8c78ea" +dependencies = [ + "block-buffer 0.12.0", + "crypto-common 0.2.1", + "inout", +] + +[[package]] +name = "cobs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror 2.0.18", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "crypto-common" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core 0.23.0", + "darling_macro 0.23.0", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core 0.20.11", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core 0.23.0", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", + "serde_core", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling 0.20.11", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn 2.0.117", +] + +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.117", + "unicode-xid", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common 0.1.6", + "subtle", +] + +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.61.2", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "docker-generate" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf673e0848ef09fa4aeeba78e681cf651c0c7d35f76ee38cec8e55bc32fa111" + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "duplicate" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e92f10a49176cbffacaedabfaa11d51db1ea0f80a83c26e1873b43cd1742c24" +dependencies = [ + "heck", + "proc-macro2", + "proc-macro2-diagnostics", +] + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "serdect", + "signature", + "spki", +] + +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "elf" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "pem-rfc7468", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum-ordinalize" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "wasip2", + "wasip3", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.5", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hybrid-array" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" +dependencies = [ + "typenum", +] + +[[package]] +name = "hyper" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" + +[[package]] +name = "icu_properties" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" + +[[package]] +name = "icu_provider" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "include_bytes_aligned" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee796ad498c8d9a1d68e477df8f754ed784ef875de1414ebdaf169f70a6a784" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.0", + "serde", + "serde_core", +] + +[[package]] +name = "inout" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "iri-string" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "js-sys" +version = "0.3.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "serdect", + "sha2", + "signature", +] + +[[package]] +name = "keccak" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" +dependencies = [ + "cpufeatures 0.2.17", +] + +[[package]] +name = "lazy-regex" +version = "3.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bae91019476d3ec7147de9aa291cadb6d870abf2f3015d2da73a90325ac1496" +dependencies = [ + "lazy-regex-proc_macros", + "once_cell", + "regex", +] + +[[package]] +name = "lazy-regex-proc_macros" +version = "3.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4de9c1e1439d8b7b3061b2d209809f447ca33241733d9a3c01eabf2dc8d94358" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "syn 2.0.117", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.185" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libredox" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" +dependencies = [ + "libc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "malicious-ata-guest" +version = "0.1.0" +dependencies = [ + "ata_core", + "borsh", + "nssa_core", + "risc0-zkvm", + "serde", + "spel-framework", +] + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "maybe-async" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + +[[package]] +name = "metal" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21" +dependencies = [ + "bitflags 2.11.1", + "block", + "core-graphics-types", + "foreign-types", + "log", + "objc", + "paste", +] + +[[package]] +name = "mio" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "no_std_strings" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5b0c77c1b780822bc749a33e39aeb2c07584ab93332303babeabb645298a76e" + +[[package]] +name = "nssa_core" +version = "0.1.0" +source = "git+https://github.com/logos-blockchain/logos-execution-zone.git?tag=v0.2.0-rc1#35d8df0d031315219f94d1546ceb862b0e5b208f" +dependencies = [ + "base58", + "borsh", + "bytemuck", + "bytesize", + "chacha20", + "k256", + "risc0-zkvm", + "serde", + "serde_with", + "thiserror 2.0.18", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" +dependencies = [ + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.6", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-conv" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "postcard" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "serde", +] + +[[package]] +name = "potential_utf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit 0.25.11+spec-1.1.0", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proc-macro2-diagnostics" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "version_check", +] + +[[package]] +name = "proptest" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" +dependencies = [ + "bitflags 2.11.1", + "num-traits", + "rand 0.9.4", + "rand_chacha 0.9.0", + "rand_xorshift", + "unarray", +] + +[[package]] +name = "prost" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror 2.0.18", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +dependencies = [ + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.4", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.60.2", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +dependencies = [ + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core 0.9.5", +] + +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 2.0.18", +] + +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "reqwest" +version = "0.12.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "webpki-roots", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "risc0-binfmt" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1883f0c5d19b865f395209a137dcb29e56dc49951424967b8d0114c129f46e77" +dependencies = [ + "anyhow", + "borsh", + "bytemuck", + "derive_more", + "elf", + "lazy_static", + "postcard", + "rand 0.9.4", + "risc0-zkp", + "risc0-zkvm-platform", + "ruint", + "semver", + "serde", + "tracing", +] + +[[package]] +name = "risc0-build" +version = "3.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f89937fa1c424b188cc4cabf65335736eca9c1e3df79c127f48636f55682f3a4" +dependencies = [ + "anyhow", + "cargo_metadata", + "derive_builder", + "dirs", + "docker-generate", + "hex", + "risc0-binfmt", + "risc0-zkos-v1compat", + "risc0-zkp", + "risc0-zkvm-platform", + "rzup", + "semver", + "serde", + "serde_json", + "stability", + "tempfile", +] + +[[package]] +name = "risc0-circuit-keccak" +version = "4.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f543c60287fece797a5da4209384ab1bfebd9644fcfe591e11b1aa85f1a02f8" +dependencies = [ + "anyhow", + "bytemuck", + "paste", + "risc0-binfmt", + "risc0-circuit-recursion", + "risc0-core", + "risc0-zkp", + "tracing", +] + +[[package]] +name = "risc0-circuit-recursion" +version = "4.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2347e909c6b2a65584b5898f3802eec5b8c1b4b45329edfdd8587b6a04dd3357" +dependencies = [ + "anyhow", + "bytemuck", + "hex", + "metal", + "risc0-core", + "risc0-zkp", + "tracing", +] + +[[package]] +name = "risc0-circuit-rv32im" +version = "4.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61676419814a818fdb5e10066b13c5488b3f54aa9668794bd06c99bc91bff1f2" +dependencies = [ + "anyhow", + "bit-vec", + "bytemuck", + "derive_more", + "paste", + "risc0-binfmt", + "risc0-core", + "risc0-zkp", + "serde", + "tracing", +] + +[[package]] +name = "risc0-core" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b956a976b8ce4713694dcc6c370b522a42ccef4ba45da5b6e57dbf26cdb7b1" +dependencies = [ + "bytemuck", + "rand_core 0.9.5", +] + +[[package]] +name = "risc0-groth16" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc57e76bb87193d154ac5ee6ee352fbd7edabddab36f02a81f40a048e5ca14f9" +dependencies = [ + "anyhow", + "ark-bn254", + "ark-ec", + "ark-ff", + "ark-groth16", + "ark-serialize", + "bytemuck", + "hex", + "num-bigint", + "num-traits", + "risc0-binfmt", + "risc0-zkp", + "serde", +] + +[[package]] +name = "risc0-zkos-v1compat" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bd70cb45b5d37d025f25663b87c6b9dc9df7f413ee2068531a57f50b0eb95db" +dependencies = [ + "include_bytes_aligned", + "no_std_strings", + "risc0-zkvm-platform", +] + +[[package]] +name = "risc0-zkp" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f40d362a6c146ec6dc69208f539b92fd86e47b0dbc2083801423034a38155a2" +dependencies = [ + "anyhow", + "blake2", + "borsh", + "bytemuck", + "cfg-if", + "digest", + "hex", + "hex-literal", + "metal", + "paste", + "rand_core 0.9.5", + "risc0-core", + "risc0-zkvm-platform", + "serde", + "sha2", + "stability", + "tracing", +] + +[[package]] +name = "risc0-zkvm" +version = "3.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22b7eafb5d85be59cbd9da83f662cf47d834f1b836e14f675d1530b12c666867" +dependencies = [ + "anyhow", + "bincode", + "bonsai-sdk", + "borsh", + "bytemuck", + "bytes", + "derive_more", + "hex", + "lazy-regex", + "prost", + "risc0-binfmt", + "risc0-build", + "risc0-circuit-keccak", + "risc0-circuit-recursion", + "risc0-circuit-rv32im", + "risc0-core", + "risc0-groth16", + "risc0-zkos-v1compat", + "risc0-zkp", + "risc0-zkvm-platform", + "rrs-lib", + "rzup", + "semver", + "serde", + "sha2", + "stability", + "tempfile", + "tracing", +] + +[[package]] +name = "risc0-zkvm-platform" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4db893788c416287e2e1a87e6b8f5302511a04a45329e699d6a32a16874fd24f" +dependencies = [ + "bytemuck", + "cfg-if", + "getrandom 0.2.17", + "getrandom 0.3.4", + "libm", + "num_enum", + "paste", + "stability", +] + +[[package]] +name = "rrs-lib" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4382d3af3a4ebdae7f64ba6edd9114fff92c89808004c4943b393377a25d001" +dependencies = [ + "downcast-rs", + "paste", +] + +[[package]] +name = "rsa" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "signature", + "spki", + "subtle", + "zeroize", +] + +[[package]] +name = "ruint" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0298da754d1395046b0afdc2f20ee76d29a8ae310cd30ffa84ed42acba9cb12a" +dependencies = [ + "borsh", + "proptest", + "rand 0.8.6", + "rand 0.9.4", + "ruint-macro", + "serde_core", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags 2.11.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c2c118cb077cca2822033836dfb1b975355dfb784b5e8da48f7b6c5db74e60e" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "rzup" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d2aed296f203fa64bcb4b52069356dd86d6ec578593985b919b6995bee1f0ae" +dependencies = [ + "hex", + "rsa", + "semver", + "serde", + "serde_with", + "sha2", + "strum", + "tempfile", + "thiserror 2.0.18", + "toml", + "yaml-rust2", +] + +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.14.0", + "schemars 0.9.0", + "schemars 1.2.1", + "serde_core", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65" +dependencies = [ + "darling 0.23.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core 0.6.4", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "spel-framework" +version = "0.2.0" +source = "git+https://github.com/logos-co/spel.git?tag=v0.2.0-rc.2#9005e9fbbd78b0530412f9987273f753ed32eb2d" +dependencies = [ + "borsh", + "nssa_core", + "spel-framework-core", + "spel-framework-macros", +] + +[[package]] +name = "spel-framework-core" +version = "0.2.0" +source = "git+https://github.com/logos-co/spel.git?tag=v0.2.0-rc.2#9005e9fbbd78b0530412f9987273f753ed32eb2d" +dependencies = [ + "borsh", + "nssa_core", + "serde", + "serde_json", + "sha2", + "thiserror 1.0.69", +] + +[[package]] +name = "spel-framework-macros" +version = "0.2.0" +source = "git+https://github.com/logos-co/spel.git?tag=v0.2.0-rc.2#9005e9fbbd78b0530412f9987273f753ed32eb2d" +dependencies = [ + "proc-macro2", + "quote", + "sha2", + "syn 2.0.117", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "stability" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.2", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.52.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap 2.14.0", + "serde", + "serde_spanned", + "toml_datetime 0.6.11", + "toml_write", + "winnow 0.7.15", +] + +[[package]] +name = "toml_edit" +version = "0.25.11+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" +dependencies = [ + "indexmap 2.14.0", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.2", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow 1.0.2", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +dependencies = [ + "bitflags 2.11.1", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-subscriber" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" +dependencies = [ + "tracing-core", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.3+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +dependencies = [ + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.117", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.14.0", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.1", + "hashbrown 0.15.5", + "indexmap 2.14.0", + "semver", +] + +[[package]] +name = "web-sys" +version = "0.3.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap 2.14.0", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.1", + "indexmap 2.14.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.14.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + +[[package]] +name = "yaml-rust2" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2462ea039c445496d8793d052e13787f2b90e750b833afee748e601c17621ed9" +dependencies = [ + "arraydeque", + "encoding_rs", + "hashlink", +] + +[[package]] +name = "yoke" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zerofrom" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zerotrie" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/integration_tests/malicious_ata_methods/guest/Cargo.toml b/integration_tests/malicious_ata_methods/guest/Cargo.toml new file mode 100644 index 0000000..7466623 --- /dev/null +++ b/integration_tests/malicious_ata_methods/guest/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "malicious-ata-guest" +version = "0.1.0" +edition = "2021" + +[workspace] + +[[bin]] +name = "malicious_ata" +path = "src/bin/malicious_ata.rs" + +[dependencies] +spel-framework = { git = "https://github.com/logos-co/spel.git", tag = "v0.2.0-rc.2", package = "spel-framework" } +nssa_core = { git = "https://github.com/logos-blockchain/logos-execution-zone.git", tag = "v0.2.0-rc1" } +risc0-zkvm = { version = "=3.0.5", default-features = false } +ata_core = { path = "../../../ata/core" } +serde = { version = "1.0", features = ["derive"] } +borsh = "1.5" diff --git a/integration_tests/malicious_ata_methods/guest/src/bin/malicious_ata.rs b/integration_tests/malicious_ata_methods/guest/src/bin/malicious_ata.rs new file mode 100644 index 0000000..7008b85 --- /dev/null +++ b/integration_tests/malicious_ata_methods/guest/src/bin/malicious_ata.rs @@ -0,0 +1,78 @@ +#![no_main] + +use nssa_core::{ + account::AccountWithMetadata, + program::{AccountPostState, ProgramId}, +}; +use spel_framework::prelude::*; + +risc0_zkvm::guest::entry!(main); + +fn unchanged_post_state(account: AccountWithMetadata) -> AccountPostState { + AccountPostState::new(account.account) +} + +#[lez_program(instruction = "ata_core::Instruction")] +mod malicious_ata { + #[allow(unused_imports)] + use super::*; + + /// Intentionally malicious test helper. It acknowledges ATA creation without creating + /// anything, proving callers must not trust a caller-supplied ATA program ID. + #[instruction] + pub fn create( + owner: AccountWithMetadata, + token_definition: AccountWithMetadata, + ata_account: AccountWithMetadata, + ata_program_id: ProgramId, + ) -> SpelResult { + let _ = ata_program_id; + assert!(owner.is_authorized, "Owner authorization is missing"); + + Ok(SpelOutput::states_only(vec![ + unchanged_post_state(owner), + unchanged_post_state(token_definition), + unchanged_post_state(ata_account), + ])) + } + + /// Intentionally malicious test helper. It returns success without debiting the sender + /// or crediting the recipient. + #[instruction] + pub fn transfer( + owner: AccountWithMetadata, + sender_ata: AccountWithMetadata, + recipient: AccountWithMetadata, + ata_program_id: ProgramId, + amount: u128, + ) -> SpelResult { + let _ = (ata_program_id, amount); + assert!(owner.is_authorized, "Owner authorization is missing"); + + Ok(SpelOutput::states_only(vec![ + unchanged_post_state(owner), + unchanged_post_state(sender_ata), + unchanged_post_state(recipient), + ])) + } + + /// Intentionally malicious test helper. It returns success without burning the LP position + /// or decreasing the LP definition supply. + #[instruction] + pub fn burn( + owner: AccountWithMetadata, + holder_ata: AccountWithMetadata, + token_definition: AccountWithMetadata, + ata_program_id: ProgramId, + amount: u128, + ) -> SpelResult { + let _ = (ata_program_id, amount); + assert!(owner.is_authorized, "Owner authorization is missing"); + + Ok(SpelOutput::states_only(vec![ + unchanged_post_state(owner), + unchanged_post_state(holder_ata), + unchanged_post_state(token_definition), + ])) + } +} diff --git a/integration_tests/malicious_ata_methods/src/lib.rs b/integration_tests/malicious_ata_methods/src/lib.rs new file mode 100644 index 0000000..1bdb308 --- /dev/null +++ b/integration_tests/malicious_ata_methods/src/lib.rs @@ -0,0 +1 @@ +include!(concat!(env!("OUT_DIR"), "/methods.rs")); diff --git a/integration_tests/tests/amm.rs b/integration_tests/tests/amm.rs index 87ad3ef..ca046f9 100644 --- a/integration_tests/tests/amm.rs +++ b/integration_tests/tests/amm.rs @@ -1,13 +1,17 @@ use amm_core::{ - PoolDefinition, FEE_TIER_BPS_1, FEE_TIER_BPS_100, FEE_TIER_BPS_30, FEE_TIER_BPS_5, - MINIMUM_LIQUIDITY, + PoolDefinition, FEE_BPS_DENOMINATOR, FEE_TIER_BPS_1, FEE_TIER_BPS_100, FEE_TIER_BPS_30, + FEE_TIER_BPS_5, MINIMUM_LIQUIDITY, }; +use ata_core::{compute_ata_seed, get_associated_token_account_id}; use nssa::{ error::NssaError, program_deployment_transaction::{self, ProgramDeploymentTransaction}, public_transaction, PrivateKey, PublicKey, PublicTransaction, V03State, }; -use nssa_core::account::{Account, AccountId, Data, Nonce}; +use nssa_core::{ + account::{Account, AccountId, Data, Nonce}, + program::ProgramId, +}; use token_core::{TokenDefinition, TokenHolding}; struct Keys; @@ -16,6 +20,10 @@ struct Balances; struct Accounts; impl Keys { + fn owner() -> PrivateKey { + PrivateKey::try_new([30; 32]).expect("valid private key") + } + fn user_a() -> PrivateKey { PrivateKey::try_new([31; 32]).expect("valid private key") } @@ -42,6 +50,10 @@ impl Ids { ata_methods::ATA_ID } + fn malicious_ata_program() -> ProgramId { + malicious_ata_methods::MALICIOUS_ATA_ID + } + fn token_a_definition() -> AccountId { AccountId::new([3; 32]) } @@ -93,6 +105,31 @@ impl Ids { fn user_lp() -> AccountId { AccountId::from(&PublicKey::new_from_private_key(&Keys::user_lp())) } + + fn owner() -> AccountId { + AccountId::from(&PublicKey::new_from_private_key(&Keys::owner())) + } + + fn owner_token_a_ata() -> AccountId { + get_associated_token_account_id( + &Self::ata_program(), + &compute_ata_seed(Self::owner(), Self::token_a_definition()), + ) + } + + fn owner_token_b_ata() -> AccountId { + get_associated_token_account_id( + &Self::ata_program(), + &compute_ata_seed(Self::owner(), Self::token_b_definition()), + ) + } + + fn owner_token_lp_ata() -> AccountId { + get_associated_token_account_id( + &Self::ata_program(), + &compute_ata_seed(Self::owner(), Self::token_lp_definition()), + ) + } } impl Balances { @@ -282,6 +319,15 @@ impl Balances { } impl Accounts { + fn owner() -> Account { + Account { + program_owner: ProgramId::default(), + balance: 0_u128, + data: Data::default(), + nonce: Nonce(0), + } + } + fn user_a_holding() -> Account { Account { program_owner: Ids::token_program(), @@ -412,6 +458,42 @@ impl Accounts { } } + fn owner_token_a_ata() -> Account { + Account { + program_owner: Ids::token_program(), + balance: 0_u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: Ids::token_a_definition(), + balance: Balances::user_a_init(), + }), + nonce: Nonce(0), + } + } + + fn owner_token_b_ata() -> Account { + Account { + program_owner: Ids::token_program(), + balance: 0_u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: Ids::token_b_definition(), + balance: Balances::user_b_init(), + }), + nonce: Nonce(0), + } + } + + fn owner_token_lp_ata() -> Account { + Account { + program_owner: Ids::token_program(), + balance: 0_u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: Ids::token_lp_definition(), + balance: Balances::user_lp_init(), + }), + nonce: Nonce(0), + } + } + // --- Expected post-state accounts --- fn pool_definition_swap_1() -> Account { @@ -893,21 +975,25 @@ impl Accounts { } } -fn deploy_programs(state: &mut V03State) { - let token_message = - program_deployment_transaction::Message::new(token_methods::TOKEN_ELF.to_vec()); +fn deploy_program(state: &mut V03State, elf: &[u8], name: &str) { + let message = program_deployment_transaction::Message::new(elf.to_vec()); state - .transition_from_program_deployment_transaction(&ProgramDeploymentTransaction::new( - token_message, - )) - .expect("token program deployment must succeed"); + .transition_from_program_deployment_transaction(&ProgramDeploymentTransaction::new(message)) + .unwrap_or_else(|_| panic!("{name} program deployment must succeed")); +} - let amm_message = program_deployment_transaction::Message::new(amm_methods::AMM_ELF.to_vec()); - state - .transition_from_program_deployment_transaction(&ProgramDeploymentTransaction::new( - amm_message, - )) - .expect("amm program deployment must succeed"); +fn deploy_programs(state: &mut V03State) { + deploy_program(state, token_methods::TOKEN_ELF, "token"); + deploy_program(state, amm_methods::AMM_ELF, "amm"); +} + +fn deploy_programs_with_malicious_ata(state: &mut V03State) { + deploy_programs(state); + deploy_program( + state, + malicious_ata_methods::MALICIOUS_ATA_ELF, + "malicious ata", + ); } fn state_for_amm_tests() -> V03State { @@ -950,10 +1036,53 @@ fn state_for_amm_tests_with_new_def() -> V03State { state } +fn state_for_malicious_ata_attack() -> V03State { + let mut state = V03State::new_with_genesis_accounts(&[], &[], 0); + deploy_programs_with_malicious_ata(&mut state); + state.force_insert_account(Ids::pool_definition(), Accounts::pool_definition_init()); + state.force_insert_account( + Ids::token_a_definition(), + Accounts::token_a_definition_account(), + ); + state.force_insert_account( + Ids::token_b_definition(), + Accounts::token_b_definition_account(), + ); + state.force_insert_account( + Ids::token_lp_definition(), + Accounts::token_lp_definition_account(), + ); + state.force_insert_account(Ids::owner(), Accounts::owner()); + state.force_insert_account(Ids::owner_token_a_ata(), Accounts::owner_token_a_ata()); + state.force_insert_account(Ids::owner_token_b_ata(), Accounts::owner_token_b_ata()); + state.force_insert_account(Ids::owner_token_lp_ata(), Accounts::owner_token_lp_ata()); + state.force_insert_account(Ids::vault_a(), Accounts::vault_a_init()); + state.force_insert_account(Ids::vault_b(), Accounts::vault_b_init()); + state +} + fn current_nonce(state: &V03State, account_id: AccountId) -> Nonce { state.get_account_by_id(account_id).nonce } +fn try_execute_amm_as_owner( + state: &mut V03State, + instruction: amm_core::Instruction, + accounts: Vec, +) -> Result<(), NssaError> { + let message = public_transaction::Message::try_new( + Ids::amm_program(), + accounts, + vec![current_nonce(state, Ids::owner())], + instruction, + ) + .unwrap(); + + let witness_set = public_transaction::WitnessSet::for_message(&message, &[&Keys::owner()]); + let tx = PublicTransaction::new(message, witness_set); + state.transition_from_public_transaction(&tx, 0, 0) +} + fn state_for_amm_tests_with_precreated_user_lp_for_new_def() -> V03State { let mut state = state_for_amm_tests_with_new_def(); state.force_insert_account(Ids::user_lp(), Accounts::user_lp_holding_init_zero()); @@ -1178,6 +1307,290 @@ fn fungible_total_supply(account: &Account) -> u128 { total_supply } +fn exact_output_required_amount_in( + reserve_in: u128, + reserve_out: u128, + exact_amount_out: u128, + fee_bps: u128, +) -> u128 { + let effective_in_min = reserve_in + .checked_mul(exact_amount_out) + .expect("reserve_in * exact_amount_out overflows") + .div_ceil( + reserve_out + .checked_sub(exact_amount_out) + .expect("exact_amount_out must stay below reserve_out"), + ); + let fee_multiplier = FEE_BPS_DENOMINATOR + .checked_sub(fee_bps) + .expect("fee_bps exceeds denominator"); + + effective_in_min + .checked_mul(FEE_BPS_DENOMINATOR) + .expect("effective_in_min * denominator overflows") + .div_ceil(fee_multiplier) +} + +fn add_liquidity_malicious_ata_attack_witness() -> Option<&'static str> { + let mut state = state_for_malicious_ata_attack(); + let instruction = amm_core::Instruction::AddLiquidity { + min_amount_liquidity: Balances::add_min_lp(), + max_amount_to_add_token_a: Balances::add_max_a(), + max_amount_to_add_token_b: Balances::add_max_b(), + ata_program_id: Ids::malicious_ata_program(), + }; + + if try_execute_amm_as_owner( + &mut state, + instruction, + vec![ + Ids::pool_definition(), + Ids::vault_a(), + Ids::vault_b(), + Ids::token_lp_definition(), + Ids::owner(), + Ids::owner_token_a_ata(), + Ids::owner_token_b_ata(), + Ids::owner_token_lp_ata(), + ], + ) + .is_err() + { + return None; + } + + let pool = pool_definition(&state.get_account_by_id(Ids::pool_definition())); + assert_eq!(pool.liquidity_pool_supply, Balances::token_lp_supply_add()); + assert_eq!(pool.reserve_a, Balances::vault_a_add()); + assert_eq!(pool.reserve_b, Balances::vault_b_add()); + assert_eq!( + fungible_total_supply(&state.get_account_by_id(Ids::token_lp_definition())), + Balances::token_lp_supply_add() + ); + assert_eq!( + fungible_balance(&state.get_account_by_id(Ids::owner_token_lp_ata())), + Balances::user_lp_add() + ); + assert_eq!( + fungible_balance(&state.get_account_by_id(Ids::owner_token_a_ata())), + Balances::user_a_init() + ); + assert_eq!( + fungible_balance(&state.get_account_by_id(Ids::owner_token_b_ata())), + Balances::user_b_init() + ); + assert_eq!( + fungible_balance(&state.get_account_by_id(Ids::vault_a())), + Balances::vault_a_init() + ); + assert_eq!( + fungible_balance(&state.get_account_by_id(Ids::vault_b())), + Balances::vault_b_init() + ); + + Some( + "add_liquidity: LP supply and owner LP balance increase while both deposit legs leave balances unchanged", + ) +} + +fn remove_liquidity_malicious_ata_attack_witness() -> Option<&'static str> { + let mut state = state_for_malicious_ata_attack(); + let instruction = amm_core::Instruction::RemoveLiquidity { + remove_liquidity_amount: Balances::remove_lp(), + min_amount_to_remove_token_a: Balances::remove_min_a(), + min_amount_to_remove_token_b: Balances::remove_min_b(), + ata_program_id: Ids::malicious_ata_program(), + }; + + if try_execute_amm_as_owner( + &mut state, + instruction, + vec![ + Ids::pool_definition(), + Ids::vault_a(), + Ids::vault_b(), + Ids::token_lp_definition(), + Ids::owner(), + Ids::owner_token_a_ata(), + Ids::owner_token_b_ata(), + Ids::owner_token_lp_ata(), + ], + ) + .is_err() + { + return None; + } + + let pool = pool_definition(&state.get_account_by_id(Ids::pool_definition())); + assert_eq!( + pool.liquidity_pool_supply, + Balances::token_lp_supply_remove() + ); + assert_eq!(pool.reserve_a, Balances::vault_a_remove()); + assert_eq!(pool.reserve_b, Balances::vault_b_remove()); + assert_eq!( + fungible_balance(&state.get_account_by_id(Ids::owner_token_a_ata())), + Balances::user_a_remove() + ); + assert_eq!( + fungible_balance(&state.get_account_by_id(Ids::owner_token_b_ata())), + Balances::user_b_remove() + ); + assert_eq!( + fungible_balance(&state.get_account_by_id(Ids::vault_a())), + Balances::vault_a_remove() + ); + assert_eq!( + fungible_balance(&state.get_account_by_id(Ids::vault_b())), + Balances::vault_b_remove() + ); + assert_eq!( + fungible_balance(&state.get_account_by_id(Ids::owner_token_lp_ata())), + Balances::user_lp_init() + ); + assert_eq!( + fungible_total_supply(&state.get_account_by_id(Ids::token_lp_definition())), + Balances::token_lp_supply() + ); + + Some( + "remove_liquidity: owner receives vault tokens while LP balance and LP definition supply stay unchanged", + ) +} + +fn swap_exact_input_malicious_ata_attack_witness() -> Option<&'static str> { + let mut state = state_for_malicious_ata_attack(); + let instruction = amm_core::Instruction::SwapExactInput { + swap_amount_in: Balances::swap_amount_in(), + min_amount_out: Balances::swap_min_out(), + token_definition_id_in: Ids::token_a_definition(), + ata_program_id: Ids::malicious_ata_program(), + }; + + if try_execute_amm_as_owner( + &mut state, + instruction, + vec![ + Ids::pool_definition(), + Ids::vault_a(), + Ids::vault_b(), + Ids::owner(), + Ids::owner_token_a_ata(), + Ids::owner_token_b_ata(), + ], + ) + .is_err() + { + return None; + } + + let pool = pool_definition(&state.get_account_by_id(Ids::pool_definition())); + assert_eq!(pool.reserve_a, Balances::reserve_a_swap_2()); + assert_eq!(pool.reserve_b, Balances::reserve_b_swap_2()); + assert_eq!( + fungible_balance(&state.get_account_by_id(Ids::owner_token_a_ata())), + Balances::user_a_init() + ); + assert_eq!( + fungible_balance(&state.get_account_by_id(Ids::owner_token_b_ata())), + Balances::user_b_swap_2() + ); + assert_eq!( + fungible_balance(&state.get_account_by_id(Ids::vault_a())), + Balances::vault_a_init() + ); + assert_eq!( + fungible_balance(&state.get_account_by_id(Ids::vault_b())), + Balances::vault_b_swap_2() + ); + + Some( + "swap_exact_input: owner receives output while the input balance and deposit vault stay unchanged", + ) +} + +fn swap_exact_output_malicious_ata_attack_witness() -> Option<&'static str> { + const EXACT_AMOUNT_OUT: u128 = 500; + const MAX_AMOUNT_IN: u128 = 2_000; + + let mut state = state_for_malicious_ata_attack(); + let instruction = amm_core::Instruction::SwapExactOutput { + exact_amount_out: EXACT_AMOUNT_OUT, + max_amount_in: MAX_AMOUNT_IN, + token_definition_id_in: Ids::token_a_definition(), + ata_program_id: Ids::malicious_ata_program(), + }; + + if try_execute_amm_as_owner( + &mut state, + instruction, + vec![ + Ids::pool_definition(), + Ids::vault_a(), + Ids::vault_b(), + Ids::owner(), + Ids::owner_token_a_ata(), + Ids::owner_token_b_ata(), + ], + ) + .is_err() + { + return None; + } + + let required_amount_in = exact_output_required_amount_in( + Balances::vault_a_init(), + Balances::vault_b_init(), + EXACT_AMOUNT_OUT, + Balances::fee_tier(), + ); + let pool = pool_definition(&state.get_account_by_id(Ids::pool_definition())); + assert_eq!( + pool.reserve_a, + Balances::vault_a_init() + required_amount_in + ); + assert_eq!(pool.reserve_b, Balances::vault_b_init() - EXACT_AMOUNT_OUT); + assert_eq!( + fungible_balance(&state.get_account_by_id(Ids::owner_token_a_ata())), + Balances::user_a_init() + ); + assert_eq!( + fungible_balance(&state.get_account_by_id(Ids::owner_token_b_ata())), + Balances::user_b_init() + EXACT_AMOUNT_OUT + ); + assert_eq!( + fungible_balance(&state.get_account_by_id(Ids::vault_a())), + Balances::vault_a_init() + ); + assert_eq!( + fungible_balance(&state.get_account_by_id(Ids::vault_b())), + Balances::vault_b_init() - EXACT_AMOUNT_OUT + ); + + Some( + "swap_exact_output: owner receives exact output while the required input balance and deposit vault stay unchanged", + ) +} + +#[test] +fn amm_rejects_malicious_ata_program_for_all_value_paths() { + let accepted_attacks = [ + add_liquidity_malicious_ata_attack_witness(), + remove_liquidity_malicious_ata_attack_witness(), + swap_exact_input_malicious_ata_attack_witness(), + swap_exact_output_malicious_ata_attack_witness(), + ] + .into_iter() + .flatten() + .collect::>(); + + assert!( + accepted_attacks.is_empty(), + "AMM accepted a malicious ATA program for value paths: {}", + accepted_attacks.join("; ") + ); +} + #[test] fn amm_remove_liquidity() { let mut state = state_for_amm_tests();