From 31b6512d2dedf39cad4c0c59d27b427510b4e32e Mon Sep 17 00:00:00 2001 From: ryzen_xp Date: Thu, 25 Dec 2025 11:16:52 +0530 Subject: [PATCH 1/3] [Feat]:: added tests for zylith contract --- zylith/src/zylith.cairo | 6 + zylith/tests/test_zylith.cairo | 740 ++++++++++++++++++++++++++++++++- 2 files changed, 737 insertions(+), 9 deletions(-) diff --git a/zylith/src/zylith.cairo b/zylith/src/zylith.cairo index de5e43c..f766a4f 100644 --- a/zylith/src/zylith.cairo +++ b/zylith/src/zylith.cairo @@ -248,6 +248,12 @@ pub mod Zylith { let actual_new_sqrt_price = self.pool.sqrt_price_x128.read(); let actual_new_tick = self.pool.tick.read(); + + // for testing after all thing good then remove it + println!("amount :{} expected amount0 : {}" , amount0 , expected_amount0_delta); + println!("amount :{} expected amount1 : {}" , amount1 , expected_amount1_delta); + println!("amount :{} expected amount1 : {}" , actual_new_sqrt_price , expected_new_sqrt_price); + // Compare deltas - the proof's expected values must match actual execution assert(amount0 == expected_amount0_delta, 'AMOUNT0_DELTA_MISMATCH'); assert(amount1 == expected_amount1_delta, 'AMOUNT1_DELTA_MISMATCH'); diff --git a/zylith/tests/test_zylith.cairo b/zylith/tests/test_zylith.cairo index fa83cac..3a0666d 100644 --- a/zylith/tests/test_zylith.cairo +++ b/zylith/tests/test_zylith.cairo @@ -1,3 +1,4 @@ +use starknet::SyscallResultTrait; use core::array::ArrayTrait; use core::integer::u128; use core::num::traits::Zero; @@ -7,6 +8,7 @@ use snforge_std::{ stop_cheat_caller_address, }; use starknet::ContractAddress; +use zylith::clmm::math; use zylith::interfaces::izylith::{IZylithDispatcher, IZylithDispatcherTrait}; use zylith::mocks::erc20::{IMockERC20Dispatcher, IMockERC20DispatcherTrait}; @@ -27,25 +29,25 @@ fn user2() -> ContractAddress { // this is mock fn deploy_mock_erc20(name: felt252, symbol: felt252) -> IMockERC20Dispatcher { - let contract = declare("MockERC20").unwrap().contract_class(); + let contract = declare("MockERC20").unwrap_syscall().contract_class(); let mut constructor_args = array![]; constructor_args.append(name); constructor_args.append(symbol); constructor_args.append(18); - let (contract_address, _) = contract.deploy(@constructor_args).unwrap(); + let (contract_address, _) = contract.deploy(@constructor_args).unwrap_syscall(); IMockERC20Dispatcher { contract_address } } fn deploy_zylith() -> IZylithDispatcher { - let contract = declare("Zylith").unwrap().contract_class(); + let contract = declare("Zylith").unwrap_syscall().contract_class(); let owner: ContractAddress = 1.try_into().unwrap(); - let mock_verifier_class = declare("MockVerifier").unwrap().contract_class(); - let (membership_verifier, _) = mock_verifier_class.deploy(@array![]).unwrap(); - let (swap_verifier, _) = mock_verifier_class.deploy(@array![]).unwrap(); - let (withdraw_verifier, _) = mock_verifier_class.deploy(@array![]).unwrap(); - let (lp_verifier, _) = mock_verifier_class.deploy(@array![]).unwrap(); + let mock_verifier_class = declare("MockVerifier").unwrap_syscall().contract_class(); + let (membership_verifier, _) = mock_verifier_class.deploy(@array![]).unwrap_syscall(); + let (swap_verifier, _) = mock_verifier_class.deploy(@array![]).unwrap_syscall(); + let (withdraw_verifier, _) = mock_verifier_class.deploy(@array![]).unwrap_syscall(); + let (lp_verifier, _) = mock_verifier_class.deploy(@array![]).unwrap_syscall(); let mut constructor_args = array![]; constructor_args.append(owner.into()); @@ -54,7 +56,7 @@ fn deploy_zylith() -> IZylithDispatcher { constructor_args.append(withdraw_verifier.into()); constructor_args.append(lp_verifier.into()); - let (contract_address, _) = contract.deploy(@constructor_args).unwrap(); + let (contract_address, _) = contract.deploy(@constructor_args).unwrap_syscall(); IZylithDispatcher { contract_address } } @@ -175,3 +177,723 @@ fn test_initialize_twice_fails() { stop_cheat_caller_address(setup.zylith.contract_address); } + + +// ============================================================================ +// Private Deposite +// ============================================================================ + +#[test] +fn test_private_deposit_transfers_tokens_and_adds_commitment() { + let setup = setup_with_erc20(); + initialize_pool(@setup); + + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup + .zylith + .initialize( + setup.token0.contract_address, + setup.token1.contract_address, + TEST_FEE, + TICK_SPACING, + sqrt_price, + ); + stop_cheat_caller_address(setup.zylith.contract_address); + + let deposit_amount: u256 = 1000000000000000000; // 1 token + let commitment: felt252 = 0x123456789abcdef; // Mock commitment + + let balance_before = setup.token0.balance_of(caller()); + + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup.zylith.private_deposit(setup.token0.contract_address, deposit_amount, commitment); + stop_cheat_caller_address(setup.zylith.contract_address); + + // Check token transfer + let balance_after = setup.token0.balance_of(caller()); + assert!(balance_before - balance_after == deposit_amount, "Tokens not transferred"); + + // Check commitment added to Merkle tree + let root = setup.zylith.get_merkle_root(); + assert!(root != 0, "Root should be updated"); + assert!(setup.zylith.is_root_known(root), "New root should be known"); +} + +#[test] +#[should_panic(expected: ('INVALID_TOKEN',))] +fn test_private_deposit_invalid_token_fails() { + let setup = setup_with_erc20(); + initialize_pool(@setup); + + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup + .zylith + .initialize( + setup.token0.contract_address, + setup.token1.contract_address, + TEST_FEE, + TICK_SPACING, + sqrt_price, + ); + stop_cheat_caller_address(setup.zylith.contract_address); + + let invalid_token = deploy_mock_erc20('Invalid', 'INV'); + let deposit_amount: u256 = 1000000000000000000; + let commitment: felt252 = 0x123; + + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup.zylith.private_deposit(invalid_token.contract_address, deposit_amount, commitment); +} + +#[test] +fn test_private_deposit_updates_merkle_tree() { + let setup = setup_with_erc20(); + initialize_pool(@setup); + + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup + .zylith + .initialize( + setup.token0.contract_address, + setup.token1.contract_address, + TEST_FEE, + TICK_SPACING, + sqrt_price, + ); + stop_cheat_caller_address(setup.zylith.contract_address); + + let commitment1: felt252 = 0x111; + let commitment2: felt252 = 0x222; + let amount: u256 = 1000000000000000000; + + start_cheat_caller_address(setup.zylith.contract_address, caller()); + + setup.zylith.private_deposit(setup.token0.contract_address, amount, commitment1); + let root1 = setup.zylith.get_merkle_root(); + + setup.zylith.private_deposit(setup.token0.contract_address, amount, commitment2); + let root2 = setup.zylith.get_merkle_root(); + + stop_cheat_caller_address(setup.zylith.contract_address); + + assert!(root1 != root2, "Root should change after second deposit"); + assert!(setup.zylith.is_root_known(root1), "Previous root should still be known"); + assert!(setup.zylith.is_root_known(root2), "New root should be known"); + assert!( + setup.zylith.get_known_roots_count() == 3, "Should have 3 known roots", + ); // 0, root1, root2 +} + +// ============================================================================ +// Private Swap +// // ============================================================================ +// #[test] +// fn test_private_swap_with_valid_proof() { +// let setup = setup_with_erc20(); +// initialize_pool(@setup); + +// start_cheat_caller_address(setup.zylith.contract_address, caller()); +// setup.zylith.initialize( +// setup.token0.contract_address, +// setup.token1.contract_address, +// TEST_FEE, +// TICK_SPACING, +// sqrt_price, +// ); +// stop_cheat_caller_address(setup.zylith.contract_address); + + +// let deposit_amount: u256 = 1_000_000_000_000_000_000; // 1 token +// let deposit_commitment: felt252 = 0x123456; + +// start_cheat_caller_address(setup.zylith.contract_address, caller()); +// setup.zylith.private_deposit(setup.token0.contract_address, deposit_amount, deposit_commitment); +// setup.zylith.private_deposit(setup.token1.contract_address, deposit_amount, deposit_commitment); +// stop_cheat_caller_address(setup.zylith.contract_address); + +// let root_before_swap = setup.zylith.get_merkle_root(); + + +// let nullifier: felt252 = 0x01; +// let new_commitment: felt252 = 0x999; +// let amount_specified: u128 = 1000; +// let zero_for_one: bool = true; + +// let sqrt_price_limit = if zero_for_one { +// math::MIN_SQRT_RATIO + 1 +// } else { +// math::MAX_SQRT_RATIO - 1 +// }; + +// let expected_amount0_delta: felt252 = 100; +// let expected_amount1_delta: felt252 = 200; +// let expected_new_tick: i32 = 0; + + +// let proof = array![ +// nullifier, +// root_before_swap, +// new_commitment, +// amount_specified.into(), +// if zero_for_one { 1 } else { 0 }, +// expected_amount0_delta, +// expected_amount1_delta, +// sqrt_price_limit.try_into().unwrap(), +// expected_new_tick.into(), +// ]; + +// let public_inputs = array![ +// nullifier, +// root_before_swap, +// new_commitment, +// amount_specified.into(), +// if zero_for_one { 1 } else { 0 }, +// expected_amount0_delta.try_into().unwrap(), +// expected_amount1_delta.try_into().unwrap(), +// sqrt_price_limit.try_into().unwrap(), +// expected_new_tick.into(), +// ]; + + +// start_cheat_caller_address(setup.zylith.contract_address, caller()); +// let (amount0, amount1) = setup.zylith.private_swap( +// proof, +// public_inputs, +// zero_for_one, +// amount_specified, +// sqrt_price_limit, +// new_commitment, +// ); +// stop_cheat_caller_address(setup.zylith.contract_address); + + +// assert!(amount0 != 0 || amount1 != 0, "Swap should return non-zero amounts"); +// assert!( +// setup.zylith.is_nullifier_spent(nullifier), +// "Swap nullifier must be spent" +// ); + +// let root_after_swap = setup.zylith.get_merkle_root(); +// assert!( +// root_after_swap != root_before_swap, +// "Merkle root should update after swap" +// ); +// } + + + + +// #[test] +// #[should_panic(expected: ('NULLIFIER_ALREADY_SPENT',))] +// fn test_private_swap_double_spend_fails() { +// let setup = setup_with_erc20(); +// initialize_pool(@setup); +// start_cheat_caller_address(setup.zylith.contract_address, caller()); +// setup +// .zylith +// .initialize( +// setup.token0.contract_address, +// setup.token1.contract_address, +// TEST_FEE, +// TICK_SPACING, +// sqrt_price, +// ); +// stop_cheat_caller_address(setup.zylith.contract_address); + +// // Add liquidity +// start_cheat_caller_address(setup.zylith.contract_address, caller()); +// setup.zylith.mint(-120, 120, 10000000); +// stop_cheat_caller_address(setup.zylith.contract_address); + +// // Deposit +// let commitment1: felt252 = 0x111; +// let amount: u256 = 1000000000000000000; +// start_cheat_caller_address(setup.zylith.contract_address, caller()); +// setup.zylith.private_deposit(setup.token0.contract_address, amount, commitment1); +// let current_root = setup.zylith.get_merkle_root(); +// stop_cheat_caller_address(setup.zylith.contract_address); + +// // Create proof with same nullifier +// let mut proof = array![0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]; +// let nullifier: felt252 = 0x999; +// let new_commitment: felt252 = 0x222; +// let amount_specified: u128 = 100000; +// let zero_for_one = true; +// let sqrt_price_limit = math::MIN_SQRT_RATIO + 1; + +// let mut public_inputs = array![ +// nullifier, current_root, new_commitment, amount_specified.into(), 1, +// (-100000).try_into().unwrap(), 99000.into(), sqrt_price_limit.try_into().unwrap(), 0.into(), +// ]; + +// start_cheat_caller_address(setup.zylith.contract_address, caller()); + +// // First swap +// setup +// .zylith +// .private_swap( +// proof.clone(), +// public_inputs.clone(), +// zero_for_one, +// amount_specified, +// sqrt_price_limit, +// new_commitment, +// ); + +// // Try to use same nullifier again - should fail +// let new_commitment2: felt252 = 0x333; +// let mut public_inputs2 = array![ +// nullifier, // Same nullifier! +// current_root, new_commitment2, amount_specified.into(), 1, +// (-100000).try_into().unwrap(), 99000.into(), sqrt_price_limit.try_into().unwrap(), 0.into(), +// ]; + +// setup +// .zylith +// .private_swap( +// proof, +// public_inputs2, +// zero_for_one, +// amount_specified, +// sqrt_price_limit, +// new_commitment2, +// ); +// } + +// #[test] +// #[should_panic(expected: ('INVALID_MERKLE_ROOT',))] +// fn test_private_swap_invalid_root_fails() { +// let setup = setup_with_erc20(); +// initialize_pool(@setup); + +// start_cheat_caller_address(setup.zylith.contract_address, caller()); +// setup.zylith.initialize( +// setup.token0.contract_address, +// setup.token1.contract_address, +// TEST_FEE, +// TICK_SPACING, +// sqrt_price, +// ); +// stop_cheat_caller_address(setup.zylith.contract_address); + +// // -------------------------------------------------- +// // Private deposit +// // -------------------------------------------------- +// let deposit_amount: u256 = 1_000_000_000_000_000_000; // 1 token +// let deposit_commitment: felt252 = 0x123456; + +// start_cheat_caller_address(setup.zylith.contract_address, caller()); +// setup.zylith.private_deposit(setup.token0.contract_address, deposit_amount, deposit_commitment); +// setup.zylith.private_deposit(setup.token1.contract_address, deposit_amount, deposit_commitment); +// stop_cheat_caller_address(setup.zylith.contract_address); + +// let root_before_swap = setup.zylith.get_merkle_root(); + + +// // Swap parameters + +// let nullifier: felt252 = 0x01; +// let new_commitment: felt252 = 0x999; +// let amount_specified: u128 = 1000; +// let zero_for_one: bool = true; + +// let sqrt_price_limit = if zero_for_one { +// math::MIN_SQRT_RATIO + 1 +// } else { +// math::MAX_SQRT_RATIO - 1 +// }; + +// // Expected deltas (mocked but CONSISTENT) +// let expected_amount0_delta: felt252 = 100; +// let expected_amount1_delta: felt252 = 200; +// let expected_new_tick: i32 = 0; + + +// let proof = array![ +// nullifier, +// root_before_swap, +// new_commitment, +// amount_specified.into(), +// if zero_for_one { 1 } else { 0 }, +// expected_amount0_delta, +// expected_amount1_delta, +// sqrt_price_limit.try_into().unwrap(), +// expected_new_tick.into(), +// ]; + +// let public_inputs = array![ +// nullifier, +// 'fake_root', +// new_commitment, +// amount_specified.into(), +// if zero_for_one { 1 } else { 0 }, +// expected_amount0_delta.try_into().unwrap(), +// expected_amount1_delta.try_into().unwrap(), +// sqrt_price_limit.try_into().unwrap(), +// expected_new_tick.into(), +// ]; + +// // -------------------------------------------------- +// // Execute private swap +// // -------------------------------------------------- +// start_cheat_caller_address(setup.zylith.contract_address, caller()); +// setup.zylith.private_swap( +// proof, +// public_inputs, +// zero_for_one, +// amount_specified, +// sqrt_price_limit, +// new_commitment, +// ); +// stop_cheat_caller_address(setup.zylith.contract_address); +// } + +// ============================================================================ +// Private Withdraw +// ============================================================================ + +#[test] +fn test_private_withdraw_with_valid_proof() { + let setup = setup_with_erc20(); + initialize_pool(@setup); + + // Initialize pool + + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup + .zylith + .initialize( + setup.token0.contract_address, + setup.token1.contract_address, + TEST_FEE, + TICK_SPACING, + sqrt_price, + ); + stop_cheat_caller_address(setup.zylith.contract_address); + + // private Deposit first + + let commitment: felt252 = 0x111; + let amount: u256 = 1000; + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup.zylith.private_deposit(setup.token0.contract_address, amount, commitment); + let current_root = setup.zylith.get_merkle_root(); + stop_cheat_caller_address(setup.zylith.contract_address); + + // Prepare withdraw + let recipient = user2(); + + let mut proof = array![0x999, current_root, recipient.into(), 500, 0x5, 0x6, 0x7, 0x8]; + let nullifier: felt252 = 0x999; + + let withdraw_amount: u128 = 500; // 0.5 token + + let mut public_inputs = array![ + nullifier, current_root, recipient.into(), withdraw_amount.into(), + ]; + // record old balance of token0 + + let balance_before = setup.token0.balance_of(recipient); + + // Now withdraw token0 + + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup + .zylith + .private_withdraw( + proof, public_inputs, setup.token0.contract_address, recipient, withdraw_amount, + ); + stop_cheat_caller_address(setup.zylith.contract_address); + + // Checking Token0 balance after withdraw + + let balance_after = setup.token0.balance_of(recipient); + assert!( + balance_after - balance_before == withdraw_amount.into(), "Recipient should receive tokens", + ); + assert!(setup.zylith.is_nullifier_spent(nullifier), "Nullifier should be spent"); +} + +#[test] +#[should_panic(expected: ('INVALID_TOKEN',))] +fn test_private_withdraw_invalid_token_fails() { + let setup = setup_with_erc20(); + initialize_pool(@setup); + + // Initialize pool + + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup + .zylith + .initialize( + setup.token0.contract_address, + setup.token1.contract_address, + TEST_FEE, + TICK_SPACING, + sqrt_price, + ); + stop_cheat_caller_address(setup.zylith.contract_address); + + // private Deposit first + + let commitment: felt252 = 0x111; + let amount: u256 = 1000; + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup.zylith.private_deposit(setup.token0.contract_address, amount, commitment); + let current_root = setup.zylith.get_merkle_root(); + stop_cheat_caller_address(setup.zylith.contract_address); + + // Prepare withdraw + let recipient = user2(); + + let mut proof = array![0x999, current_root, recipient.into(), 500, 0x5, 0x6, 0x7, 0x8]; + let nullifier: felt252 = 0x999; + + let withdraw_amount: u128 = 500; // 0.5 token + + let mut public_inputs = array![ + nullifier, current_root, recipient.into(), withdraw_amount.into(), + ]; + + // Fake TOken address + + let token_fake = deploy_mock_erc20('Tokenfake', 'TK'); + + + // Now withdraw token0 + + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup + .zylith + .private_withdraw( + proof, public_inputs, token_fake.contract_address, recipient, withdraw_amount, + ); + stop_cheat_caller_address(setup.zylith.contract_address); + +} + +#[test] +#[should_panic(expected: ('AMOUNT_MISMATCH',))] +fn test_private_withdraw_amount_mismatch_fails() { + let setup = setup_with_erc20(); + initialize_pool(@setup); + + // Initialize pool + + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup + .zylith + .initialize( + setup.token0.contract_address, + setup.token1.contract_address, + TEST_FEE, + TICK_SPACING, + sqrt_price, + ); + stop_cheat_caller_address(setup.zylith.contract_address); + + // private Deposit first + + let commitment: felt252 = 0x111; + let amount: u256 = 1000; + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup.zylith.private_deposit(setup.token0.contract_address, amount, commitment); + let current_root = setup.zylith.get_merkle_root(); + stop_cheat_caller_address(setup.zylith.contract_address); + + // Prepare withdraw with invalid amount + let recipient = user2(); + + let mut proof = array![0x999, current_root, recipient.into(), 50, 0x5, 0x6, 0x7, 0x8]; + let nullifier: felt252 = 0x999; + + let withdraw_amount: u128 = 500; + + let mut public_inputs = array![ + nullifier, current_root, recipient.into(), withdraw_amount.into(), + ]; + + // Now withdraw token0 + + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup + .zylith + .private_withdraw( + proof, public_inputs, setup.token0.contract_address, recipient, withdraw_amount, + ); + stop_cheat_caller_address(setup.zylith.contract_address); + +} + +// ============================================================================ +// Private Mint & Burn Liquidity +// ============================================================================ + +#[test] +fn test_private_mint_liquidity_with_valid_proof() { + let setup = setup_with_erc20(); + initialize_pool(@setup); + + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup + .zylith + .initialize( + setup.token0.contract_address, + setup.token1.contract_address, + TEST_FEE, + TICK_SPACING, + sqrt_price, + ); + stop_cheat_caller_address(setup.zylith.contract_address); + + // Deposit tokens first + let commitment: felt252 = 0x111; + let amount: u256 = 1000000000000000000; + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup.zylith.private_deposit(setup.token0.contract_address, amount, commitment); + setup.zylith.private_deposit(setup.token1.contract_address, amount, commitment); + let current_root = setup.zylith.get_merkle_root(); + stop_cheat_caller_address(setup.zylith.contract_address); + + // Prepare mint + let mut proof = array![0x1, current_root, 120, 240, 1000000, 0x222, 0x7, 0x8]; + let nullifier: felt252 = 0x1; + let new_commitment: felt252 = 0x222; + let position_commitment: felt252 = 0x333; + let tick_lower: i32 = 120; + let tick_upper: i32 = 240; + let liquidity: u128 = 1000000; + + let mut public_inputs = array![ + nullifier, current_root, tick_lower.into(), tick_upper.into(), liquidity.into(), + new_commitment, position_commitment, + ]; + + start_cheat_caller_address(setup.zylith.contract_address, caller()); + let (amount0, amount1) = setup + .zylith + .private_mint_liquidity( + proof, public_inputs, tick_lower.into(), tick_upper, liquidity, new_commitment, + ); + stop_cheat_caller_address(setup.zylith.contract_address); + + assert!(amount0 > 0 || amount1 > 0, "Should mint some liquidity"); + assert!(setup.zylith.is_nullifier_spent(nullifier), "Nullifier should be spent"); +} + +#[test] +fn test_private_burn_liquidity_with_valid_proof() { + let setup = setup_with_erc20(); + initialize_pool(@setup); + + // Initialize pool + + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup.zylith.initialize( + setup.token0.contract_address, + setup.token1.contract_address, + TEST_FEE, + TICK_SPACING, + sqrt_price, + ); + stop_cheat_caller_address(setup.zylith.contract_address); + + // Private deposit + + let deposit_commitment: felt252 = 0x111; + let deposit_amount: u256 = 10_000_000_000_000_000_000; // 10 tokens + + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup.zylith.private_deposit(setup.token0.contract_address, deposit_amount, deposit_commitment); + setup.zylith.private_deposit(setup.token1.contract_address, deposit_amount, deposit_commitment); + stop_cheat_caller_address(setup.zylith.contract_address); + + let root_before_mint = setup.zylith.get_merkle_root(); + + + // Private mint liquidity + + let tick_lower: i32 = 120; + let tick_upper: i32 = 240; + let minted_liquidity: u128 = 2_000_000; + + let mint_nullifier: felt252 = 0x01; + let new_commitment_after_mint: felt252 = 0x222; + let position_commitment: felt252 = 0x333; + + let mint_proof = array![ + mint_nullifier, + root_before_mint, + tick_lower.into(), + tick_upper.into(), + minted_liquidity.into(), + new_commitment_after_mint, + position_commitment, + ]; + + let mint_public_inputs = array![ + mint_nullifier, + root_before_mint, + tick_lower.into(), + tick_upper.into(), + minted_liquidity.into(), + new_commitment_after_mint, + position_commitment, + ]; + + start_cheat_caller_address(setup.zylith.contract_address, caller()); + setup.zylith.private_mint_liquidity( + mint_proof, + mint_public_inputs, + tick_lower, + tick_upper, + minted_liquidity, + new_commitment_after_mint, + ); + stop_cheat_caller_address(setup.zylith.contract_address); + + let root_after_mint = setup.zylith.get_merkle_root(); + + // Private burn liquidity + + let burn_liquidity: u128 = 1_000_000; // <= minted_liquidity + let burn_nullifier: felt252 = 0x999; + let new_commitment_after_burn: felt252 = 0x555; + + let burn_proof = array![ + burn_nullifier, + root_after_mint, + tick_lower.into(), + tick_upper.into(), + burn_liquidity.into(), + new_commitment_after_burn, + position_commitment, + ]; + + let burn_public_inputs = array![ + burn_nullifier, + root_after_mint, + tick_lower.into(), + tick_upper.into(), + burn_liquidity.into(), + new_commitment_after_burn, + position_commitment, + ]; + + start_cheat_caller_address(setup.zylith.contract_address, caller()); + let (amount0, amount1) = setup.zylith.private_burn_liquidity( + burn_proof, + burn_public_inputs, + tick_lower, + tick_upper, + burn_liquidity, + new_commitment_after_burn, + ); + stop_cheat_caller_address(setup.zylith.contract_address); + + assert!(amount0 > 0 || amount1 > 0, "Burn should return tokens"); + assert!( + setup.zylith.is_nullifier_spent(burn_nullifier), + "Burn nullifier must be spent" + ); +} From 7565e1170018b5138392174f25eae3d8b9a3668a Mon Sep 17 00:00:00 2001 From: ryzen_xp Date: Thu, 25 Dec 2025 11:21:53 +0530 Subject: [PATCH 2/3] fmt --- zylith/src/zylith.cairo | 11 ++- zylith/tests/test_zylith.cairo | 162 ++++++++++++++------------------- 2 files changed, 74 insertions(+), 99 deletions(-) diff --git a/zylith/src/zylith.cairo b/zylith/src/zylith.cairo index f766a4f..505d446 100644 --- a/zylith/src/zylith.cairo +++ b/zylith/src/zylith.cairo @@ -248,11 +248,12 @@ pub mod Zylith { let actual_new_sqrt_price = self.pool.sqrt_price_x128.read(); let actual_new_tick = self.pool.tick.read(); - - // for testing after all thing good then remove it - println!("amount :{} expected amount0 : {}" , amount0 , expected_amount0_delta); - println!("amount :{} expected amount1 : {}" , amount1 , expected_amount1_delta); - println!("amount :{} expected amount1 : {}" , actual_new_sqrt_price , expected_new_sqrt_price); + // for testing after all thing good then remove + println!("amount :{} expected amount0 : {}", amount0, expected_amount0_delta); + println!("amount :{} expected amount1 : {}", amount1, expected_amount1_delta); + println!( + "amount :{} expected amount1 : {}", actual_new_sqrt_price, expected_new_sqrt_price, + ); // Compare deltas - the proof's expected values must match actual execution assert(amount0 == expected_amount0_delta, 'AMOUNT0_DELTA_MISMATCH'); diff --git a/zylith/tests/test_zylith.cairo b/zylith/tests/test_zylith.cairo index 3a0666d..0d2e765 100644 --- a/zylith/tests/test_zylith.cairo +++ b/zylith/tests/test_zylith.cairo @@ -1,4 +1,3 @@ -use starknet::SyscallResultTrait; use core::array::ArrayTrait; use core::integer::u128; use core::num::traits::Zero; @@ -7,7 +6,7 @@ use snforge_std::{ ContractClassTrait, DeclareResultTrait, declare, start_cheat_caller_address, stop_cheat_caller_address, }; -use starknet::ContractAddress; +use starknet::{ContractAddress, SyscallResultTrait}; use zylith::clmm::math; use zylith::interfaces::izylith::{IZylithDispatcher, IZylithDispatcherTrait}; use zylith::mocks::erc20::{IMockERC20Dispatcher, IMockERC20DispatcherTrait}; @@ -302,18 +301,18 @@ fn test_private_deposit_updates_merkle_tree() { // ); // stop_cheat_caller_address(setup.zylith.contract_address); - // let deposit_amount: u256 = 1_000_000_000_000_000_000; // 1 token // let deposit_commitment: felt252 = 0x123456; // start_cheat_caller_address(setup.zylith.contract_address, caller()); -// setup.zylith.private_deposit(setup.token0.contract_address, deposit_amount, deposit_commitment); -// setup.zylith.private_deposit(setup.token1.contract_address, deposit_amount, deposit_commitment); +// setup.zylith.private_deposit(setup.token0.contract_address, deposit_amount, +// deposit_commitment); +// setup.zylith.private_deposit(setup.token1.contract_address, deposit_amount, +// deposit_commitment); // stop_cheat_caller_address(setup.zylith.contract_address); // let root_before_swap = setup.zylith.get_merkle_root(); - // let nullifier: felt252 = 0x01; // let new_commitment: felt252 = 0x999; // let amount_specified: u128 = 1000; @@ -329,7 +328,6 @@ fn test_private_deposit_updates_merkle_tree() { // let expected_amount1_delta: felt252 = 200; // let expected_new_tick: i32 = 0; - // let proof = array![ // nullifier, // root_before_swap, @@ -354,7 +352,6 @@ fn test_private_deposit_updates_merkle_tree() { // expected_new_tick.into(), // ]; - // start_cheat_caller_address(setup.zylith.contract_address, caller()); // let (amount0, amount1) = setup.zylith.private_swap( // proof, @@ -366,7 +363,6 @@ fn test_private_deposit_updates_merkle_tree() { // ); // stop_cheat_caller_address(setup.zylith.contract_address); - // assert!(amount0 != 0 || amount1 != 0, "Swap should return non-zero amounts"); // assert!( // setup.zylith.is_nullifier_spent(nullifier), @@ -380,9 +376,6 @@ fn test_private_deposit_updates_merkle_tree() { // ); // } - - - // #[test] // #[should_panic(expected: ('NULLIFIER_ALREADY_SPENT',))] // fn test_private_swap_double_spend_fails() { @@ -423,7 +416,8 @@ fn test_private_deposit_updates_merkle_tree() { // let mut public_inputs = array![ // nullifier, current_root, new_commitment, amount_specified.into(), 1, -// (-100000).try_into().unwrap(), 99000.into(), sqrt_price_limit.try_into().unwrap(), 0.into(), +// (-100000).try_into().unwrap(), 99000.into(), sqrt_price_limit.try_into().unwrap(), +// 0.into(), // ]; // start_cheat_caller_address(setup.zylith.contract_address, caller()); @@ -445,7 +439,8 @@ fn test_private_deposit_updates_merkle_tree() { // let mut public_inputs2 = array![ // nullifier, // Same nullifier! // current_root, new_commitment2, amount_specified.into(), 1, -// (-100000).try_into().unwrap(), 99000.into(), sqrt_price_limit.try_into().unwrap(), 0.into(), +// (-100000).try_into().unwrap(), 99000.into(), sqrt_price_limit.try_into().unwrap(), +// 0.into(), // ]; // setup @@ -483,13 +478,14 @@ fn test_private_deposit_updates_merkle_tree() { // let deposit_commitment: felt252 = 0x123456; // start_cheat_caller_address(setup.zylith.contract_address, caller()); -// setup.zylith.private_deposit(setup.token0.contract_address, deposit_amount, deposit_commitment); -// setup.zylith.private_deposit(setup.token1.contract_address, deposit_amount, deposit_commitment); +// setup.zylith.private_deposit(setup.token0.contract_address, deposit_amount, +// deposit_commitment); +// setup.zylith.private_deposit(setup.token1.contract_address, deposit_amount, +// deposit_commitment); // stop_cheat_caller_address(setup.zylith.contract_address); // let root_before_swap = setup.zylith.get_merkle_root(); - // // Swap parameters // let nullifier: felt252 = 0x01; @@ -508,7 +504,6 @@ fn test_private_deposit_updates_merkle_tree() { // let expected_amount1_delta: felt252 = 200; // let expected_new_tick: i32 = 0; - // let proof = array![ // nullifier, // root_before_swap, @@ -557,7 +552,7 @@ fn test_private_withdraw_with_valid_proof() { let setup = setup_with_erc20(); initialize_pool(@setup); - // Initialize pool + // Initialize pool start_cheat_caller_address(setup.zylith.contract_address, caller()); setup @@ -585,17 +580,17 @@ fn test_private_withdraw_with_valid_proof() { let mut proof = array![0x999, current_root, recipient.into(), 500, 0x5, 0x6, 0x7, 0x8]; let nullifier: felt252 = 0x999; - + let withdraw_amount: u128 = 500; // 0.5 token let mut public_inputs = array![ nullifier, current_root, recipient.into(), withdraw_amount.into(), ]; - // record old balance of token0 + // record old balance of token0 let balance_before = setup.token0.balance_of(recipient); - - // Now withdraw token0 + + // Now withdraw token0 start_cheat_caller_address(setup.zylith.contract_address, caller()); setup @@ -617,10 +612,10 @@ fn test_private_withdraw_with_valid_proof() { #[test] #[should_panic(expected: ('INVALID_TOKEN',))] fn test_private_withdraw_invalid_token_fails() { - let setup = setup_with_erc20(); + let setup = setup_with_erc20(); initialize_pool(@setup); - // Initialize pool + // Initialize pool start_cheat_caller_address(setup.zylith.contract_address, caller()); setup @@ -648,7 +643,7 @@ fn test_private_withdraw_invalid_token_fails() { let mut proof = array![0x999, current_root, recipient.into(), 500, 0x5, 0x6, 0x7, 0x8]; let nullifier: felt252 = 0x999; - + let withdraw_amount: u128 = 500; // 0.5 token let mut public_inputs = array![ @@ -657,10 +652,9 @@ fn test_private_withdraw_invalid_token_fails() { // Fake TOken address - let token_fake = deploy_mock_erc20('Tokenfake', 'TK'); - - - // Now withdraw token0 + let token_fake = deploy_mock_erc20('Tokenfake', 'TK'); + + // Now withdraw token0 start_cheat_caller_address(setup.zylith.contract_address, caller()); setup @@ -669,7 +663,6 @@ fn test_private_withdraw_invalid_token_fails() { proof, public_inputs, token_fake.contract_address, recipient, withdraw_amount, ); stop_cheat_caller_address(setup.zylith.contract_address); - } #[test] @@ -678,7 +671,7 @@ fn test_private_withdraw_amount_mismatch_fails() { let setup = setup_with_erc20(); initialize_pool(@setup); - // Initialize pool + // Initialize pool start_cheat_caller_address(setup.zylith.contract_address, caller()); setup @@ -701,19 +694,19 @@ fn test_private_withdraw_amount_mismatch_fails() { let current_root = setup.zylith.get_merkle_root(); stop_cheat_caller_address(setup.zylith.contract_address); - // Prepare withdraw with invalid amount + // Prepare withdraw with invalid amount let recipient = user2(); let mut proof = array![0x999, current_root, recipient.into(), 50, 0x5, 0x6, 0x7, 0x8]; let nullifier: felt252 = 0x999; - - let withdraw_amount: u128 = 500; + + let withdraw_amount: u128 = 500; let mut public_inputs = array![ nullifier, current_root, recipient.into(), withdraw_amount.into(), ]; - - // Now withdraw token0 + + // Now withdraw token0 start_cheat_caller_address(setup.zylith.contract_address, caller()); setup @@ -722,7 +715,6 @@ fn test_private_withdraw_amount_mismatch_fails() { proof, public_inputs, setup.token0.contract_address, recipient, withdraw_amount, ); stop_cheat_caller_address(setup.zylith.contract_address); - } // ============================================================================ @@ -789,13 +781,15 @@ fn test_private_burn_liquidity_with_valid_proof() { // Initialize pool start_cheat_caller_address(setup.zylith.contract_address, caller()); - setup.zylith.initialize( - setup.token0.contract_address, - setup.token1.contract_address, - TEST_FEE, - TICK_SPACING, - sqrt_price, - ); + setup + .zylith + .initialize( + setup.token0.contract_address, + setup.token1.contract_address, + TEST_FEE, + TICK_SPACING, + sqrt_price, + ); stop_cheat_caller_address(setup.zylith.contract_address); // Private deposit @@ -810,7 +804,6 @@ fn test_private_burn_liquidity_with_valid_proof() { let root_before_mint = setup.zylith.get_merkle_root(); - // Private mint liquidity let tick_lower: i32 = 120; @@ -822,34 +815,26 @@ fn test_private_burn_liquidity_with_valid_proof() { let position_commitment: felt252 = 0x333; let mint_proof = array![ - mint_nullifier, - root_before_mint, - tick_lower.into(), - tick_upper.into(), - minted_liquidity.into(), - new_commitment_after_mint, - position_commitment, + mint_nullifier, root_before_mint, tick_lower.into(), tick_upper.into(), + minted_liquidity.into(), new_commitment_after_mint, position_commitment, ]; let mint_public_inputs = array![ - mint_nullifier, - root_before_mint, - tick_lower.into(), - tick_upper.into(), - minted_liquidity.into(), - new_commitment_after_mint, - position_commitment, + mint_nullifier, root_before_mint, tick_lower.into(), tick_upper.into(), + minted_liquidity.into(), new_commitment_after_mint, position_commitment, ]; start_cheat_caller_address(setup.zylith.contract_address, caller()); - setup.zylith.private_mint_liquidity( - mint_proof, - mint_public_inputs, - tick_lower, - tick_upper, - minted_liquidity, - new_commitment_after_mint, - ); + setup + .zylith + .private_mint_liquidity( + mint_proof, + mint_public_inputs, + tick_lower, + tick_upper, + minted_liquidity, + new_commitment_after_mint, + ); stop_cheat_caller_address(setup.zylith.contract_address); let root_after_mint = setup.zylith.get_merkle_root(); @@ -861,39 +846,28 @@ fn test_private_burn_liquidity_with_valid_proof() { let new_commitment_after_burn: felt252 = 0x555; let burn_proof = array![ - burn_nullifier, - root_after_mint, - tick_lower.into(), - tick_upper.into(), - burn_liquidity.into(), - new_commitment_after_burn, - position_commitment, + burn_nullifier, root_after_mint, tick_lower.into(), tick_upper.into(), + burn_liquidity.into(), new_commitment_after_burn, position_commitment, ]; let burn_public_inputs = array![ - burn_nullifier, - root_after_mint, - tick_lower.into(), - tick_upper.into(), - burn_liquidity.into(), - new_commitment_after_burn, - position_commitment, + burn_nullifier, root_after_mint, tick_lower.into(), tick_upper.into(), + burn_liquidity.into(), new_commitment_after_burn, position_commitment, ]; start_cheat_caller_address(setup.zylith.contract_address, caller()); - let (amount0, amount1) = setup.zylith.private_burn_liquidity( - burn_proof, - burn_public_inputs, - tick_lower, - tick_upper, - burn_liquidity, - new_commitment_after_burn, - ); + let (amount0, amount1) = setup + .zylith + .private_burn_liquidity( + burn_proof, + burn_public_inputs, + tick_lower, + tick_upper, + burn_liquidity, + new_commitment_after_burn, + ); stop_cheat_caller_address(setup.zylith.contract_address); assert!(amount0 > 0 || amount1 > 0, "Burn should return tokens"); - assert!( - setup.zylith.is_nullifier_spent(burn_nullifier), - "Burn nullifier must be spent" - ); + assert!(setup.zylith.is_nullifier_spent(burn_nullifier), "Burn nullifier must be spent"); } From a371a8dd1054bbd96488f06ef132ca8b980ab3bb Mon Sep 17 00:00:00 2001 From: ryzen_xp Date: Thu, 25 Dec 2025 15:52:56 +0530 Subject: [PATCH 3/3] clean code --- zylith/tests/test_zylith.cairo | 167 --------------------------------- 1 file changed, 167 deletions(-) diff --git a/zylith/tests/test_zylith.cairo b/zylith/tests/test_zylith.cairo index 0d2e765..28d74cc 100644 --- a/zylith/tests/test_zylith.cairo +++ b/zylith/tests/test_zylith.cairo @@ -376,173 +376,6 @@ fn test_private_deposit_updates_merkle_tree() { // ); // } -// #[test] -// #[should_panic(expected: ('NULLIFIER_ALREADY_SPENT',))] -// fn test_private_swap_double_spend_fails() { -// let setup = setup_with_erc20(); -// initialize_pool(@setup); -// start_cheat_caller_address(setup.zylith.contract_address, caller()); -// setup -// .zylith -// .initialize( -// setup.token0.contract_address, -// setup.token1.contract_address, -// TEST_FEE, -// TICK_SPACING, -// sqrt_price, -// ); -// stop_cheat_caller_address(setup.zylith.contract_address); - -// // Add liquidity -// start_cheat_caller_address(setup.zylith.contract_address, caller()); -// setup.zylith.mint(-120, 120, 10000000); -// stop_cheat_caller_address(setup.zylith.contract_address); - -// // Deposit -// let commitment1: felt252 = 0x111; -// let amount: u256 = 1000000000000000000; -// start_cheat_caller_address(setup.zylith.contract_address, caller()); -// setup.zylith.private_deposit(setup.token0.contract_address, amount, commitment1); -// let current_root = setup.zylith.get_merkle_root(); -// stop_cheat_caller_address(setup.zylith.contract_address); - -// // Create proof with same nullifier -// let mut proof = array![0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]; -// let nullifier: felt252 = 0x999; -// let new_commitment: felt252 = 0x222; -// let amount_specified: u128 = 100000; -// let zero_for_one = true; -// let sqrt_price_limit = math::MIN_SQRT_RATIO + 1; - -// let mut public_inputs = array![ -// nullifier, current_root, new_commitment, amount_specified.into(), 1, -// (-100000).try_into().unwrap(), 99000.into(), sqrt_price_limit.try_into().unwrap(), -// 0.into(), -// ]; - -// start_cheat_caller_address(setup.zylith.contract_address, caller()); - -// // First swap -// setup -// .zylith -// .private_swap( -// proof.clone(), -// public_inputs.clone(), -// zero_for_one, -// amount_specified, -// sqrt_price_limit, -// new_commitment, -// ); - -// // Try to use same nullifier again - should fail -// let new_commitment2: felt252 = 0x333; -// let mut public_inputs2 = array![ -// nullifier, // Same nullifier! -// current_root, new_commitment2, amount_specified.into(), 1, -// (-100000).try_into().unwrap(), 99000.into(), sqrt_price_limit.try_into().unwrap(), -// 0.into(), -// ]; - -// setup -// .zylith -// .private_swap( -// proof, -// public_inputs2, -// zero_for_one, -// amount_specified, -// sqrt_price_limit, -// new_commitment2, -// ); -// } - -// #[test] -// #[should_panic(expected: ('INVALID_MERKLE_ROOT',))] -// fn test_private_swap_invalid_root_fails() { -// let setup = setup_with_erc20(); -// initialize_pool(@setup); - -// start_cheat_caller_address(setup.zylith.contract_address, caller()); -// setup.zylith.initialize( -// setup.token0.contract_address, -// setup.token1.contract_address, -// TEST_FEE, -// TICK_SPACING, -// sqrt_price, -// ); -// stop_cheat_caller_address(setup.zylith.contract_address); - -// // -------------------------------------------------- -// // Private deposit -// // -------------------------------------------------- -// let deposit_amount: u256 = 1_000_000_000_000_000_000; // 1 token -// let deposit_commitment: felt252 = 0x123456; - -// start_cheat_caller_address(setup.zylith.contract_address, caller()); -// setup.zylith.private_deposit(setup.token0.contract_address, deposit_amount, -// deposit_commitment); -// setup.zylith.private_deposit(setup.token1.contract_address, deposit_amount, -// deposit_commitment); -// stop_cheat_caller_address(setup.zylith.contract_address); - -// let root_before_swap = setup.zylith.get_merkle_root(); - -// // Swap parameters - -// let nullifier: felt252 = 0x01; -// let new_commitment: felt252 = 0x999; -// let amount_specified: u128 = 1000; -// let zero_for_one: bool = true; - -// let sqrt_price_limit = if zero_for_one { -// math::MIN_SQRT_RATIO + 1 -// } else { -// math::MAX_SQRT_RATIO - 1 -// }; - -// // Expected deltas (mocked but CONSISTENT) -// let expected_amount0_delta: felt252 = 100; -// let expected_amount1_delta: felt252 = 200; -// let expected_new_tick: i32 = 0; - -// let proof = array![ -// nullifier, -// root_before_swap, -// new_commitment, -// amount_specified.into(), -// if zero_for_one { 1 } else { 0 }, -// expected_amount0_delta, -// expected_amount1_delta, -// sqrt_price_limit.try_into().unwrap(), -// expected_new_tick.into(), -// ]; - -// let public_inputs = array![ -// nullifier, -// 'fake_root', -// new_commitment, -// amount_specified.into(), -// if zero_for_one { 1 } else { 0 }, -// expected_amount0_delta.try_into().unwrap(), -// expected_amount1_delta.try_into().unwrap(), -// sqrt_price_limit.try_into().unwrap(), -// expected_new_tick.into(), -// ]; - -// // -------------------------------------------------- -// // Execute private swap -// // -------------------------------------------------- -// start_cheat_caller_address(setup.zylith.contract_address, caller()); -// setup.zylith.private_swap( -// proof, -// public_inputs, -// zero_for_one, -// amount_specified, -// sqrt_price_limit, -// new_commitment, -// ); -// stop_cheat_caller_address(setup.zylith.contract_address); -// } - // ============================================================================ // Private Withdraw // ============================================================================