2025-11-14 20:59:42 -05:00
use nssa_core ::{
account ::{ Account , AccountId , AccountWithMetadata , Data } ,
2025-12-07 20:34:26 -05:00
program ::{ ProgramId , ProgramInput , ChainedCall , AccountPostState , PdaSeed , read_nssa_inputs , write_nssa_outputs_with_chained_call } ,
2025-11-14 20:59:42 -05:00
} ;
2025-12-02 17:21:49 -05:00
// The AMM program has five functions (four directly accessible via instructions):
2025-11-20 21:02:18 -05:00
// 1. New AMM definition.
2025-11-14 20:59:42 -05:00
// Arguments to this function are:
2025-12-09 14:42:58 -05:00
// * Seven **default** accounts: [amm_pool, vault_holding_a, vault_holding_b, pool_lp, user_holding_a, user_holding_b, user_holding_lp].
2025-11-20 21:02:18 -05:00
// amm_pool is a default account that will initiate the amm definition account values
// vault_holding_a is a token holding account for token a
// vault_holding_b is a token holding account for token b
// pool_lp is a token holding account for the pool's lp token
2025-12-09 14:42:58 -05:00
// user_holding_a is a token holding account for token a
// user_holding_b is a token holding account for token b
2025-11-20 21:02:18 -05:00
// user_holding_lp is a token holding account for lp token
2025-12-09 14:42:58 -05:00
// * Requires authorization: user_holding_a, user_holding_b
2025-11-21 19:17:50 -05:00
// * An instruction data of 65-bytes, indicating the initial amm reserves' balances and token_program_id with
2025-11-14 20:59:42 -05:00
// the following layout:
2025-12-09 14:42:58 -05:00
// [0x00 || array of balances (little-endian 16 bytes) || AMM_PROGRAM_ID)]
2025-11-20 21:02:18 -05:00
// 2. Swap assets
2025-11-14 20:59:42 -05:00
// Arguments to this function are:
2025-12-09 14:42:58 -05:00
// * Five accounts: [amm_pool, vault_holding_1, vault_holding_2, user_holding_a, user_holding_b].
// * Requires authorization: user holding account associated to TOKEN_DEFINITION_ID (either user_holding_a or user_holding_b)
// * An instruction data byte string of length 49, indicating which token type to swap, quantity of tokens put into the swap
// (of type TOKEN_DEFINITION_ID) and min_amount_out.
2025-11-20 21:02:18 -05:00
// [0x01 || amount (little-endian 16 bytes) || TOKEN_DEFINITION_ID].
// 3. Add liquidity
// Arguments to this function are:
2025-12-09 14:42:58 -05:00
// * Seven accounts: [amm_pool, vault_holding_a, vault_holding_b, pool_lp, user_holding_a, UserHouser_holding_a, user_holding_lp].
// * Requires authorization: user_holding_a, user_holding_b
// * An instruction data byte string of length 49, amounts for minimum amount of liquidity from add (min_amount_lp),
// * max amount added for each token (max_amount_a and max_amount_b); indicate
// [0x02 || array of of balances (little-endian 16 bytes)].
2025-11-20 21:02:18 -05:00
// 4. Remove liquidity
2025-12-09 14:42:58 -05:00
// * Seven accounts: [amm_pool, vault_holding_a, vault_holding_b, pool_lp, user_holding_a, UserHouser_holding_a, user_holding_lp].
// * Requires authorization: user_holding_lp
// * An instruction data byte string of length 49, amounts for minimum amount of liquidity to redeem (balance_lp),
// * minimum balance of each token to remove (min_amount_a and min_amount_b); indicate
// [0x03 || array of balances (little-endian 16 bytes)].
// - Internal functions:
2025-12-02 17:21:49 -05:00
// - Swap logic
// Arguments of this function are:
// * Four accounts: [user_deposit_tx, vault_deposit_tx, vault_withdraw_tx, user_withdraw_tx].
// user_deposit_tx and vault_deposit_tx define deposit transaction.
// vault_withdraw_tx and user_withdraw_tx define withdraw transaction.
// * deposit_amount is the amount for user_deposit_tx -> vault_deposit_tx transfer.
// * reserve_amounts is the pool's reserves; used to compute the withdraw amount.
// * Outputs the token transfers as a Vec<ChainedCall> and the withdraw amount.
2025-12-09 14:42:58 -05:00
// - PDA computations:
// * compute_pool_pda: AMM_PROGRAM_ID, token definitions for the pool pair
// * compute_vault_pda: AMM_PROGRAM_ID, pool definition id, definition token id
// * compute_liquidity_token_pda: AMM_PROGRAM, pool definition id, pool definition id
// - PDA seed computations:
// * compute_pool_pda_seed: token definitions for the pool pair
// * compute_vault_pda_seed: pool definition id, definition token id,
// * compute_liquidity_token_pda_seed: pool definition id
2025-11-14 20:59:42 -05:00
2025-12-06 14:52:18 -05:00
const POOL_DEFINITION_DATA_SIZE : usize = 225 ;
2025-12-04 21:53:58 -05:00
2025-12-07 20:34:26 -05:00
#[ derive(Default) ]
2025-11-14 20:59:42 -05:00
struct PoolDefinition {
2025-12-02 15:20:16 -05:00
definition_token_a_id : AccountId ,
definition_token_b_id : AccountId ,
2025-12-08 22:05:51 -05:00
vault_a_id : AccountId ,
vault_b_id : AccountId ,
2025-11-14 20:59:42 -05:00
liquidity_pool_id : AccountId ,
2025-12-04 21:53:58 -05:00
liquidity_pool_supply : u128 ,
2025-11-14 20:59:42 -05:00
reserve_a : u128 ,
reserve_b : u128 ,
2025-12-06 14:52:18 -05:00
fees : u128 ,
2025-12-04 21:53:58 -05:00
active : bool
2025-11-14 20:59:42 -05:00
}
impl PoolDefinition {
2025-12-15 18:55:38 -05:00
fn into_data ( self ) -> Data {
2025-11-14 20:59:42 -05:00
let mut bytes = [ 0 ; POOL_DEFINITION_DATA_SIZE ] ;
bytes [ 0 .. 32 ] . copy_from_slice ( & self . definition_token_a_id . to_bytes ( ) ) ;
bytes [ 32 .. 64 ] . copy_from_slice ( & self . definition_token_b_id . to_bytes ( ) ) ;
2025-12-08 22:05:51 -05:00
bytes [ 64 .. 96 ] . copy_from_slice ( & self . vault_a_id . to_bytes ( ) ) ;
bytes [ 96 .. 128 ] . copy_from_slice ( & self . vault_b_id . to_bytes ( ) ) ;
2025-11-14 20:59:42 -05:00
bytes [ 128 .. 160 ] . copy_from_slice ( & self . liquidity_pool_id . to_bytes ( ) ) ;
2025-12-04 21:53:58 -05:00
bytes [ 160 .. 176 ] . copy_from_slice ( & self . liquidity_pool_supply . to_le_bytes ( ) ) ;
2025-11-14 20:59:42 -05:00
bytes [ 176 .. 192 ] . copy_from_slice ( & self . reserve_a . to_le_bytes ( ) ) ;
bytes [ 192 .. 208 ] . copy_from_slice ( & self . reserve_b . to_le_bytes ( ) ) ;
2025-12-06 14:52:18 -05:00
bytes [ 208 .. 224 ] . copy_from_slice ( & self . fees . to_le_bytes ( ) ) ;
bytes [ 224 ] = self . active as u8 ;
2025-12-15 18:55:38 -05:00
bytes
. to_vec ( )
. try_into ( )
. expect ( " 225 bytes should fit into Data " )
2025-11-14 20:59:42 -05:00
}
fn parse ( data : & [ u8 ] ) -> Option < Self > {
if data . len ( ) ! = POOL_DEFINITION_DATA_SIZE {
None
} else {
2025-12-04 21:53:58 -05:00
let definition_token_a_id = AccountId ::new ( data [ 0 .. 32 ] . try_into ( ) . expect ( " Parse data: The AMM program must be provided a valid AccountId for Token A definition " ) ) ;
let definition_token_b_id = AccountId ::new ( data [ 32 .. 64 ] . try_into ( ) . expect ( " Parse data: The AMM program must be provided a valid AccountId for Vault B definition " ) ) ;
2025-12-08 22:05:51 -05:00
let vault_a_id = AccountId ::new ( data [ 64 .. 96 ] . try_into ( ) . expect ( " Parse data: The AMM program must be provided a valid AccountId for Vault A " ) ) ;
let vault_b_id = AccountId ::new ( data [ 96 .. 128 ] . try_into ( ) . expect ( " Parse data: The AMM program must be provided a valid AccountId for Vault B " ) ) ;
2025-12-04 21:53:58 -05:00
let liquidity_pool_id = AccountId ::new ( data [ 128 .. 160 ] . try_into ( ) . expect ( " Parse data: The AMM program must be provided a valid AccountId for Token liquidity pool definition " ) ) ;
let liquidity_pool_supply = u128 ::from_le_bytes ( data [ 160 .. 176 ] . try_into ( ) . expect ( " Parse data: The AMM program must be provided a valid u128 for liquidity cap " ) ) ;
let reserve_a = u128 ::from_le_bytes ( data [ 176 .. 192 ] . try_into ( ) . expect ( " Parse data: The AMM program must be provided a valid u128 for reserve A balance " ) ) ;
let reserve_b = u128 ::from_le_bytes ( data [ 192 .. 208 ] . try_into ( ) . expect ( " Parse data: The AMM program must be provided a valid u128 for reserve B balance " ) ) ;
2025-12-06 14:52:18 -05:00
let fees = u128 ::from_le_bytes ( data [ 208 .. 224 ] . try_into ( ) . expect ( " Parse data: The AMM program must be provided a valid u128 for fees " ) ) ;
let active = match data [ 224 ] {
2025-12-04 21:53:58 -05:00
0 = > false ,
1 = > true ,
_ = > panic! ( " Parse data: The AMM program must be provided a valid bool for active " ) ,
} ;
2025-11-14 20:59:42 -05:00
Some ( Self {
definition_token_a_id ,
definition_token_b_id ,
2025-12-08 22:05:51 -05:00
vault_a_id ,
vault_b_id ,
2025-11-14 20:59:42 -05:00
liquidity_pool_id ,
2025-12-04 21:53:58 -05:00
liquidity_pool_supply ,
2025-11-14 20:59:42 -05:00
reserve_a ,
reserve_b ,
2025-12-06 14:52:18 -05:00
fees ,
2025-12-04 21:53:58 -05:00
active ,
2025-11-14 20:59:42 -05:00
} )
}
}
}
//TODO: remove repeated code for Token_Definition and TokenHoldling
2025-12-04 21:53:58 -05:00
const TOKEN_DEFINITION_TYPE : u8 = 0 ;
const TOKEN_DEFINITION_DATA_SIZE : usize = 23 ;
2025-11-14 20:59:42 -05:00
const TOKEN_HOLDING_TYPE : u8 = 1 ;
const TOKEN_HOLDING_DATA_SIZE : usize = 49 ;
2025-12-04 21:53:58 -05:00
struct TokenDefinition {
account_type : u8 ,
name : [ u8 ; 6 ] ,
total_supply : u128 ,
}
2025-11-14 20:59:42 -05:00
struct TokenHolding {
account_type : u8 ,
definition_id : AccountId ,
balance : u128 ,
}
2025-12-04 21:53:58 -05:00
impl TokenDefinition {
2025-12-15 18:55:38 -05:00
fn into_data ( self ) -> Data {
2025-12-04 21:53:58 -05:00
let mut bytes = [ 0 ; TOKEN_DEFINITION_DATA_SIZE ] ;
bytes [ 0 ] = self . account_type ;
bytes [ 1 .. 7 ] . copy_from_slice ( & self . name ) ;
bytes [ 7 .. ] . copy_from_slice ( & self . total_supply . to_le_bytes ( ) ) ;
2025-12-15 18:55:38 -05:00
bytes
. to_vec ( )
. try_into ( )
. expect ( " 23 bytes should fit into Data " )
2025-12-04 21:53:58 -05:00
}
2025-12-15 18:55:38 -05:00
2025-12-04 21:53:58 -05:00
fn parse ( data : & [ u8 ] ) -> Option < Self > {
if data . len ( ) ! = TOKEN_DEFINITION_DATA_SIZE | | data [ 0 ] ! = TOKEN_DEFINITION_TYPE {
None
} else {
let account_type = data [ 0 ] ;
let name = data [ 1 .. 7 ] . try_into ( ) . unwrap ( ) ;
let total_supply = u128 ::from_le_bytes (
data [ 7 .. ]
. try_into ( )
. expect ( " Total supply must be 16 bytes little-endian " ) ,
) ;
Some ( Self {
account_type ,
name ,
total_supply ,
} )
}
}
}
2025-11-14 20:59:42 -05:00
impl TokenHolding {
2025-12-04 21:53:58 -05:00
fn new ( definition_id : & AccountId ) -> Self {
Self {
account_type : TOKEN_HOLDING_TYPE ,
definition_id : definition_id . clone ( ) ,
balance : 0 ,
}
}
2025-11-14 20:59:42 -05:00
fn parse ( data : & [ u8 ] ) -> Option < Self > {
if data . len ( ) ! = TOKEN_HOLDING_DATA_SIZE | | data [ 0 ] ! = TOKEN_HOLDING_TYPE {
None
} else {
let account_type = data [ 0 ] ;
2025-12-04 21:53:58 -05:00
let definition_id = AccountId ::new (
data [ 1 .. 33 ]
. try_into ( )
. expect ( " Defintion ID must be 32 bytes long " ) ,
) ;
let balance = u128 ::from_le_bytes (
data [ 33 .. ]
. try_into ( )
. expect ( " balance must be 16 bytes little-endian " ) ,
) ;
2025-11-14 20:59:42 -05:00
Some ( Self {
definition_id ,
balance ,
account_type ,
} )
}
}
fn into_data ( self ) -> Data {
let mut bytes = [ 0 ; TOKEN_HOLDING_DATA_SIZE ] ;
bytes [ 0 ] = self . account_type ;
bytes [ 1 .. 33 ] . copy_from_slice ( & self . definition_id . to_bytes ( ) ) ;
bytes [ 33 .. ] . copy_from_slice ( & self . balance . to_le_bytes ( ) ) ;
2025-12-15 18:55:38 -05:00
bytes
. to_vec ( )
. try_into ( )
. expect ( " 49 bytes should fit into Data " )
2025-11-14 20:59:42 -05:00
}
}
2025-11-24 19:44:08 -05:00
2025-11-25 23:06:47 -05:00
type Instruction = Vec < u8 > ;
fn main ( ) {
2025-12-15 18:55:38 -05:00
let ( ProgramInput {
2025-11-25 23:06:47 -05:00
pre_states ,
instruction ,
2025-12-15 18:55:38 -05:00
} , instruction_words ) = read_nssa_inputs ::< Instruction > ( ) ;
2025-11-25 23:06:47 -05:00
2025-12-07 20:34:26 -05:00
let ( post_states , chained_calls ) = match instruction [ 0 ] {
2025-11-25 23:06:47 -05:00
0 = > {
2025-12-04 21:53:58 -05:00
let balance_a : u128 = u128 ::from_le_bytes ( instruction [ 1 .. 17 ] . try_into ( ) . expect ( " New definition: AMM Program expects u128 for balance a " ) ) ;
let balance_b : u128 = u128 ::from_le_bytes ( instruction [ 17 .. 33 ] . try_into ( ) . expect ( " New definition: AMM Program expects u128 for balance b " ) ) ;
2025-12-07 20:34:26 -05:00
2025-12-08 22:05:51 -05:00
// Convert Vec<u8> to ProgramId ([u32;8])
let mut amm_program_id : [ u32 ; 8 ] = [ 0 ; 8 ] ;
amm_program_id [ 0 ] = u32 ::from_le_bytes ( instruction [ 33 .. 37 ] . try_into ( ) . expect ( " New definition: AMM Program expects valid u32 " ) ) ;
amm_program_id [ 1 ] = u32 ::from_le_bytes ( instruction [ 37 .. 41 ] . try_into ( ) . expect ( " New definition: AMM Program expects valid u32 " ) ) ;
amm_program_id [ 2 ] = u32 ::from_le_bytes ( instruction [ 41 .. 45 ] . try_into ( ) . expect ( " New definition: AMM Program expects valid u32 " ) ) ;
amm_program_id [ 3 ] = u32 ::from_le_bytes ( instruction [ 45 .. 49 ] . try_into ( ) . expect ( " New definition: AMM Program expects valid u32 " ) ) ;
amm_program_id [ 4 ] = u32 ::from_le_bytes ( instruction [ 49 .. 53 ] . try_into ( ) . expect ( " New definition: AMM Program expects valid u32 " ) ) ;
amm_program_id [ 5 ] = u32 ::from_le_bytes ( instruction [ 53 .. 57 ] . try_into ( ) . expect ( " New definition: AMM Program expects valid u32 " ) ) ;
amm_program_id [ 6 ] = u32 ::from_le_bytes ( instruction [ 57 .. 61 ] . try_into ( ) . expect ( " New definition: AMM Program expects valid u32 " ) ) ;
amm_program_id [ 7 ] = u32 ::from_le_bytes ( instruction [ 61 .. 65 ] . try_into ( ) . expect ( " New definition: AMM Program expects valid u32 " ) ) ;
new_definition ( & pre_states , & [ balance_a , balance_b ] , amm_program_id )
2025-11-25 23:06:47 -05:00
}
1 = > {
2025-12-08 22:05:51 -05:00
let mut token_in_id : [ u8 ; 32 ] = [ 0 ; 32 ] ;
token_in_id [ 0 .. ] . copy_from_slice ( & instruction [ 33 .. 65 ] ) ;
let token_in_id = AccountId ::new ( token_in_id ) ;
2025-11-25 23:06:47 -05:00
2025-12-06 14:52:18 -05:00
let amount_in = u128 ::from_le_bytes ( instruction [ 1 .. 17 ] . try_into ( ) . expect ( " Swap: AMM Program expects valid u128 for balance to move " ) ) ;
let min_amount_out = u128 ::from_le_bytes ( instruction [ 17 .. 33 ] . try_into ( ) . expect ( " Swap: AMM Program expects valid u128 for balance to move " ) ) ;
2025-11-25 23:06:47 -05:00
2025-12-08 22:05:51 -05:00
swap ( & pre_states , & [ amount_in , min_amount_out ] , token_in_id )
2025-11-25 23:06:47 -05:00
}
2 = > {
2025-12-08 13:19:30 -05:00
let min_amount_lp = u128 ::from_le_bytes ( instruction [ 1 .. 17 ] . try_into ( ) . expect ( " Add liquidity: AMM Program expects valid u128 for min amount liquidity " ) ) ;
2025-12-06 14:52:18 -05:00
let max_amount_a = u128 ::from_le_bytes ( instruction [ 17 .. 33 ] . try_into ( ) . expect ( " Add liquidity: AMM Program expects valid u128 for max amount a " ) ) ;
let max_amount_b = u128 ::from_le_bytes ( instruction [ 33 .. 49 ] . try_into ( ) . expect ( " Add liquidity: AMM Program expects valid u128 for max amount b " ) ) ;
2025-12-07 20:34:26 -05:00
add_liquidity ( & pre_states , & [ min_amount_lp , max_amount_a , max_amount_b ] )
2025-11-25 23:06:47 -05:00
}
3 = > {
2025-12-04 21:53:58 -05:00
let balance_lp = u128 ::from_le_bytes ( instruction [ 1 .. 17 ] . try_into ( ) . expect ( " Remove liquidity: AMM Program expects valid u128 for balance liquidity " ) ) ;
2025-12-08 13:19:30 -05:00
let min_amount_a = u128 ::from_le_bytes ( instruction [ 17 .. 33 ] . try_into ( ) . expect ( " Remove liquidity: AMM Program expects valid u128 for balance a " ) ) ;
let min_amount_b = u128 ::from_le_bytes ( instruction [ 33 .. 49 ] . try_into ( ) . expect ( " Remove liquidity: AMM Program expects valid u128 for balance b " ) ) ;
2025-12-04 21:53:58 -05:00
2025-12-08 13:19:30 -05:00
remove_liquidity ( & pre_states , & [ balance_lp , min_amount_a , min_amount_b ] )
2025-11-25 23:06:47 -05:00
}
_ = > panic! ( " Invalid instruction " ) ,
} ;
2025-11-14 20:59:42 -05:00
2025-12-15 18:55:38 -05:00
write_nssa_outputs_with_chained_call ( instruction_words , pre_states , post_states , chained_calls ) ;
2025-12-07 20:34:26 -05:00
}
2025-12-06 14:52:18 -05:00
2025-12-08 22:05:51 -05:00
fn compute_pool_pda ( amm_program_id : ProgramId , definition_token_a_id : AccountId , definition_token_b_id : AccountId ) -> AccountId {
AccountId ::from ( ( & amm_program_id ,
& compute_pool_pda_seed ( definition_token_a_id , definition_token_b_id ) ) )
}
fn compute_pool_pda_seed ( definition_token_a_id : AccountId , definition_token_b_id : AccountId ) -> PdaSeed {
2025-12-07 20:34:26 -05:00
use risc0_zkvm ::sha ::{ Impl , Sha256 } ;
2025-12-08 22:05:51 -05:00
let mut i : usize = 0 ;
let ( token_1 , token_2 ) = loop {
if definition_token_a_id . value ( ) [ i ] > definition_token_b_id . value ( ) [ i ] {
let token_1 = definition_token_a_id . clone ( ) ;
let token_2 = definition_token_b_id . clone ( ) ;
break ( token_1 , token_2 )
} else if definition_token_a_id . value ( ) [ i ] < definition_token_b_id . value ( ) [ i ] {
let token_1 = definition_token_b_id . clone ( ) ;
let token_2 = definition_token_a_id . clone ( ) ;
break ( token_1 , token_2 )
}
if i = = 32 {
panic! ( " Definitions match " ) ;
} else {
i + = 1 ;
}
} ;
2025-12-08 13:19:30 -05:00
let mut bytes = [ 0 ; 64 ] ;
2025-12-08 22:05:51 -05:00
bytes [ 0 .. 32 ] . copy_from_slice ( & token_1 . to_bytes ( ) ) ;
bytes [ 32 .. ] . copy_from_slice ( & token_2 . to_bytes ( ) ) ;
PdaSeed ::new ( Impl ::hash_bytes ( & bytes ) . as_bytes ( ) . try_into ( ) . expect ( " Hash output must be exactly 32 bytes long " ) )
}
fn compute_vault_pda ( amm_program_id : ProgramId ,
pool_id : AccountId ,
definition_token_id : AccountId
) -> AccountId {
AccountId ::from ( ( & amm_program_id ,
& compute_vault_pda_seed ( pool_id , definition_token_id ) ) )
2025-12-07 20:34:26 -05:00
}
2025-12-06 14:52:18 -05:00
2025-12-08 22:05:51 -05:00
fn compute_vault_pda_seed ( pool_id : AccountId ,
definition_token_id : AccountId
) -> PdaSeed {
2025-12-07 20:34:26 -05:00
use risc0_zkvm ::sha ::{ Impl , Sha256 } ;
2025-12-08 13:19:30 -05:00
let mut bytes = [ 0 ; 64 ] ;
bytes [ 0 .. 32 ] . copy_from_slice ( & pool_id . to_bytes ( ) ) ;
bytes [ 32 .. ] . copy_from_slice ( & definition_token_id . to_bytes ( ) ) ;
2025-12-06 14:52:18 -05:00
2025-12-08 13:19:30 -05:00
PdaSeed ::new ( Impl ::hash_bytes ( & bytes ) . as_bytes ( ) . try_into ( ) . expect ( " Hash output must be exactly 32 bytes long " ) )
2025-12-06 14:52:18 -05:00
}
2025-12-08 22:05:51 -05:00
fn compute_liquidity_token_pda ( amm_program_id : ProgramId , pool_id : AccountId ) -> AccountId {
AccountId ::from ( ( & amm_program_id ,
& compute_liquidity_token_pda_seed ( pool_id ) ) )
}
fn compute_liquidity_token_pda_seed ( pool_id : AccountId ) -> PdaSeed {
use risc0_zkvm ::sha ::{ Impl , Sha256 } ;
let mut bytes = [ 0 ; 64 ] ;
bytes [ 0 .. 32 ] . copy_from_slice ( & pool_id . to_bytes ( ) ) ;
bytes [ 32 .. ] . copy_from_slice ( & [ 0 ; 32 ] ) ;
PdaSeed ::new ( Impl ::hash_bytes ( & bytes ) . as_bytes ( ) . try_into ( ) . expect ( " Hash output must be exactly 32 bytes long " ) )
}
2025-12-07 20:34:26 -05:00
fn new_definition (
2025-11-14 20:59:42 -05:00
pre_states : & [ AccountWithMetadata ] ,
balance_in : & [ u128 ] ,
2025-12-08 22:05:51 -05:00
amm_program_id : ProgramId ,
2025-12-07 20:34:26 -05:00
) -> ( Vec < AccountPostState > , Vec < ChainedCall > ) {
2025-12-06 14:52:18 -05:00
2025-11-14 20:59:42 -05:00
//Pool accounts: pool itself, and its 2 vaults and LP token
//2 accounts for funding tokens
//initial funder's LP account
2025-12-07 20:34:26 -05:00
if pre_states . len ( ) ! = 7 {
2025-11-18 14:43:40 -05:00
panic! ( " Invalid number of input accounts " )
2025-11-14 20:59:42 -05:00
}
if balance_in . len ( ) ! = 2 {
2025-12-07 20:34:26 -05:00
panic! ( " Invalid number of input balances " )
2025-11-14 20:59:42 -05:00
}
2025-12-07 20:34:26 -05:00
let pool = & pre_states [ 0 ] ;
let vault_a = & pre_states [ 1 ] ;
let vault_b = & pre_states [ 2 ] ;
let pool_lp = & pre_states [ 3 ] ;
let user_holding_a = & pre_states [ 4 ] ;
let user_holding_b = & pre_states [ 5 ] ;
let user_holding_lp = & pre_states [ 6 ] ;
2025-11-14 20:59:42 -05:00
let amount_a = balance_in [ 0 ] ;
let amount_b = balance_in [ 1 ] ;
// Prevents pool constant coefficient (k) from being 0.
2025-11-18 14:43:40 -05:00
if amount_a = = 0 | | amount_b = = 0 {
panic! ( " Balances must be nonzero " )
}
2025-11-14 20:59:42 -05:00
// Verify token_a and token_b are different
2025-12-08 22:05:51 -05:00
let definition_token_a_id = TokenHolding ::parse ( & user_holding_a . account . data )
. expect ( " New definition: AMM Program expects valid Token Holding account for Token A " ) . definition_id ;
let definition_token_b_id = TokenHolding ::parse ( & user_holding_b . account . data )
. expect ( " New definition: AMM Program expects valid Token Holding account for Token B " ) . definition_id ;
// both instances of the same token program
2025-12-07 20:34:26 -05:00
let token_program = user_holding_a . account . program_owner ;
2025-11-17 18:48:17 -05:00
if definition_token_a_id = = definition_token_b_id {
2025-12-09 14:42:58 -05:00
panic! ( " Cannot set up a swap for a token with itself " )
2025-11-17 18:48:17 -05:00
}
2025-12-08 22:05:51 -05:00
if pool . account_id ! = compute_pool_pda ( amm_program_id . clone ( ) ,
definition_token_a_id . clone ( ) ,
definition_token_b_id . clone ( ) ) {
2025-12-07 20:34:26 -05:00
panic! ( " Pool Definition Account ID does not match PDA " ) ;
}
2025-12-08 22:05:51 -05:00
if vault_a . account_id ! = compute_vault_pda ( amm_program_id . clone ( ) ,
pool . account_id . clone ( ) ,
definition_token_a_id . clone ( ) ) | |
vault_b . account_id ! = compute_vault_pda ( amm_program_id . clone ( ) ,
pool . account_id . clone ( ) ,
definition_token_b_id . clone ( ) ) {
2025-12-07 20:34:26 -05:00
panic! ( " Vault ID does not match PDA " ) ;
}
2025-12-08 22:05:51 -05:00
if pool_lp . account_id ! = compute_liquidity_token_pda ( amm_program_id . clone ( ) ,
pool . account_id . clone ( ) ) {
panic! ( " Liquidity pool Token Definition Account ID does not match PDA " ) ;
}
2025-12-07 20:34:26 -05:00
// Verify that Pool Account is not active
let pool_account_data = if pool . account = = Account ::default ( ) {
PoolDefinition ::default ( )
} else {
PoolDefinition ::parse ( & pool . account . data ) . expect ( " AMM program expects a valid Pool account " )
} ;
2025-12-08 22:05:51 -05:00
if pool_account_data . active {
2025-12-07 20:34:26 -05:00
panic! ( " Cannot initialize an active Pool Definition " )
2025-12-06 14:52:18 -05:00
}
2025-12-07 20:34:26 -05:00
//3. LP Token minting calculation
// We assume LP is based on the initial deposit amount for Token_A.
2025-12-06 14:52:18 -05:00
2025-11-14 20:59:42 -05:00
// 5. Update pool account
2025-12-09 14:42:58 -05:00
let mut pool_post = pool . account . clone ( ) ;
2025-11-14 20:59:42 -05:00
let pool_post_definition = PoolDefinition {
definition_token_a_id ,
definition_token_b_id ,
2025-12-08 22:05:51 -05:00
vault_a_id : vault_a . account_id . clone ( ) ,
vault_b_id : vault_b . account_id . clone ( ) ,
liquidity_pool_id : pool_lp . account_id . clone ( ) ,
2025-12-09 14:42:58 -05:00
liquidity_pool_supply : amount_a . clone ( ) ,
reserve_a : amount_a . clone ( ) ,
reserve_b : amount_b . clone ( ) ,
2025-12-06 14:52:18 -05:00
fees : 0 u128 , //TODO: we assume all fees are 0 for now.
2025-12-04 21:53:58 -05:00
active : true ,
2025-11-14 20:59:42 -05:00
} ;
pool_post . data = pool_post_definition . into_data ( ) ;
2025-12-09 14:42:58 -05:00
let pool_post : AccountPostState =
if pool . account = = Account ::default ( ) { AccountPostState ::new_claimed ( pool_post . clone ( ) ) }
else { AccountPostState ::new ( pool_post . clone ( ) ) } ;
2025-11-14 20:59:42 -05:00
2025-12-09 14:42:58 -05:00
let mut chained_calls = Vec ::< ChainedCall > ::new ( ) ;
2025-12-07 20:34:26 -05:00
2025-12-04 21:53:58 -05:00
//Chain call for Token A (user_holding_a -> Vault_A)
2025-12-09 14:42:58 -05:00
let mut instruction_data = [ 0 ; 23 ] ;
instruction_data [ 0 ] = 1 ;
instruction_data [ 1 .. 17 ] . copy_from_slice ( & amount_a . to_le_bytes ( ) ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction_data ) . expect ( " New definition: AMM Program expects valid token transfer instruction data " ) ;
2025-11-14 20:59:42 -05:00
let call_token_a = ChainedCall {
2025-12-09 14:42:58 -05:00
program_id : user_holding_a . account . program_owner ,
instruction_data ,
2025-12-07 20:34:26 -05:00
pre_states : vec ! [ user_holding_a . clone ( ) , vault_a . clone ( ) ] ,
pda_seeds : Vec ::< PdaSeed > ::new ( ) ,
2025-11-14 20:59:42 -05:00
} ;
2025-12-09 14:42:58 -05:00
2025-12-04 21:53:58 -05:00
//Chain call for Token B (user_holding_b -> Vault_B)
2025-12-09 14:42:58 -05:00
let mut instruction_data = [ 0 ; 23 ] ;
instruction_data [ 0 ] = 1 ;
instruction_data [ 1 .. 17 ] . copy_from_slice ( & amount_b . to_le_bytes ( ) ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction_data ) . expect ( " New definition: AMM Program expects valid instruction_data " ) ;
2025-11-25 23:06:47 -05:00
2025-11-14 20:59:42 -05:00
let call_token_b = ChainedCall {
2025-12-09 14:42:58 -05:00
program_id : user_holding_b . account . program_owner ,
instruction_data ,
2025-12-07 20:34:26 -05:00
pre_states : vec ! [ user_holding_b . clone ( ) , vault_b . clone ( ) ] ,
pda_seeds : Vec ::< PdaSeed > ::new ( ) ,
2025-11-14 20:59:42 -05:00
} ;
2025-12-09 14:42:58 -05:00
//Chain call for liquidity token (TokenLP definition -> User LP Holding)
let mut instruction_data = [ 0 ; 23 ] ;
instruction_data [ 0 ] = if pool . account = = Account ::default ( ) { 0 } else { 4 } ; //new or mint
let nme = if pool . account = = Account ::default ( ) { [ 1 u8 ; 6 ] } else { [ 0 u8 ; 6 ] } ;
2025-12-08 22:05:51 -05:00
2025-12-09 14:42:58 -05:00
instruction_data [ 1 .. 17 ] . copy_from_slice ( & amount_a . to_le_bytes ( ) ) ;
instruction_data [ 17 .. ] . copy_from_slice ( & nme ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction_data ) . expect ( " New definition: AMM Program expects valid instruction_data " ) ;
2025-11-25 23:06:47 -05:00
2025-12-08 22:05:51 -05:00
let mut pool_lp_auth = pool_lp . clone ( ) ;
pool_lp_auth . is_authorized = true ;
2025-12-09 14:42:58 -05:00
let token_program_id = user_holding_a . account . program_owner ;
2025-11-14 20:59:42 -05:00
let call_token_lp = ChainedCall {
2025-12-09 14:42:58 -05:00
program_id : token_program_id ,
instruction_data ,
2025-12-08 22:05:51 -05:00
pre_states : vec ! [ pool_lp_auth . clone ( ) , user_holding_lp . clone ( ) ] ,
pda_seeds : vec ! [ compute_liquidity_token_pda_seed ( pool . account_id . clone ( ) ) ] ,
2025-11-14 20:59:42 -05:00
} ;
2025-12-07 20:34:26 -05:00
chained_calls . push ( call_token_lp ) ;
chained_calls . push ( call_token_b ) ;
chained_calls . push ( call_token_a ) ;
2025-11-14 20:59:42 -05:00
2025-12-09 14:42:58 -05:00
2025-11-25 23:06:47 -05:00
let post_states = vec! [
2025-12-09 14:42:58 -05:00
pool_post . clone ( ) ,
2025-12-07 20:34:26 -05:00
AccountPostState ::new ( pre_states [ 1 ] . account . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 2 ] . account . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 3 ] . account . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 4 ] . account . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 5 ] . account . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 6 ] . account . clone ( ) ) ] ;
( post_states . clone ( ) , chained_calls )
2025-11-14 20:59:42 -05:00
}
fn swap (
pre_states : & [ AccountWithMetadata ] ,
2025-12-06 14:52:18 -05:00
amounts : & [ u128 ] ,
2025-12-08 22:05:51 -05:00
token_in_id : AccountId ,
2025-12-07 20:34:26 -05:00
) -> ( Vec < AccountPostState > , Vec < ChainedCall > ) {
2025-11-14 20:59:42 -05:00
if pre_states . len ( ) ! = 5 {
panic! ( " Invalid number of input accounts " ) ;
}
2025-12-06 14:52:18 -05:00
if amounts . len ( ) ! = 2 {
panic! ( " Invalid number of amounts provided " ) ;
}
let amount_in = amounts [ 0 ] ;
let min_amount_out = amounts [ 1 ] ;
2025-11-14 20:59:42 -05:00
let pool = & pre_states [ 0 ] ;
2025-12-02 17:21:49 -05:00
let vault_a = & pre_states [ 1 ] ;
let vault_b = & pre_states [ 2 ] ;
2025-12-04 21:53:58 -05:00
let user_holding_a = & pre_states [ 3 ] ;
let user_holding_b = & pre_states [ 4 ] ;
2025-11-14 20:59:42 -05:00
// Verify vaults are in fact vaults
2025-12-04 21:53:58 -05:00
let pool_def_data = PoolDefinition ::parse ( & pool . account . data ) . expect ( " Swap: AMM Program expects a valid Pool Definition Account " ) ;
if ! pool_def_data . active {
panic! ( " Pool is inactive " ) ;
}
2025-11-20 21:02:18 -05:00
2025-12-08 22:05:51 -05:00
if vault_a . account_id ! = pool_def_data . vault_a_id {
2025-11-21 19:17:50 -05:00
panic! ( " Vault A was not provided " ) ;
2025-12-02 17:21:49 -05:00
}
2025-11-14 20:59:42 -05:00
2025-12-08 22:05:51 -05:00
if vault_b . account_id ! = pool_def_data . vault_b_id {
2025-11-18 14:43:40 -05:00
panic! ( " Vault B was not provided " ) ;
2025-12-02 17:21:49 -05:00
}
2025-11-14 20:59:42 -05:00
2025-12-02 17:21:49 -05:00
// fetch pool reserves
2025-12-06 14:52:18 -05:00
// validates reserves is at least the vaults' balances
if TokenHolding ::parse ( & vault_a . account . data ) . expect ( " Swap: AMM Program expects a valid Token Holding Account for Vault A " ) . balance < pool_def_data . reserve_a {
panic! ( " Reserve for Token A exceeds vault balance " ) ;
}
if TokenHolding ::parse ( & vault_b . account . data ) . expect ( " Swap: AMM Program expects a valid Token Holding Account for Vault B " ) . balance < pool_def_data . reserve_b {
panic! ( " Reserve for Token B exceeds vault balance " ) ;
}
2025-11-14 20:59:42 -05:00
2025-12-07 20:34:26 -05:00
let ( chained_calls , [ deposit_a , withdraw_a ] , [ deposit_b , withdraw_b ] )
2025-12-08 22:05:51 -05:00
= if token_in_id = = pool_def_data . definition_token_a_id {
let ( chained_calls , withdraw_b ) = swap_logic ( & [ user_holding_a . clone ( ) ,
vault_a . clone ( ) ,
vault_b . clone ( ) ,
user_holding_b . clone ( ) ] ,
& [ amount_in , min_amount_out ] ,
& [ pool_def_data . reserve_a , pool_def_data . reserve_b ] ,
pool . account_id . clone ( ) ) ;
2025-12-02 17:21:49 -05:00
2025-12-07 20:34:26 -05:00
( chained_calls , [ amount_in , 0 ] , [ 0 , withdraw_b ] )
2025-12-08 22:05:51 -05:00
} else if token_in_id = = pool_def_data . definition_token_b_id {
let ( chained_calls , withdraw_a ) = swap_logic ( & [ user_holding_b . clone ( ) ,
vault_b . clone ( ) ,
vault_a . clone ( ) ,
user_holding_a . clone ( ) ] ,
& [ amount_in , min_amount_out ] ,
& [ pool_def_data . reserve_b , pool_def_data . reserve_a ] ,
pool . account_id . clone ( ) ) ;
2025-12-02 17:21:49 -05:00
2025-12-07 20:34:26 -05:00
( chained_calls , [ 0 , withdraw_a ] , [ amount_in , 0 ] )
2025-12-02 17:21:49 -05:00
} else {
panic! ( " AccountId is not a token type for the pool " ) ;
} ;
2025-11-14 20:59:42 -05:00
2025-12-02 17:21:49 -05:00
// Update pool account
2025-11-14 20:59:42 -05:00
let mut pool_post = pool . account . clone ( ) ;
let pool_post_definition = PoolDefinition {
definition_token_a_id : pool_def_data . definition_token_a_id . clone ( ) ,
definition_token_b_id : pool_def_data . definition_token_b_id . clone ( ) ,
2025-12-08 22:05:51 -05:00
vault_a_id : pool_def_data . vault_a_id . clone ( ) ,
vault_b_id : pool_def_data . vault_b_id . clone ( ) ,
2025-11-14 20:59:42 -05:00
liquidity_pool_id : pool_def_data . liquidity_pool_id . clone ( ) ,
2025-12-04 21:53:58 -05:00
liquidity_pool_supply : pool_def_data . liquidity_pool_supply . clone ( ) ,
2025-11-14 20:59:42 -05:00
reserve_a : pool_def_data . reserve_a + deposit_a - withdraw_a ,
reserve_b : pool_def_data . reserve_b + deposit_b - withdraw_b ,
2025-12-06 14:52:18 -05:00
fees : 0 u128 ,
2025-12-04 21:53:58 -05:00
active : true ,
2025-11-14 20:59:42 -05:00
} ;
pool_post . data = pool_post_definition . into_data ( ) ;
2025-11-25 23:06:47 -05:00
2025-12-02 17:21:49 -05:00
let post_states = vec! [
2025-12-07 20:34:26 -05:00
AccountPostState ::new ( pool_post . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 1 ] . account . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 2 ] . account . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 3 ] . account . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 4 ] . account . clone ( ) ) ] ;
2025-11-25 23:06:47 -05:00
2025-12-07 20:34:26 -05:00
( post_states , chained_calls )
2025-12-02 17:21:49 -05:00
}
2025-11-25 23:06:47 -05:00
2025-12-02 17:21:49 -05:00
fn swap_logic (
pre_states : & [ AccountWithMetadata ] ,
2025-12-08 22:05:51 -05:00
balances : & [ u128 ] ,
2025-12-02 17:21:49 -05:00
reserve_amounts : & [ u128 ] ,
2025-12-08 22:05:51 -05:00
pool_id : AccountId ,
2025-12-02 17:21:49 -05:00
) -> ( Vec < ChainedCall > , u128 )
{
let user_deposit_tx = pre_states [ 0 ] . clone ( ) ;
let vault_deposit_tx = pre_states [ 1 ] . clone ( ) ;
let vault_withdraw_tx = pre_states [ 2 ] . clone ( ) ;
let user_withdraw_tx = pre_states [ 3 ] . clone ( ) ;
let reserve_deposit_vault_amount = reserve_amounts [ 0 ] ;
let reserve_withdraw_vault_amount = reserve_amounts [ 1 ] ;
2025-12-08 22:05:51 -05:00
let deposit_amount = balances [ 0 ] ;
let min_amount_out = balances [ 1 ] ;
2025-12-02 17:21:49 -05:00
// Compute withdraw amount
// Compute pool's exchange constant
// let k = pool_def_data.reserve_a * pool_def_data.reserve_b;
let withdraw_amount = ( reserve_withdraw_vault_amount * deposit_amount ) / ( reserve_deposit_vault_amount + deposit_amount ) ;
//Slippage check
2025-12-06 14:52:18 -05:00
if min_amount_out > withdraw_amount {
panic! ( " Withdraw amount is less than minimal amount out " ) ;
}
if withdraw_amount = = 0 {
panic! ( " Withdraw amount should be nonzero " ) ;
}
2025-12-02 17:21:49 -05:00
2025-12-07 20:34:26 -05:00
let mut chained_calls = Vec ::new ( ) ;
2025-12-02 17:21:49 -05:00
let mut instruction_data = [ 0 ; 23 ] ;
instruction_data [ 0 ] = 1 ;
instruction_data [ 1 .. 17 ] . copy_from_slice ( & deposit_amount . to_le_bytes ( ) ) ;
2025-12-04 21:53:58 -05:00
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction_data ) . expect ( " Swap Logic: AMM Program expects valid transaction instruction data " ) ;
2025-12-07 20:34:26 -05:00
chained_calls . push (
2025-11-26 21:44:57 -05:00
ChainedCall {
2025-12-02 17:21:49 -05:00
program_id : vault_deposit_tx . account . program_owner ,
2025-12-09 14:42:58 -05:00
instruction_data ,
2025-12-07 20:34:26 -05:00
pre_states : vec ! [ user_deposit_tx . clone ( ) , vault_deposit_tx . clone ( ) ] ,
pda_seeds : Vec ::< PdaSeed > ::new ( ) ,
2025-11-26 21:44:57 -05:00
}
2025-12-02 17:21:49 -05:00
) ;
2025-11-14 20:59:42 -05:00
2025-12-08 22:05:51 -05:00
let mut vault_withdraw_tx = vault_withdraw_tx . clone ( ) ;
vault_withdraw_tx . is_authorized = true ;
2025-12-02 17:21:49 -05:00
let mut instruction_data = [ 0 ; 23 ] ;
instruction_data [ 0 ] = 1 ;
instruction_data [ 1 .. 17 ] . copy_from_slice ( & withdraw_amount . to_le_bytes ( ) ) ;
2025-12-04 21:53:58 -05:00
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction_data ) . expect ( " Swap Logic: AMM Program expects valid transaction instruction data " ) ;
2025-12-07 20:34:26 -05:00
chained_calls . push (
2025-11-26 21:44:57 -05:00
ChainedCall {
2025-12-02 17:21:49 -05:00
program_id : vault_deposit_tx . account . program_owner ,
2025-12-09 14:42:58 -05:00
instruction_data ,
2025-12-07 20:34:26 -05:00
pre_states : vec ! [ vault_withdraw_tx . clone ( ) , user_withdraw_tx . clone ( ) ] ,
2025-12-08 22:05:51 -05:00
pda_seeds : vec ! [ compute_vault_pda_seed ( pool_id ,
TokenHolding ::parse ( & vault_withdraw_tx . account . data )
. expect ( " Swap Logic: AMM Program expects valid token data " )
. definition_id ) ] ,
2025-11-26 21:44:57 -05:00
}
2025-12-02 17:21:49 -05:00
) ;
2025-11-26 21:44:57 -05:00
2025-12-07 20:34:26 -05:00
( chained_calls , withdraw_amount )
2025-11-14 20:59:42 -05:00
}
fn add_liquidity ( pre_states : & [ AccountWithMetadata ] ,
2025-12-07 20:34:26 -05:00
balances : & [ u128 ] ) -> ( Vec < AccountPostState > , Vec < ChainedCall > ) {
2025-11-14 20:59:42 -05:00
if pre_states . len ( ) ! = 7 {
panic! ( " Invalid number of input accounts " ) ;
}
let pool = & pre_states [ 0 ] ;
2025-12-04 21:53:58 -05:00
let vault_a = & pre_states [ 1 ] ;
let vault_b = & pre_states [ 2 ] ;
2025-12-06 14:52:18 -05:00
let pool_definition_lp = & pre_states [ 3 ] ;
2025-12-04 21:53:58 -05:00
let user_holding_a = & pre_states [ 4 ] ;
let user_holding_b = & pre_states [ 5 ] ;
let user_holding_lp = & pre_states [ 6 ] ;
2025-11-14 20:59:42 -05:00
2025-11-28 08:11:04 -05:00
// Verify vaults are in fact vaults
2025-12-04 21:53:58 -05:00
let pool_def_data = PoolDefinition ::parse ( & pool . account . data ) . expect ( " Add liquidity: AMM Program expects valid Pool Definition Account " ) ;
2025-12-08 22:05:51 -05:00
if vault_a . account_id ! = pool_def_data . vault_a_id {
2025-11-28 08:11:04 -05:00
panic! ( " Vault A was not provided " ) ;
2025-12-04 21:53:58 -05:00
}
2025-12-06 14:52:18 -05:00
if pool_def_data . liquidity_pool_id ! = pool_definition_lp . account_id {
panic! ( " LP definition mismatch " ) ;
}
2025-12-08 22:05:51 -05:00
if vault_b . account_id ! = pool_def_data . vault_b_id {
2025-11-18 14:43:40 -05:00
panic! ( " Vault B was not provided " ) ;
2025-12-04 21:53:58 -05:00
}
2025-12-06 14:52:18 -05:00
if balances . len ( ) ! = 3 {
2025-11-20 21:02:18 -05:00
panic! ( " Invalid number of input balances " ) ;
}
2025-12-06 14:52:18 -05:00
let min_amount_lp = balances [ 0 ] ;
let max_amount_a = balances [ 1 ] ;
let max_amount_b = balances [ 2 ] ;
2025-11-14 20:59:42 -05:00
2025-11-20 21:02:18 -05:00
if max_amount_a = = 0 | | max_amount_b = = 0 {
panic! ( " Both max-balances must be nonzero " ) ;
}
2025-12-06 14:52:18 -05:00
if min_amount_lp = = 0 {
panic! ( " Min-lp must be nonzero " ) ;
}
2025-11-20 21:02:18 -05:00
2025-11-26 21:44:57 -05:00
// 2. Determine deposit amount
2025-12-04 21:53:58 -05:00
let vault_b_balance = TokenHolding ::parse ( & vault_b . account . data ) . expect ( " Add liquidity: AMM Program expects valid Token Holding Account for Vault B " ) . balance ;
let vault_a_balance = TokenHolding ::parse ( & vault_a . account . data ) . expect ( " Add liquidity: AMM Program expects valid Token Holding Account for Vault A " ) . balance ;
2025-12-06 14:52:18 -05:00
2025-11-20 21:02:18 -05:00
if pool_def_data . reserve_a = = 0 | | pool_def_data . reserve_b = = 0 {
panic! ( " Reserves must be nonzero " ) ;
}
2025-12-06 14:52:18 -05:00
if vault_a_balance < pool_def_data . reserve_a | | vault_b_balance < pool_def_data . reserve_b {
panic! ( " Vaults' balances must be at least the reserve amounts " ) ;
}
2025-11-26 21:44:57 -05:00
2025-12-06 14:52:18 -05:00
// Calculate actual_amounts
let ideal_a : u128 = ( pool_def_data . reserve_a * max_amount_b ) / pool_def_data . reserve_b ;
let ideal_b : u128 = ( pool_def_data . reserve_b * max_amount_a ) / pool_def_data . reserve_a ;
2025-11-14 20:59:42 -05:00
2025-12-06 14:52:18 -05:00
let actual_amount_a = if ideal_a > max_amount_a { max_amount_a } else { ideal_a } ;
let actual_amount_b = if ideal_b > max_amount_b { max_amount_b } else { ideal_b } ;
2025-11-20 21:02:18 -05:00
2025-12-06 14:52:18 -05:00
// 3. Validate amounts
if max_amount_a < actual_amount_a | | max_amount_b < actual_amount_b {
panic! ( " Actual trade amounts cannot exceed max_amounts " ) ;
2025-11-20 21:02:18 -05:00
}
if actual_amount_a = = 0 | | actual_amount_b = = 0 {
panic! ( " A trade amount is 0 " ) ;
}
2025-11-14 20:59:42 -05:00
// 4. Calculate LP to mint
2025-12-06 14:52:18 -05:00
let delta_lp = std ::cmp ::min ( pool_def_data . liquidity_pool_supply * actual_amount_a / pool_def_data . reserve_a ,
pool_def_data . liquidity_pool_supply * actual_amount_b / pool_def_data . reserve_b ) ;
if delta_lp = = 0 {
panic! ( " Payable LP must be nonzero " ) ;
}
2025-11-14 20:59:42 -05:00
2025-12-06 14:52:18 -05:00
if delta_lp < min_amount_lp {
panic! ( " Payable LP is less than provided minimum LP amount " ) ;
}
2025-11-14 20:59:42 -05:00
// 5. Update pool account
let mut pool_post = pool . account . clone ( ) ;
let pool_post_definition = PoolDefinition {
definition_token_a_id : pool_def_data . definition_token_a_id . clone ( ) ,
definition_token_b_id : pool_def_data . definition_token_b_id . clone ( ) ,
2025-12-08 22:05:51 -05:00
vault_a_id : pool_def_data . vault_a_id . clone ( ) ,
vault_b_id : pool_def_data . vault_b_id . clone ( ) ,
2025-11-14 20:59:42 -05:00
liquidity_pool_id : pool_def_data . liquidity_pool_id . clone ( ) ,
2025-12-04 21:53:58 -05:00
liquidity_pool_supply : pool_def_data . liquidity_pool_supply + delta_lp ,
2025-11-14 20:59:42 -05:00
reserve_a : pool_def_data . reserve_a + actual_amount_a ,
reserve_b : pool_def_data . reserve_b + actual_amount_b ,
2025-12-06 14:52:18 -05:00
fees : 0 u128 ,
2025-12-04 21:53:58 -05:00
active : true ,
2025-11-14 20:59:42 -05:00
} ;
2025-11-25 23:06:47 -05:00
2025-11-14 20:59:42 -05:00
pool_post . data = pool_post_definition . into_data ( ) ;
let mut chained_call = Vec ::new ( ) ;
2025-12-07 20:34:26 -05:00
// Chain call for Token A (UserHoldingA -> Vault_A)
2025-11-14 20:59:42 -05:00
let mut instruction_data = [ 0 ; 23 ] ;
instruction_data [ 0 ] = 1 ;
instruction_data [ 1 .. 17 ] . copy_from_slice ( & actual_amount_a . to_le_bytes ( ) ) ;
2025-12-04 21:53:58 -05:00
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction_data ) . expect ( " Add liquidity: AMM Program expects valid token transfer instruction data " ) ;
2025-11-14 20:59:42 -05:00
let call_token_a = ChainedCall {
2025-12-04 21:53:58 -05:00
program_id : vault_a . account . program_owner ,
2025-12-09 14:42:58 -05:00
instruction_data ,
2025-12-07 20:34:26 -05:00
pre_states : vec ! [ user_holding_a . clone ( ) , vault_a . clone ( ) ] ,
pda_seeds : Vec ::< PdaSeed > ::new ( ) ,
2025-11-14 20:59:42 -05:00
} ;
2025-12-07 20:34:26 -05:00
// Chain call for Token B (UserHoldingB -> Vault_B)
2025-11-25 23:06:47 -05:00
let mut instruction_data = [ 0 ; 23 ] ;
instruction_data [ 0 ] = 1 ;
2025-11-14 20:59:42 -05:00
instruction_data [ 1 .. 17 ] . copy_from_slice ( & actual_amount_b . to_le_bytes ( ) ) ;
2025-12-04 21:53:58 -05:00
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction_data ) . expect ( " Add liquidity: AMM Program expects valid token transfer instruction data " ) ;
2025-11-14 20:59:42 -05:00
let call_token_b = ChainedCall {
2025-12-04 21:53:58 -05:00
program_id : vault_b . account . program_owner ,
2025-12-09 14:42:58 -05:00
instruction_data ,
2025-12-07 20:34:26 -05:00
pre_states : vec ! [ user_holding_b . clone ( ) , vault_b . clone ( ) ] ,
pda_seeds : Vec ::< PdaSeed > ::new ( ) ,
2025-11-14 20:59:42 -05:00
} ;
2025-11-26 21:44:57 -05:00
2025-12-08 22:05:51 -05:00
// Chain call for LP (mint new tokens for user_holding_lp)
let mut pool_definition_lp_auth = pool_definition_lp . clone ( ) ;
pool_definition_lp_auth . is_authorized = true ;
2025-11-25 23:06:47 -05:00
let mut instruction_data = [ 0 ; 23 ] ;
2025-12-06 14:52:18 -05:00
instruction_data [ 0 ] = 4 ;
2025-11-14 20:59:42 -05:00
instruction_data [ 1 .. 17 ] . copy_from_slice ( & delta_lp . to_le_bytes ( ) ) ;
2025-12-04 21:53:58 -05:00
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction_data ) . expect ( " Add liquidity: AMM Program expects valid token transfer instruction data " ) ;
2025-11-14 20:59:42 -05:00
let call_token_lp = ChainedCall {
2025-12-06 14:52:18 -05:00
program_id : pool_definition_lp . account . program_owner ,
2025-12-09 14:42:58 -05:00
instruction_data ,
2025-12-08 22:05:51 -05:00
pre_states : vec ! [ pool_definition_lp_auth . clone ( ) , user_holding_lp . clone ( ) ] ,
pda_seeds : vec ! [ compute_liquidity_token_pda_seed ( pool . account_id . clone ( ) ) ]
2025-11-14 20:59:42 -05:00
} ;
chained_call . push ( call_token_lp ) ;
chained_call . push ( call_token_b ) ;
chained_call . push ( call_token_a ) ;
2025-11-25 09:02:43 -05:00
let post_states = vec! [
2025-12-07 20:34:26 -05:00
AccountPostState ::new ( pool_post ) ,
AccountPostState ::new ( pre_states [ 1 ] . account . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 2 ] . account . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 3 ] . account . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 4 ] . account . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 5 ] . account . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 6 ] . account . clone ( ) ) , ] ;
2025-11-14 20:59:42 -05:00
2025-12-07 20:34:26 -05:00
( post_states , chained_call )
2025-11-14 20:59:42 -05:00
}
2025-12-04 21:53:58 -05:00
fn remove_liquidity ( pre_states : & [ AccountWithMetadata ] ,
amounts : & [ u128 ]
2025-12-07 20:34:26 -05:00
) -> ( Vec < AccountPostState > , Vec < ChainedCall > )
2025-12-04 21:53:58 -05:00
{
2025-11-14 20:59:42 -05:00
if pre_states . len ( ) ! = 7 {
panic! ( " Invalid number of input accounts " ) ;
}
let pool = & pre_states [ 0 ] ;
2025-12-04 21:53:58 -05:00
let vault_a = & pre_states [ 1 ] ;
let vault_b = & pre_states [ 2 ] ;
2025-12-06 14:52:18 -05:00
let pool_definition_lp = & pre_states [ 3 ] ;
2025-12-04 21:53:58 -05:00
let user_holding_a = & pre_states [ 4 ] ;
let user_holding_b = & pre_states [ 5 ] ;
let user_holding_lp = & pre_states [ 6 ] ;
if amounts . len ( ) ! = 3 {
panic! ( " Invalid number of balances " ) ;
}
let amount_lp = amounts [ 0 ] ;
let amount_min_a = amounts [ 1 ] ;
let amount_min_b = amounts [ 2 ] ;
2025-11-28 08:11:04 -05:00
// Verify vaults are in fact vaults
2025-12-04 21:53:58 -05:00
let pool_def_data = PoolDefinition ::parse ( & pool . account . data ) . expect ( " Remove liquidity: AMM Program expects a valid Pool Definition Account " ) ;
2025-11-14 20:59:42 -05:00
2025-12-04 21:53:58 -05:00
if ! pool_def_data . active {
panic! ( " Pool is inactive " ) ;
}
2025-12-06 14:52:18 -05:00
if pool_def_data . liquidity_pool_id ! = pool_definition_lp . account_id {
panic! ( " LP definition mismatch " ) ;
}
2025-12-08 22:05:51 -05:00
if vault_a . account_id ! = pool_def_data . vault_a_id {
2025-11-28 08:11:04 -05:00
panic! ( " Vault A was not provided " ) ;
2025-12-04 21:53:58 -05:00
}
2025-12-08 22:05:51 -05:00
if vault_b . account_id ! = pool_def_data . vault_b_id {
2025-11-18 14:43:40 -05:00
panic! ( " Vault B was not provided " ) ;
2025-12-04 21:53:58 -05:00
}
2025-12-08 13:19:30 -05:00
// Vault addresses do not need to be checked with PDA
// calculation for setting authorization since stored
// in the Pool Definition.
let mut running_vault_a = vault_a . clone ( ) ;
let mut running_vault_b = vault_b . clone ( ) ;
running_vault_a . is_authorized = true ;
running_vault_b . is_authorized = true ;
2025-12-06 14:52:18 -05:00
if amount_min_a = = 0 | | amount_min_b = = 0 {
panic! ( " Minimum withdraw amount must be nonzero " ) ;
}
if amount_lp = = 0 {
panic! ( " Liquidity amount must be nonzero " ) ;
}
2025-12-04 21:53:58 -05:00
// 2. Compute withdrawal amounts
let user_holding_lp_data = TokenHolding ::parse ( & user_holding_lp . account . data ) . expect ( " Remove liquidity: AMM Program expects a valid Token Account for liquidity token " ) ;
if user_holding_lp_data . balance > pool_def_data . liquidity_pool_supply | | user_holding_lp_data . definition_id ! = pool_def_data . liquidity_pool_id {
panic! ( " Invalid liquidity account provided " ) ;
}
2025-12-06 14:52:18 -05:00
let withdraw_amount_a = ( pool_def_data . reserve_a * amount_lp ) / pool_def_data . liquidity_pool_supply ;
let withdraw_amount_b = ( pool_def_data . reserve_b * amount_lp ) / pool_def_data . liquidity_pool_supply ;
2025-11-14 20:59:42 -05:00
2025-12-04 21:53:58 -05:00
// 3. Validate and slippage check
if withdraw_amount_a < amount_min_a {
panic! ( " Insufficient minimal withdraw amount (Token A) provided for liquidity amount " ) ;
}
if withdraw_amount_b < amount_min_b {
panic! ( " Insufficient minimal withdraw amount (Token B) provided for liquidity amount " ) ;
}
2025-11-14 20:59:42 -05:00
// 4. Calculate LP to reduce cap by
2025-12-04 21:53:58 -05:00
let delta_lp : u128 = ( pool_def_data . liquidity_pool_supply * amount_lp ) / pool_def_data . liquidity_pool_supply ;
2025-11-14 20:59:42 -05:00
2025-12-06 14:52:18 -05:00
let active : bool = if pool_def_data . liquidity_pool_supply - delta_lp = = 0 { false } else { true } ;
2025-11-14 20:59:42 -05:00
// 5. Update pool account
let mut pool_post = pool . account . clone ( ) ;
let pool_post_definition = PoolDefinition {
definition_token_a_id : pool_def_data . definition_token_a_id . clone ( ) ,
definition_token_b_id : pool_def_data . definition_token_b_id . clone ( ) ,
2025-12-08 22:05:51 -05:00
vault_a_id : pool_def_data . vault_a_id . clone ( ) ,
vault_b_id : pool_def_data . vault_b_id . clone ( ) ,
2025-11-14 20:59:42 -05:00
liquidity_pool_id : pool_def_data . liquidity_pool_id . clone ( ) ,
2025-12-04 21:53:58 -05:00
liquidity_pool_supply : pool_def_data . liquidity_pool_supply - delta_lp ,
2025-11-14 20:59:42 -05:00
reserve_a : pool_def_data . reserve_a - withdraw_amount_a ,
reserve_b : pool_def_data . reserve_b - withdraw_amount_b ,
2025-12-06 14:52:18 -05:00
fees : 0 u128 ,
active ,
2025-11-14 20:59:42 -05:00
} ;
pool_post . data = pool_post_definition . into_data ( ) ;
2025-12-07 20:34:26 -05:00
let mut chained_calls = Vec ::new ( ) ;
2025-11-14 20:59:42 -05:00
2025-11-26 21:44:57 -05:00
//Chaincall for Token A withdraw
2025-12-06 14:52:18 -05:00
let mut instruction : [ u8 ; 23 ] = [ 0 ; 23 ] ;
2025-12-08 13:19:30 -05:00
instruction [ 0 ] = 1 ; // token transfer
2025-11-25 23:06:47 -05:00
instruction [ 1 .. 17 ] . copy_from_slice ( & withdraw_amount_a . to_le_bytes ( ) ) ;
2025-12-04 21:53:58 -05:00
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction ) . expect ( " Remove liquidity: AMM Program expects valid token transfer instruction data " ) ;
2025-11-14 20:59:42 -05:00
let call_token_a = ChainedCall {
2025-12-04 21:53:58 -05:00
program_id : vault_a . account . program_owner ,
2025-12-09 14:42:58 -05:00
instruction_data ,
2025-12-08 13:19:30 -05:00
pre_states : vec ! [ running_vault_a , user_holding_a . clone ( ) ] ,
2025-12-08 22:05:51 -05:00
pda_seeds : vec ! [ compute_vault_pda_seed ( pool . account_id . clone ( ) , pool_def_data . definition_token_a_id . clone ( ) ) ] ,
2025-11-14 20:59:42 -05:00
} ;
2025-11-26 21:44:57 -05:00
//Chaincall for Token B withdraw
2025-12-06 14:52:18 -05:00
let mut instruction : [ u8 ; 23 ] = [ 0 ; 23 ] ;
2025-12-08 13:19:30 -05:00
instruction [ 0 ] = 1 ; // token transfer
2025-11-25 23:06:47 -05:00
instruction [ 1 .. 17 ] . copy_from_slice ( & withdraw_amount_b . to_le_bytes ( ) ) ;
2025-12-04 21:53:58 -05:00
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction ) . expect ( " Remove liquidity: AMM Program expects valid token transfer instruction data " ) ;
2025-11-14 20:59:42 -05:00
let call_token_b = ChainedCall {
2025-12-04 21:53:58 -05:00
program_id : vault_b . account . program_owner ,
2025-12-09 14:42:58 -05:00
instruction_data ,
2025-12-08 13:19:30 -05:00
pre_states : vec ! [ running_vault_b , user_holding_b . clone ( ) ] ,
2025-12-08 22:05:51 -05:00
pda_seeds : vec ! [ compute_vault_pda_seed ( pool . account_id . clone ( ) , pool_def_data . definition_token_b_id . clone ( ) ) ] ,
2025-11-14 20:59:42 -05:00
} ;
2025-12-08 22:05:51 -05:00
//Chaincall for LP adjustment
let mut pool_definition_lp_auth = pool_definition_lp . clone ( ) ;
pool_definition_lp_auth . is_authorized = true ;
2025-12-06 14:52:18 -05:00
let mut instruction : [ u8 ; 23 ] = [ 0 ; 23 ] ;
2025-12-08 13:19:30 -05:00
instruction [ 0 ] = 3 ; // token burn
2025-11-25 23:06:47 -05:00
instruction [ 1 .. 17 ] . copy_from_slice ( & delta_lp . to_le_bytes ( ) ) ;
2025-12-04 21:53:58 -05:00
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction ) . expect ( " Remove liquidity: AMM Program expects valid token transfer instruction data " ) ;
2025-11-14 20:59:42 -05:00
let call_token_lp = ChainedCall {
2025-12-06 14:52:18 -05:00
program_id : pool_definition_lp . account . program_owner ,
2025-12-09 14:42:58 -05:00
instruction_data ,
2025-12-08 22:05:51 -05:00
pre_states : vec ! [ pool_definition_lp_auth . clone ( ) , user_holding_lp . clone ( ) ] ,
pda_seeds : vec ! [ compute_liquidity_token_pda_seed ( pool . account_id . clone ( ) ) ]
2025-11-14 20:59:42 -05:00
} ;
2025-12-07 20:34:26 -05:00
chained_calls . push ( call_token_lp ) ;
chained_calls . push ( call_token_b ) ;
chained_calls . push ( call_token_a ) ;
2025-12-06 14:52:18 -05:00
2025-11-25 09:02:43 -05:00
let post_states = vec !
2025-12-06 14:52:18 -05:00
[
2025-12-07 20:34:26 -05:00
AccountPostState ::new ( pool_post . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 1 ] . account . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 2 ] . account . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 3 ] . account . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 4 ] . account . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 5 ] . account . clone ( ) ) ,
AccountPostState ::new ( pre_states [ 6 ] . account . clone ( ) ) ] ;
( post_states , chained_calls )
2025-11-17 18:48:17 -05:00
}
2025-11-18 14:43:40 -05:00
#[ cfg(test) ]
mod tests {
2025-12-07 20:34:26 -05:00
use nssa_core ::{ { account ::{ Account , AccountId , AccountWithMetadata } , program ::ChainedCall , program ::PdaSeed } , program ::ProgramId } ;
2025-11-18 14:43:40 -05:00
2025-12-08 22:05:51 -05:00
use crate ::{ PoolDefinition , TokenDefinition , TokenHolding , add_liquidity , new_definition , remove_liquidity , swap ,
compute_liquidity_token_pda , compute_liquidity_token_pda_seed , compute_pool_pda , compute_pool_pda_seed ,
compute_vault_pda , compute_vault_pda_seed } ;
2025-12-04 21:53:58 -05:00
const TOKEN_PROGRAM_ID : ProgramId = [ 15 ; 8 ] ;
2025-12-08 22:05:51 -05:00
const AMM_PROGRAM_ID : ProgramId = [ 42 ; 8 ] ;
2025-12-04 21:53:58 -05:00
enum AccountEnum {
2025-12-07 20:34:26 -05:00
UserHoldingB ,
UserHoldingA ,
VaultAUninit ,
VaultBUninit ,
VaultAInit ,
VaultBInit ,
VaultAInitHigh ,
VaultBInitHigh ,
VaultAInitLow ,
VaultBInitLow ,
VaultAInitZero ,
VaultBInitZero ,
VaultAWrongAccId ,
VaultBWrongAccId ,
PoolLPUninit ,
PoolLPInit ,
PoolLPWrongAccId ,
UserHoldingLPUninit ,
UserHoldingLPInit ,
PoolDefinitionUninit ,
PoolDefinitionInit ,
PoolDefinitionInitReserveAZero ,
PoolDefinitionInitReserveBZero ,
PoolDefinitionInitReserveALow ,
PoolDefinitionInitReserveBLow ,
PoolDefinitionUnauth ,
PoolDefinitionSwapTest1 ,
PoolDefinitionSwapTest2 ,
PoolDefinitionAddZeroLP ,
PoolDefinitionAddSuccessful ,
PoolDefinitionRemoveSuccessful ,
2025-12-08 22:05:51 -05:00
PoolDefinitionInactive ,
PoolDefinitionWrongId ,
VaultAWrongId ,
VaultBWrongId ,
PoolLPWrongId ,
PoolDefinitionActive ,
2025-12-04 21:53:58 -05:00
}
enum BalanceEnum {
2025-12-07 20:34:26 -05:00
VaultAReserveInit ,
VaultBReserveInit ,
VaultAReserveLow ,
VaultBReserveLow ,
VaultAReserveHigh ,
VaultBReserveHigh ,
UserTokenABal ,
UserTokenBBal ,
UserTokenLPBal ,
RemoveMinAmountA ,
RemoveMinAmountB ,
RemoveActualASuccessful ,
RemoveMinAmountBLow ,
RemoveMinAmountBAow ,
RemoveAmountLP ,
RemoveAmountLP1 ,
AddMaxAmountALow ,
AddMaxAmountBLow ,
AddMaxAmountBHigh ,
AddMaxAmountA ,
AddMaxAmountb ,
AddMinAmountLP ,
VaultASwapTest1 ,
VaultASwapTest2 ,
VaultBSwapTest1 ,
VaultBSwapTest2 ,
MinAmountOut ,
VaultAAddSuccessful ,
VaultBAddSuccessful ,
AddSuccessfulAmountA ,
AddSuccessfulAmountB ,
VaultARemoveSuccessful ,
VaultBRemoveSuccessful ,
2025-12-04 21:53:58 -05:00
}
fn helper_balance_constructor ( selection : BalanceEnum ) -> u128 {
match selection {
2025-12-07 20:34:26 -05:00
BalanceEnum ::VaultAReserveInit = > 1_000 ,
BalanceEnum ::VaultBReserveInit = > 500 ,
BalanceEnum ::VaultAReserveLow = > 10 ,
BalanceEnum ::VaultBReserveLow = > 10 ,
BalanceEnum ::VaultAReserveHigh = > 500_000 ,
BalanceEnum ::VaultBReserveHigh = > 500_000 ,
BalanceEnum ::UserTokenABal = > 1_000 ,
BalanceEnum ::UserTokenBBal = > 500 ,
BalanceEnum ::UserTokenLPBal = > 100 ,
BalanceEnum ::RemoveMinAmountA = > 50 ,
BalanceEnum ::RemoveMinAmountB = > 100 ,
BalanceEnum ::RemoveActualASuccessful = > 100 ,
BalanceEnum ::RemoveMinAmountBLow = > 50 ,
BalanceEnum ::RemoveMinAmountBAow = > 10 ,
BalanceEnum ::RemoveAmountLP = > 100 ,
BalanceEnum ::RemoveAmountLP1 = > 30 ,
BalanceEnum ::AddMaxAmountA = > 500 ,
BalanceEnum ::AddMaxAmountb = > 200 ,
BalanceEnum ::AddMaxAmountBHigh = > 20_000 ,
BalanceEnum ::AddMaxAmountALow = > 10 ,
BalanceEnum ::AddMaxAmountBLow = > 10 ,
BalanceEnum ::AddMinAmountLP = > 20 ,
BalanceEnum ::VaultASwapTest1 = > 1_500 ,
BalanceEnum ::VaultASwapTest2 = > 715 ,
BalanceEnum ::VaultBSwapTest1 = > 334 ,
BalanceEnum ::VaultBSwapTest2 = > 700 ,
BalanceEnum ::MinAmountOut = > 200 ,
BalanceEnum ::VaultAAddSuccessful = > 1_400 ,
BalanceEnum ::VaultBAddSuccessful = > 700 ,
BalanceEnum ::AddSuccessfulAmountA = > 400 ,
BalanceEnum ::AddSuccessfulAmountB = > 200 ,
BalanceEnum ::VaultARemoveSuccessful = > 900 ,
BalanceEnum ::VaultBRemoveSuccessful = > 450 ,
2025-12-04 21:53:58 -05:00
_ = > panic! ( " Invalid selection " )
}
}
enum IdEnum {
2025-12-07 20:34:26 -05:00
TokenADefinitionId ,
TokenBDefinitionId ,
TokenLPDefinitionId ,
UserTokenAId ,
UserTokenBId ,
UserTokenLPId ,
PoolDefinitionId ,
VaultAId ,
VaultBId ,
2025-12-04 21:53:58 -05:00
}
2025-12-06 14:52:18 -05:00
enum ChainedCallsEnum {
2025-12-07 20:34:26 -05:00
CcTokenAInitialization ,
CcTokenBInitialization ,
CcPoolLPInitiailization ,
CcSwapTokenATest1 ,
CcSwapTokenBTest1 ,
CcSwapTokenATest2 ,
CcSwapTokenBTest2 ,
CcAddTokenA ,
CcAddTokenB ,
CcAddPoolLP ,
CcRemoveTokenA ,
CcRemoveTokenB ,
CcRemovePoolLP ,
2025-12-08 22:05:51 -05:00
CcNewDefinitionTokenA ,
CcNewDefinitionTokenB ,
CcNewDefinitionLP ,
2025-12-06 14:52:18 -05:00
}
fn helper_chained_call_constructor ( selection : ChainedCallsEnum ) -> ChainedCall {
match selection {
2025-12-07 20:34:26 -05:00
ChainedCallsEnum ::CcTokenAInitialization = > {
2025-12-06 14:52:18 -05:00
let mut instruction : [ u8 ; 23 ] = [ 0 ; 23 ] ;
instruction [ 0 ] = 1 ;
instruction [ 1 .. 17 ] . copy_from_slice (
2025-12-07 20:34:26 -05:00
& helper_balance_constructor ( BalanceEnum ::UserTokenABal )
2025-12-06 14:52:18 -05:00
. to_le_bytes ( ) ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction ) . expect ( " AMM Program expects valid transaction instruction data " ) ;
ChainedCall {
program_id : TOKEN_PROGRAM_ID ,
instruction_data ,
pre_states : vec ! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::VaultAUninit ) ] ,
pda_seeds : Vec ::< PdaSeed > ::new ( ) ,
2025-12-06 14:52:18 -05:00
}
}
2025-12-07 20:34:26 -05:00
ChainedCallsEnum ::CcTokenBInitialization = > {
2025-12-06 14:52:18 -05:00
let mut instruction : [ u8 ; 23 ] = [ 0 ; 23 ] ;
instruction [ 0 ] = 1 ;
instruction [ 1 .. 17 ] . copy_from_slice (
2025-12-07 20:34:26 -05:00
& helper_balance_constructor ( BalanceEnum ::UserTokenBBal )
2025-12-06 14:52:18 -05:00
. to_le_bytes ( ) ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction ) . expect ( " AMM Program expects valid transaction instruction data " ) ;
ChainedCall {
program_id : TOKEN_PROGRAM_ID ,
instruction_data ,
pre_states : vec ! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::VaultBUninit ) ] ,
pda_seeds : Vec ::< PdaSeed > ::new ( ) ,
2025-12-06 14:52:18 -05:00
}
}
2025-12-07 20:34:26 -05:00
ChainedCallsEnum ::CcPoolLPInitiailization = > {
2025-12-06 14:52:18 -05:00
let mut instruction : [ u8 ; 23 ] = [ 0 ; 23 ] ;
instruction [ 0 ] = 1 ;
instruction [ 1 .. 17 ] . copy_from_slice (
2025-12-07 20:34:26 -05:00
& helper_balance_constructor ( BalanceEnum ::UserTokenABal )
2025-12-06 14:52:18 -05:00
. to_le_bytes ( ) ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction ) . expect ( " AMM Program expects valid transaction instruction data " ) ;
ChainedCall {
program_id : TOKEN_PROGRAM_ID ,
instruction_data ,
pre_states : vec ! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolLPUninit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPUninit ) ] ,
pda_seeds : Vec ::< PdaSeed > ::new ( ) ,
2025-12-06 14:52:18 -05:00
}
}
2025-12-07 20:34:26 -05:00
ChainedCallsEnum ::CcSwapTokenATest1 = > {
2025-12-06 14:52:18 -05:00
let mut instruction_data : [ u8 ; 23 ] = [ 0 ; 23 ] ;
instruction_data [ 0 ] = 1 ;
instruction_data [ 1 .. 17 ] . copy_from_slice (
2025-12-07 20:34:26 -05:00
& helper_balance_constructor ( BalanceEnum ::AddMaxAmountA )
2025-12-06 14:52:18 -05:00
. to_le_bytes ( ) ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction_data ) . expect ( " AMM Program expects valid transaction instruction data " ) ;
ChainedCall {
program_id : TOKEN_PROGRAM_ID ,
instruction_data ,
pre_states : vec ! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ] ,
pda_seeds : Vec ::< PdaSeed > ::new ( ) ,
2025-12-06 14:52:18 -05:00
}
}
2025-12-07 20:34:26 -05:00
ChainedCallsEnum ::CcSwapTokenBTest1 = > {
2025-12-06 14:52:18 -05:00
let swap_amount : u128 = 166 ;
2025-12-08 22:05:51 -05:00
let mut vault_b_auth = helper_account_constructor ( AccountEnum ::VaultBInit ) ;
vault_b_auth . is_authorized = true ;
2025-12-06 14:52:18 -05:00
let mut instruction : [ u8 ; 23 ] = [ 0 ; 23 ] ;
instruction [ 0 ] = 1 ;
instruction [ 1 .. 17 ] . copy_from_slice (
& swap_amount
. to_le_bytes ( ) ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction ) . expect ( " AMM Program expects valid transaction instruction data " ) ;
ChainedCall {
program_id : TOKEN_PROGRAM_ID ,
instruction_data ,
pre_states : vec ! [
2025-12-08 22:05:51 -05:00
vault_b_auth ,
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::UserHoldingB ) ] ,
2025-12-08 22:05:51 -05:00
pda_seeds : vec ! [
compute_vault_pda_seed ( helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ) ,
] ,
2025-12-06 14:52:18 -05:00
}
}
2025-12-07 20:34:26 -05:00
ChainedCallsEnum ::CcSwapTokenATest2 = > {
2025-12-06 14:52:18 -05:00
let swap_amount : u128 = 285 ;
2025-12-08 22:05:51 -05:00
let mut vault_a_auth = helper_account_constructor ( AccountEnum ::VaultAInit ) ;
vault_a_auth . is_authorized = true ;
2025-12-06 14:52:18 -05:00
let mut instruction_data : [ u8 ; 23 ] = [ 0 ; 23 ] ;
instruction_data [ 0 ] = 1 ;
instruction_data [ 1 .. 17 ] . copy_from_slice (
& swap_amount
. to_le_bytes ( ) ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction_data ) . expect ( " AMM Program expects valid transaction instruction data " ) ;
ChainedCall {
program_id : TOKEN_PROGRAM_ID ,
instruction_data ,
pre_states : vec ! [
2025-12-08 22:05:51 -05:00
vault_a_auth ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
] ,
pda_seeds : vec ! [
compute_vault_pda_seed ( helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
helper_id_constructor ( IdEnum ::TokenADefinitionId ) ) ,
] ,
2025-12-06 14:52:18 -05:00
}
}
2025-12-07 20:34:26 -05:00
ChainedCallsEnum ::CcSwapTokenBTest2 = > {
2025-12-06 14:52:18 -05:00
let mut instruction : [ u8 ; 23 ] = [ 0 ; 23 ] ;
instruction [ 0 ] = 1 ;
instruction [ 1 .. 17 ] . copy_from_slice (
2025-12-07 20:34:26 -05:00
& helper_balance_constructor ( BalanceEnum ::AddMaxAmountb )
2025-12-06 14:52:18 -05:00
. to_le_bytes ( ) ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction ) . expect ( " AMM Program expects valid transaction instruction data " ) ;
ChainedCall {
program_id : TOKEN_PROGRAM_ID ,
instruction_data ,
pre_states : vec ! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ] ,
pda_seeds : Vec ::< PdaSeed > ::new ( ) ,
2025-12-06 14:52:18 -05:00
}
}
2025-12-07 20:34:26 -05:00
ChainedCallsEnum ::CcAddTokenA = > {
2025-12-06 14:52:18 -05:00
let mut instruction : [ u8 ; 23 ] = [ 0 ; 23 ] ;
instruction [ 0 ] = 1 ;
instruction [ 1 .. 17 ] . copy_from_slice (
2025-12-07 20:34:26 -05:00
& helper_balance_constructor ( BalanceEnum ::AddSuccessfulAmountA )
2025-12-06 14:52:18 -05:00
. to_le_bytes ( ) ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction ) . expect ( " AMM Program expects valid transaction instruction data " ) ;
ChainedCall {
program_id : TOKEN_PROGRAM_ID ,
instruction_data ,
pre_states : vec ! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ] ,
pda_seeds : Vec ::< PdaSeed > ::new ( ) ,
2025-12-06 14:52:18 -05:00
}
}
2025-12-07 20:34:26 -05:00
ChainedCallsEnum ::CcAddTokenB = > {
2025-12-06 14:52:18 -05:00
let mut instruction : [ u8 ; 23 ] = [ 0 ; 23 ] ;
instruction [ 0 ] = 1 ;
instruction [ 1 .. 17 ] . copy_from_slice (
2025-12-07 20:34:26 -05:00
& helper_balance_constructor ( BalanceEnum ::AddSuccessfulAmountB )
2025-12-06 14:52:18 -05:00
. to_le_bytes ( ) ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction ) . expect ( " Swap Logic: AMM Program expects valid transaction instruction data " ) ;
ChainedCall {
program_id : TOKEN_PROGRAM_ID ,
instruction_data ,
pre_states : vec ! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ] ,
pda_seeds : Vec ::< PdaSeed > ::new ( ) ,
2025-12-06 14:52:18 -05:00
}
}
2025-12-07 20:34:26 -05:00
ChainedCallsEnum ::CcAddPoolLP = > {
2025-12-08 22:05:51 -05:00
let mut pool_lp_auth = helper_account_constructor ( AccountEnum ::PoolLPInit ) ;
pool_lp_auth . is_authorized = true ;
2025-12-06 14:52:18 -05:00
let mut instruction : [ u8 ; 23 ] = [ 0 ; 23 ] ;
instruction [ 0 ] = 4 ;
instruction [ 1 .. 17 ] . copy_from_slice (
2025-12-07 20:34:26 -05:00
& helper_balance_constructor ( BalanceEnum ::AddSuccessfulAmountA )
2025-12-06 14:52:18 -05:00
. to_le_bytes ( ) ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction ) . expect ( " Swap Logic: AMM Program expects valid transaction instruction data " ) ;
ChainedCall {
program_id : TOKEN_PROGRAM_ID ,
instruction_data ,
pre_states : vec ! [
2025-12-08 22:05:51 -05:00
pool_lp_auth ,
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ] ,
2025-12-08 22:05:51 -05:00
pda_seeds : vec ! [ compute_liquidity_token_pda_seed (
helper_id_constructor ( IdEnum ::PoolDefinitionId ) ) ] ,
2025-12-06 14:52:18 -05:00
}
}
2025-12-07 20:34:26 -05:00
ChainedCallsEnum ::CcRemoveTokenA = > {
2025-12-08 22:05:51 -05:00
let mut vault_a_auth = helper_account_constructor ( AccountEnum ::VaultAInit ) ;
vault_a_auth . is_authorized = true ;
2025-12-06 14:52:18 -05:00
let mut instruction : [ u8 ; 23 ] = [ 0 ; 23 ] ;
instruction [ 0 ] = 1 ;
instruction [ 1 .. 17 ] . copy_from_slice (
2025-12-07 20:34:26 -05:00
& helper_balance_constructor ( BalanceEnum ::RemoveActualASuccessful )
2025-12-06 14:52:18 -05:00
. to_le_bytes ( ) ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction ) . expect ( " AMM Program expects valid transaction instruction data " ) ;
ChainedCall {
program_id : TOKEN_PROGRAM_ID ,
instruction_data ,
pre_states : vec ! [
2025-12-08 22:05:51 -05:00
vault_a_auth ,
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::UserHoldingA ) , ] ,
2025-12-08 22:05:51 -05:00
pda_seeds : vec ! [
compute_vault_pda_seed ( helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
helper_id_constructor ( IdEnum ::TokenADefinitionId ) ) ,
] ,
2025-12-06 14:52:18 -05:00
}
}
2025-12-07 20:34:26 -05:00
ChainedCallsEnum ::CcRemoveTokenB = > {
2025-12-08 22:05:51 -05:00
let mut vault_b_auth = helper_account_constructor ( AccountEnum ::VaultBInit ) ;
vault_b_auth . is_authorized = true ;
2025-12-06 14:52:18 -05:00
let mut instruction : [ u8 ; 23 ] = [ 0 ; 23 ] ;
instruction [ 0 ] = 1 ;
instruction [ 1 .. 17 ] . copy_from_slice (
2025-12-07 20:34:26 -05:00
& helper_balance_constructor ( BalanceEnum ::RemoveMinAmountBLow )
2025-12-06 14:52:18 -05:00
. to_le_bytes ( ) ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction ) . expect ( " AMM Program expects valid transaction instruction data " ) ;
ChainedCall {
program_id : TOKEN_PROGRAM_ID ,
instruction_data ,
pre_states : vec ! [
2025-12-08 22:05:51 -05:00
vault_b_auth ,
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::UserHoldingB ) , ] ,
2025-12-08 22:05:51 -05:00
pda_seeds : vec ! [
compute_vault_pda_seed ( helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ) ,
] ,
2025-12-06 14:52:18 -05:00
}
}
2025-12-07 20:34:26 -05:00
ChainedCallsEnum ::CcRemovePoolLP = > {
2025-12-08 22:05:51 -05:00
let mut pool_lp_auth = helper_account_constructor ( AccountEnum ::PoolLPInit ) ;
pool_lp_auth . is_authorized = true ;
2025-12-06 14:52:18 -05:00
let mut instruction : [ u8 ; 23 ] = [ 0 ; 23 ] ;
instruction [ 0 ] = 3 ;
instruction [ 1 .. 17 ] . copy_from_slice (
2025-12-07 20:34:26 -05:00
& helper_balance_constructor ( BalanceEnum ::RemoveActualASuccessful )
2025-12-06 14:52:18 -05:00
. to_le_bytes ( ) ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction ) . expect ( " AMM Program expects valid transaction instruction data " ) ;
ChainedCall {
program_id : TOKEN_PROGRAM_ID ,
instruction_data ,
pre_states : vec ! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) , ] ,
2025-12-08 22:05:51 -05:00
pda_seeds : vec ! [ compute_liquidity_token_pda_seed (
helper_id_constructor ( IdEnum ::PoolDefinitionId ) ) ] ,
}
}
ChainedCallsEnum ::CcNewDefinitionTokenA = > {
let mut instruction : [ u8 ; 23 ] = [ 0 ; 23 ] ;
instruction [ 0 ] = 1 ;
instruction [ 1 .. 17 ] . copy_from_slice (
& helper_balance_constructor ( BalanceEnum ::AddSuccessfulAmountA )
. to_le_bytes ( ) ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction ) . expect ( " AMM Program expects valid transaction instruction data " ) ;
ChainedCall {
program_id : TOKEN_PROGRAM_ID ,
instruction_data ,
pre_states : vec ! [
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ] ,
pda_seeds : Vec ::< PdaSeed > ::new ( ) ,
}
}
ChainedCallsEnum ::CcNewDefinitionTokenB = > {
let mut instruction : [ u8 ; 23 ] = [ 0 ; 23 ] ;
instruction [ 0 ] = 1 ;
instruction [ 1 .. 17 ] . copy_from_slice (
& helper_balance_constructor ( BalanceEnum ::AddSuccessfulAmountB )
. to_le_bytes ( ) ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction ) . expect ( " Swap Logic: AMM Program expects valid transaction instruction data " ) ;
ChainedCall {
program_id : TOKEN_PROGRAM_ID ,
instruction_data ,
pre_states : vec ! [
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ] ,
2025-12-07 20:34:26 -05:00
pda_seeds : Vec ::< PdaSeed > ::new ( ) ,
2025-12-06 14:52:18 -05:00
}
}
2025-12-08 22:05:51 -05:00
ChainedCallsEnum ::CcAddPoolLP = > {
let mut pool_lp_auth = helper_account_constructor ( AccountEnum ::PoolLPInit ) ;
pool_lp_auth . is_authorized = true ;
let mut instruction : [ u8 ; 23 ] = [ 0 ; 23 ] ;
instruction [ 0 ] = 0 ;
instruction [ 1 .. 17 ] . copy_from_slice (
& helper_balance_constructor ( BalanceEnum ::AddSuccessfulAmountA )
. to_le_bytes ( ) ) ;
let instruction_data = risc0_zkvm ::serde ::to_vec ( & instruction ) . expect ( " Swap Logic: AMM Program expects valid transaction instruction data " ) ;
ChainedCall {
program_id : TOKEN_PROGRAM_ID ,
instruction_data ,
pre_states : vec ! [
pool_lp_auth ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ] ,
pda_seeds : vec ! [ compute_liquidity_token_pda_seed (
helper_id_constructor ( IdEnum ::PoolDefinitionId ) ) ] ,
}
}
_ = > panic! ( " Invalid selection " )
2025-12-06 14:52:18 -05:00
}
}
2025-12-04 21:53:58 -05:00
fn helper_id_constructor ( selection : IdEnum ) -> AccountId {
match selection {
2025-12-07 20:34:26 -05:00
IdEnum ::TokenADefinitionId = > AccountId ::new ( [ 42 ; 32 ] ) ,
IdEnum ::TokenBDefinitionId = > AccountId ::new ( [ 43 ; 32 ] ) ,
2025-12-08 22:05:51 -05:00
IdEnum ::TokenLPDefinitionId = > compute_liquidity_token_pda ( AMM_PROGRAM_ID ,
helper_id_constructor ( IdEnum ::PoolDefinitionId ) , ) ,
2025-12-07 20:34:26 -05:00
IdEnum ::UserTokenAId = > AccountId ::new ( [ 45 ; 32 ] ) ,
IdEnum ::UserTokenBId = > AccountId ::new ( [ 46 ; 32 ] ) ,
IdEnum ::UserTokenLPId = > AccountId ::new ( [ 47 ; 32 ] ) ,
2025-12-08 22:05:51 -05:00
IdEnum ::PoolDefinitionId = > compute_pool_pda ( AMM_PROGRAM_ID ,
helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ) ,
IdEnum ::VaultAId = > compute_vault_pda ( AMM_PROGRAM_ID ,
helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
helper_id_constructor ( IdEnum ::TokenADefinitionId ) ) ,
IdEnum ::VaultBId = > compute_vault_pda ( AMM_PROGRAM_ID ,
helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ) ,
2025-12-04 21:53:58 -05:00
_ = > panic! ( " Invalid selection " )
}
}
fn helper_account_constructor ( selection : AccountEnum ) -> AccountWithMetadata {
match selection {
2025-12-07 20:34:26 -05:00
AccountEnum ::UserHoldingA = > AccountWithMetadata {
2025-12-04 21:53:58 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenHolding ::into_data (
TokenHolding {
account_type : 1 u8 ,
2025-12-07 20:34:26 -05:00
definition_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
balance : helper_balance_constructor ( BalanceEnum ::UserTokenABal ) ,
2025-12-04 21:53:58 -05:00
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::UserTokenAId ) ,
2025-12-04 21:53:58 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::UserHoldingB = > AccountWithMetadata {
2025-12-04 21:53:58 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenHolding ::into_data (
TokenHolding {
account_type : 1 u8 ,
2025-12-07 20:34:26 -05:00
definition_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
balance : helper_balance_constructor ( BalanceEnum ::UserTokenBBal ) ,
2025-12-04 21:53:58 -05:00
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::UserTokenBId ) ,
2025-12-04 21:53:58 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::VaultAUninit = > AccountWithMetadata {
2025-12-04 21:53:58 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenHolding ::into_data (
TokenHolding {
account_type : 1 u8 ,
2025-12-07 20:34:26 -05:00
definition_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
2025-12-04 21:53:58 -05:00
balance : 0 ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
2025-12-04 21:53:58 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::VaultBUninit = > AccountWithMetadata {
2025-12-04 21:53:58 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenHolding ::into_data (
TokenHolding {
account_type : 1 u8 ,
2025-12-07 20:34:26 -05:00
definition_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
2025-12-04 21:53:58 -05:00
balance : 0 ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
2025-12-04 21:53:58 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::VaultAInit = > AccountWithMetadata {
2025-12-04 21:53:58 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenHolding ::into_data (
TokenHolding {
account_type : 1 u8 ,
2025-12-07 20:34:26 -05:00
definition_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
balance : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
2025-12-04 21:53:58 -05:00
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
2025-12-04 21:53:58 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::VaultBInit = > AccountWithMetadata {
2025-12-04 21:53:58 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenHolding ::into_data (
TokenHolding {
account_type : 1 u8 ,
2025-12-07 20:34:26 -05:00
definition_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
balance : helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) ,
2025-12-04 21:53:58 -05:00
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
2025-12-04 21:53:58 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::VaultAInitHigh = > AccountWithMetadata {
2025-12-04 21:53:58 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenHolding ::into_data (
TokenHolding {
account_type : 1 u8 ,
2025-12-07 20:34:26 -05:00
definition_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
balance : helper_balance_constructor ( BalanceEnum ::VaultAReserveHigh ) ,
2025-12-06 14:52:18 -05:00
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
2025-12-06 14:52:18 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::VaultBInitHigh = > AccountWithMetadata {
2025-12-06 14:52:18 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenHolding ::into_data (
TokenHolding {
account_type : 1 u8 ,
2025-12-07 20:34:26 -05:00
definition_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
balance : helper_balance_constructor ( BalanceEnum ::VaultBReserveHigh ) ,
2025-12-04 21:53:58 -05:00
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
2025-12-04 21:53:58 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::VaultAInitLow = > AccountWithMetadata {
2025-12-06 14:52:18 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenHolding ::into_data (
TokenHolding {
account_type : 1 u8 ,
2025-12-07 20:34:26 -05:00
definition_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
balance : helper_balance_constructor ( BalanceEnum ::VaultAReserveLow ) ,
2025-12-06 14:52:18 -05:00
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
2025-12-06 14:52:18 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::VaultBInitLow = > AccountWithMetadata {
2025-12-04 21:53:58 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenHolding ::into_data (
TokenHolding {
account_type : 1 u8 ,
2025-12-07 20:34:26 -05:00
definition_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
balance : helper_balance_constructor ( BalanceEnum ::VaultBReserveLow ) ,
2025-12-06 14:52:18 -05:00
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
2025-12-06 14:52:18 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::VaultAInitZero = > AccountWithMetadata {
2025-12-06 14:52:18 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenHolding ::into_data (
TokenHolding {
account_type : 1 u8 ,
2025-12-07 20:34:26 -05:00
definition_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
2025-12-06 14:52:18 -05:00
balance : 0 ,
2025-12-04 21:53:58 -05:00
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
2025-12-04 21:53:58 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::VaultBInitZero = > AccountWithMetadata {
2025-12-04 21:53:58 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenHolding ::into_data (
TokenHolding {
account_type : 1 u8 ,
2025-12-07 20:34:26 -05:00
definition_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
2025-12-04 21:53:58 -05:00
balance : 0 ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
2025-12-04 21:53:58 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::VaultAWrongAccId = > AccountWithMetadata {
2025-12-04 21:53:58 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenHolding ::into_data (
TokenHolding {
account_type : 1 u8 ,
2025-12-07 20:34:26 -05:00
definition_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
balance : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
2025-12-04 21:53:58 -05:00
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
2025-12-04 21:53:58 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::VaultBWrongAccId = > AccountWithMetadata {
2025-12-04 21:53:58 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenHolding ::into_data (
TokenHolding {
account_type : 1 u8 ,
2025-12-07 20:34:26 -05:00
definition_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
balance : helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) ,
2025-12-06 14:52:18 -05:00
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
2025-12-06 14:52:18 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::PoolLPUninit = > AccountWithMetadata {
2025-12-06 14:52:18 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenDefinition ::into_data (
TokenDefinition {
account_type : 0 u8 ,
name : [ 1 ; 6 ] ,
total_supply : 0 u128 ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
2025-12-06 14:52:18 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::PoolLPInit = > AccountWithMetadata {
2025-12-06 14:52:18 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenDefinition ::into_data (
TokenDefinition {
account_type : 0 u8 ,
name : [ 1 ; 6 ] ,
2025-12-07 20:34:26 -05:00
total_supply : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
2025-12-06 14:52:18 -05:00
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
2025-12-06 14:52:18 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::PoolLPWrongAccId = > AccountWithMetadata {
2025-12-06 14:52:18 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenDefinition ::into_data (
TokenDefinition {
account_type : 0 u8 ,
name : [ 1 ; 6 ] ,
2025-12-07 20:34:26 -05:00
total_supply : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
2025-12-04 21:53:58 -05:00
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
2025-12-04 21:53:58 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::UserHoldingLPUninit = > AccountWithMetadata {
2025-12-04 21:53:58 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenHolding ::into_data (
TokenHolding {
account_type : 1 u8 ,
2025-12-07 20:34:26 -05:00
definition_id : helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
2025-12-04 21:53:58 -05:00
balance : 0 ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::UserTokenLPId ) ,
2025-12-04 21:53:58 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::UserHoldingLPInit = > AccountWithMetadata {
2025-12-04 21:53:58 -05:00
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenHolding ::into_data (
TokenHolding {
account_type : 1 u8 ,
2025-12-07 20:34:26 -05:00
definition_id : helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
balance : helper_balance_constructor ( BalanceEnum ::UserTokenLPBal ) ,
2025-12-04 21:53:58 -05:00
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::UserTokenLPId ) ,
2025-12-04 21:53:58 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::PoolDefinitionUninit = > AccountWithMetadata {
2025-12-04 21:53:58 -05:00
account : Account ::default ( ) ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
2025-12-04 21:53:58 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::PoolDefinitionInit = > AccountWithMetadata {
2025-12-04 21:53:58 -05:00
account : Account {
2025-12-06 14:52:18 -05:00
program_owner : ProgramId ::default ( ) ,
2025-12-04 21:53:58 -05:00
balance : 0 u128 ,
data : PoolDefinition ::into_data (
PoolDefinition {
2025-12-07 20:34:26 -05:00
definition_token_a_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
definition_token_b_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
2025-12-08 22:05:51 -05:00
vault_a_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
vault_b_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
2025-12-07 20:34:26 -05:00
liquidity_pool_id : helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
liquidity_pool_supply : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
reserve_a : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
reserve_b : helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) ,
2025-12-06 14:52:18 -05:00
fees : 0 u128 ,
2025-12-04 21:53:58 -05:00
active : true ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
2025-12-04 21:53:58 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::PoolDefinitionInitReserveAZero = > AccountWithMetadata {
2025-12-04 21:53:58 -05:00
account : Account {
2025-12-06 14:52:18 -05:00
program_owner : ProgramId ::default ( ) ,
2025-12-04 21:53:58 -05:00
balance : 0 u128 ,
data : PoolDefinition ::into_data (
PoolDefinition {
2025-12-07 20:34:26 -05:00
definition_token_a_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
definition_token_b_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
2025-12-08 22:05:51 -05:00
vault_a_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
vault_b_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
2025-12-07 20:34:26 -05:00
liquidity_pool_id : helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
liquidity_pool_supply : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
2025-12-06 14:52:18 -05:00
reserve_a : 0 ,
2025-12-07 20:34:26 -05:00
reserve_b : helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) ,
2025-12-06 14:52:18 -05:00
fees : 0 u128 ,
2025-12-04 21:53:58 -05:00
active : true ,
} ) ,
nonce : 0 ,
} ,
2025-12-06 14:52:18 -05:00
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
2025-12-04 21:53:58 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::PoolDefinitionInitReserveBZero = > AccountWithMetadata {
2025-12-06 14:52:18 -05:00
account : Account {
program_owner : ProgramId ::default ( ) ,
balance : 0 u128 ,
data : PoolDefinition ::into_data (
PoolDefinition {
2025-12-07 20:34:26 -05:00
definition_token_a_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
definition_token_b_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
2025-12-08 22:05:51 -05:00
vault_a_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
vault_b_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
2025-12-07 20:34:26 -05:00
liquidity_pool_id : helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
liquidity_pool_supply : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
reserve_a : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
2025-12-06 14:52:18 -05:00
reserve_b : 0 ,
fees : 0 u128 ,
active : true ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
2025-12-06 14:52:18 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::PoolDefinitionInitReserveALow = > AccountWithMetadata {
2025-12-06 14:52:18 -05:00
account : Account {
program_owner : ProgramId ::default ( ) ,
balance : 0 u128 ,
data : PoolDefinition ::into_data (
PoolDefinition {
2025-12-07 20:34:26 -05:00
definition_token_a_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
definition_token_b_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
2025-12-08 22:05:51 -05:00
vault_a_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
vault_b_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
2025-12-07 20:34:26 -05:00
liquidity_pool_id : helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
liquidity_pool_supply : helper_balance_constructor ( BalanceEnum ::VaultAReserveLow ) ,
reserve_a : helper_balance_constructor ( BalanceEnum ::VaultAReserveLow ) ,
reserve_b : helper_balance_constructor ( BalanceEnum ::VaultBReserveHigh ) ,
2025-12-06 14:52:18 -05:00
fees : 0 u128 ,
active : true ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
2025-12-06 14:52:18 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::PoolDefinitionInitReserveBLow = > AccountWithMetadata {
2025-12-06 14:52:18 -05:00
account : Account {
program_owner : ProgramId ::default ( ) ,
balance : 0 u128 ,
data : PoolDefinition ::into_data (
PoolDefinition {
2025-12-07 20:34:26 -05:00
definition_token_a_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
definition_token_b_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
2025-12-08 22:05:51 -05:00
vault_a_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
vault_b_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
2025-12-07 20:34:26 -05:00
liquidity_pool_id : helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
liquidity_pool_supply : helper_balance_constructor ( BalanceEnum ::VaultAReserveHigh ) ,
reserve_a : helper_balance_constructor ( BalanceEnum ::VaultAReserveHigh ) ,
reserve_b : helper_balance_constructor ( BalanceEnum ::VaultBReserveLow ) ,
2025-12-06 14:52:18 -05:00
fees : 0 u128 ,
active : true ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
2025-12-06 14:52:18 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::PoolDefinitionUnauth = > AccountWithMetadata {
2025-12-06 14:52:18 -05:00
account : Account {
program_owner : ProgramId ::default ( ) ,
balance : 0 u128 ,
data : PoolDefinition ::into_data (
PoolDefinition {
2025-12-07 20:34:26 -05:00
definition_token_a_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
definition_token_b_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
2025-12-08 22:05:51 -05:00
vault_a_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
vault_b_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
2025-12-07 20:34:26 -05:00
liquidity_pool_id : helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
liquidity_pool_supply : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
reserve_a : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
reserve_b : helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) ,
2025-12-06 14:52:18 -05:00
fees : 0 u128 ,
active : true ,
} ) ,
nonce : 0 ,
} ,
is_authorized : false ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
2025-12-06 14:52:18 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::PoolDefinitionSwapTest1 = > AccountWithMetadata {
2025-12-06 14:52:18 -05:00
account : Account {
program_owner : ProgramId ::default ( ) ,
balance : 0 u128 ,
data : PoolDefinition ::into_data (
PoolDefinition {
2025-12-07 20:34:26 -05:00
definition_token_a_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
definition_token_b_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
2025-12-08 22:05:51 -05:00
vault_a_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
vault_b_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
2025-12-07 20:34:26 -05:00
liquidity_pool_id : helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
liquidity_pool_supply : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
reserve_a : helper_balance_constructor ( BalanceEnum ::VaultASwapTest1 ) ,
reserve_b : helper_balance_constructor ( BalanceEnum ::VaultBSwapTest1 ) ,
2025-12-06 14:52:18 -05:00
fees : 0 u128 ,
active : true ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
2025-12-06 14:52:18 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::PoolDefinitionSwapTest2 = > AccountWithMetadata {
2025-12-06 14:52:18 -05:00
account : Account {
program_owner : ProgramId ::default ( ) ,
balance : 0 u128 ,
data : PoolDefinition ::into_data (
PoolDefinition {
2025-12-07 20:34:26 -05:00
definition_token_a_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
definition_token_b_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
2025-12-08 22:05:51 -05:00
vault_a_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
vault_b_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
2025-12-07 20:34:26 -05:00
liquidity_pool_id : helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
liquidity_pool_supply : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
reserve_a : helper_balance_constructor ( BalanceEnum ::VaultASwapTest2 ) ,
reserve_b : helper_balance_constructor ( BalanceEnum ::VaultBSwapTest2 ) ,
2025-12-06 14:52:18 -05:00
fees : 0 u128 ,
active : true ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
2025-12-06 14:52:18 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::PoolDefinitionAddZeroLP = > AccountWithMetadata {
2025-12-06 14:52:18 -05:00
account : Account {
program_owner : ProgramId ::default ( ) ,
balance : 0 u128 ,
data : PoolDefinition ::into_data (
PoolDefinition {
2025-12-07 20:34:26 -05:00
definition_token_a_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
definition_token_b_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
2025-12-08 22:05:51 -05:00
vault_a_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
vault_b_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
2025-12-07 20:34:26 -05:00
liquidity_pool_id : helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
liquidity_pool_supply : helper_balance_constructor ( BalanceEnum ::VaultAReserveLow ) ,
reserve_a : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
reserve_b : helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) ,
2025-12-06 14:52:18 -05:00
fees : 0 u128 ,
active : true ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
2025-12-06 14:52:18 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::PoolDefinitionAddSuccessful = > AccountWithMetadata {
2025-12-06 14:52:18 -05:00
account : Account {
program_owner : ProgramId ::default ( ) ,
balance : 0 u128 ,
data : PoolDefinition ::into_data (
PoolDefinition {
2025-12-07 20:34:26 -05:00
definition_token_a_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
definition_token_b_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
2025-12-08 22:05:51 -05:00
vault_a_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
vault_b_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
2025-12-07 20:34:26 -05:00
liquidity_pool_id : helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
liquidity_pool_supply : helper_balance_constructor ( BalanceEnum ::VaultAAddSuccessful ) ,
reserve_a : helper_balance_constructor ( BalanceEnum ::VaultAAddSuccessful ) ,
reserve_b : helper_balance_constructor ( BalanceEnum ::VaultBAddSuccessful ) ,
2025-12-06 14:52:18 -05:00
fees : 0 u128 ,
active : true ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
2025-12-06 14:52:18 -05:00
} ,
2025-12-07 20:34:26 -05:00
AccountEnum ::PoolDefinitionRemoveSuccessful = > AccountWithMetadata {
2025-12-06 14:52:18 -05:00
account : Account {
program_owner : ProgramId ::default ( ) ,
balance : 0 u128 ,
data : PoolDefinition ::into_data (
PoolDefinition {
2025-12-07 20:34:26 -05:00
definition_token_a_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
definition_token_b_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
2025-12-08 22:05:51 -05:00
vault_a_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
vault_b_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
2025-12-07 20:34:26 -05:00
liquidity_pool_id : helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
liquidity_pool_supply : helper_balance_constructor ( BalanceEnum ::VaultARemoveSuccessful ) ,
reserve_a : helper_balance_constructor ( BalanceEnum ::VaultARemoveSuccessful ) ,
reserve_b : helper_balance_constructor ( BalanceEnum ::VaultBRemoveSuccessful ) ,
2025-12-06 14:52:18 -05:00
fees : 0 u128 ,
active : true ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
2025-12-07 20:34:26 -05:00
account_id : helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
2025-12-06 14:52:18 -05:00
} ,
2025-12-08 22:05:51 -05:00
AccountEnum ::PoolDefinitionInactive = > AccountWithMetadata {
account : Account {
program_owner : ProgramId ::default ( ) ,
balance : 0 u128 ,
data : PoolDefinition ::into_data (
PoolDefinition {
definition_token_a_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
definition_token_b_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
vault_a_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
vault_b_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
liquidity_pool_id : helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
liquidity_pool_supply : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
reserve_a : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
reserve_b : helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) ,
fees : 0 u128 ,
active : false ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
account_id : helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
} ,
AccountEnum ::PoolDefinitionWrongId = > AccountWithMetadata {
account : Account {
program_owner : ProgramId ::default ( ) ,
balance : 0 u128 ,
data : PoolDefinition ::into_data (
PoolDefinition {
definition_token_a_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
definition_token_b_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
vault_a_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
vault_b_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
liquidity_pool_id : helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
liquidity_pool_supply : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
reserve_a : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
reserve_b : helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) ,
fees : 0 u128 ,
active : false ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
account_id : AccountId ::new ( [ 4 ; 32 ] ) ,
} ,
AccountEnum ::VaultAWrongId = > AccountWithMetadata {
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenHolding ::into_data (
TokenHolding {
account_type : 1 u8 ,
definition_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
balance : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
account_id : AccountId ::new ( [ 4 ; 32 ] ) ,
} ,
AccountEnum ::VaultBWrongId = > AccountWithMetadata {
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenHolding ::into_data (
TokenHolding {
account_type : 1 u8 ,
definition_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
balance : helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
account_id : AccountId ::new ( [ 4 ; 32 ] ) ,
} ,
AccountEnum ::PoolLPWrongId = > AccountWithMetadata {
account : Account {
program_owner : TOKEN_PROGRAM_ID ,
balance : 0 u128 ,
data : TokenDefinition ::into_data (
TokenDefinition {
account_type : 0 u8 ,
name : [ 1 ; 6 ] ,
total_supply : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
account_id : AccountId ::new ( [ 4 ; 32 ] ) ,
} ,
AccountEnum ::PoolDefinitionActive = > AccountWithMetadata {
account : Account {
program_owner : ProgramId ::default ( ) ,
balance : 0 u128 ,
data : PoolDefinition ::into_data (
PoolDefinition {
definition_token_a_id : helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
definition_token_b_id : helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
vault_a_id : helper_id_constructor ( IdEnum ::VaultAId ) ,
vault_b_id : helper_id_constructor ( IdEnum ::VaultBId ) ,
liquidity_pool_id : helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
liquidity_pool_supply : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
reserve_a : helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
reserve_b : helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) ,
fees : 0 u128 ,
active : true ,
} ) ,
nonce : 0 ,
} ,
is_authorized : true ,
account_id : helper_id_constructor ( IdEnum ::PoolDefinitionId ) ,
} ,
2025-12-06 14:52:18 -05:00
_ = > panic! ( " Invalid selection " ) ,
}
}
2025-12-08 13:19:30 -05:00
2025-12-08 22:05:51 -05:00
#[ test ]
fn test_pool_pda_produces_unique_id_for_token_pair ( ) {
//compute_pool_pda(amm_program_id: ProgramId, definition_token_a_id: AccountId, definition_token_b_id: AccountId)
assert! ( compute_pool_pda ( AMM_PROGRAM_ID ,
helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ) = =
compute_pool_pda ( AMM_PROGRAM_ID ,
helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
helper_id_constructor ( IdEnum ::TokenADefinitionId ) ) ) ;
}
2025-12-06 14:52:18 -05:00
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
2025-12-07 20:34:26 -05:00
fn test_call_new_definition_with_invalid_number_of_accounts_1 ( ) {
2025-12-06 14:52:18 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionUninit ) ,
2025-12-06 14:52:18 -05:00
] ;
2025-12-07 20:34:26 -05:00
let _post_states = new_definition ( & pre_states ,
& [ helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
2025-12-08 22:05:51 -05:00
helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) ] ,
AMM_PROGRAM_ID ,
2025-12-07 20:34:26 -05:00
) ;
2025-11-18 14:43:40 -05:00
}
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
2025-12-07 20:34:26 -05:00
fn test_call_new_definition_with_invalid_number_of_accounts_2 ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
2025-12-04 21:53:58 -05:00
] ;
2025-12-07 20:34:26 -05:00
let _post_states = new_definition ( & pre_states ,
& [ helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
2025-12-08 22:05:51 -05:00
helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) ] ,
AMM_PROGRAM_ID ,
2025-12-07 20:34:26 -05:00
) ;
}
2025-11-18 14:43:40 -05:00
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
2025-12-07 20:34:26 -05:00
fn test_call_new_definition__with_invalid_number_of_accounts_3 ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
2025-12-04 21:53:58 -05:00
] ;
2025-12-07 20:34:26 -05:00
let _post_states = new_definition ( & pre_states ,
& [ helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
2025-12-08 22:05:51 -05:00
helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) ] ,
AMM_PROGRAM_ID ,
2025-12-07 20:34:26 -05:00
) ;
2025-11-18 14:43:40 -05:00
}
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
2025-12-07 20:34:26 -05:00
fn test_call_new_definition__with_invalid_number_of_accounts_4 ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
2025-12-04 21:53:58 -05:00
] ;
2025-12-07 20:34:26 -05:00
let _post_states = new_definition ( & pre_states ,
& [ helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) ] ,
2025-12-08 22:05:51 -05:00
AMM_PROGRAM_ID ,
2025-12-07 20:34:26 -05:00
) ;
2025-11-18 14:43:40 -05:00
}
2025-12-07 20:34:26 -05:00
2025-11-18 14:43:40 -05:00
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
2025-12-07 20:34:26 -05:00
fn test_call_new_definition__with_invalid_number_of_accounts_5 ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
2025-12-04 21:53:58 -05:00
] ;
2025-12-07 20:34:26 -05:00
let _post_states = new_definition ( & pre_states ,
& [ helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) ] ,
2025-12-08 22:05:51 -05:00
AMM_PROGRAM_ID ,
2025-12-07 20:34:26 -05:00
) ;
2025-11-18 14:43:40 -05:00
}
2025-12-07 20:34:26 -05:00
#[ should_panic(expected = " Invalid number of input accounts " ) ]
2025-11-18 14:43:40 -05:00
#[ test ]
2025-12-07 20:34:26 -05:00
fn test_call_new_definition_with_invalid_number_of_accounts_6 ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
2025-12-04 21:53:58 -05:00
] ;
2025-12-07 20:34:26 -05:00
let _post_states = new_definition ( & pre_states ,
& [ helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) ] ,
2025-12-08 22:05:51 -05:00
AMM_PROGRAM_ID ,
2025-12-07 20:34:26 -05:00
) ;
2025-11-18 14:43:40 -05:00
}
2025-12-07 20:34:26 -05:00
#[ should_panic(expected = " Invalid number of input balances " ) ]
2025-11-18 14:43:40 -05:00
#[ test ]
2025-12-07 20:34:26 -05:00
fn test_call_new_definition_with_invalid_number_of_balances ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPUninit ) ,
2025-12-04 21:53:58 -05:00
] ;
2025-12-07 20:34:26 -05:00
let _post_states = new_definition ( & pre_states ,
& [ helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) , ] ,
2025-12-08 22:05:51 -05:00
AMM_PROGRAM_ID ,
2025-12-07 20:34:26 -05:00
) ;
}
2025-11-18 14:43:40 -05:00
#[ should_panic(expected = " Balances must be nonzero " ) ]
#[ test ]
2025-12-07 20:34:26 -05:00
fn test_call_new_definition_with_zero_balance_1 ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPUninit ) ,
2025-12-04 21:53:58 -05:00
] ;
2025-12-07 20:34:26 -05:00
let _post_states = new_definition ( & pre_states ,
2025-12-04 21:53:58 -05:00
& [ 0 ,
2025-12-07 20:34:26 -05:00
helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) , ] ,
2025-12-08 22:05:51 -05:00
AMM_PROGRAM_ID ,
2025-12-07 20:34:26 -05:00
) ;
}
2025-11-18 14:43:40 -05:00
#[ should_panic(expected = " Balances must be nonzero " ) ]
#[ test ]
2025-12-07 20:34:26 -05:00
fn test_call_new_definition_with_zero_balance_2 ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPUninit ) ,
2025-12-04 21:53:58 -05:00
] ;
2025-12-07 20:34:26 -05:00
let _post_states = new_definition ( & pre_states ,
& [ helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
2025-12-04 21:53:58 -05:00
0 ] ,
2025-12-08 22:05:51 -05:00
AMM_PROGRAM_ID ,
2025-12-07 20:34:26 -05:00
) ;
}
2025-12-04 21:53:58 -05:00
2025-12-07 20:34:26 -05:00
#[ should_panic(expected = " Cannot set up a swap for a token with itself " ) ]
2025-12-04 21:53:58 -05:00
#[ test ]
2025-12-07 20:34:26 -05:00
fn test_call_new_definition_same_token_definition ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPUninit ) ,
2025-12-04 21:53:58 -05:00
] ;
2025-12-07 20:34:26 -05:00
let _post_states = new_definition ( & pre_states ,
& [ helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) , ] ,
2025-12-08 22:05:51 -05:00
AMM_PROGRAM_ID ,
) ;
}
#[ should_panic(expected = " Liquidity pool Token Definition Account ID does not match PDA " ) ]
#[ test ]
fn test_call_new_definition_wrong_liquidity_id ( ) {
let pre_states = vec! [
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPWrongId ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPUninit ) ,
] ;
let _post_states = new_definition ( & pre_states ,
& [ helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) , ] ,
AMM_PROGRAM_ID ,
2025-12-04 21:53:58 -05:00
) ;
2025-12-07 20:34:26 -05:00
}
2025-12-08 22:05:51 -05:00
#[ should_panic(expected = " Pool Definition Account ID does not match PDA " ) ]
#[ test ]
fn test_call_new_definition_wrong_pool_id ( ) {
let pre_states = vec! [
helper_account_constructor ( AccountEnum ::PoolDefinitionWrongId ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPUninit ) ,
] ;
let _post_states = new_definition ( & pre_states ,
& [ helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) , ] ,
AMM_PROGRAM_ID ,
) ;
}
#[ should_panic(expected = " Vault ID does not match PDA " ) ]
#[ test ]
fn test_call_new_definition_wrong_vault_id_1 ( ) {
let pre_states = vec! [
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAWrongId ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPUninit ) ,
] ;
let _post_states = new_definition ( & pre_states ,
& [ helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) , ] ,
AMM_PROGRAM_ID ,
) ;
}
#[ should_panic(expected = " Vault ID does not match PDA " ) ]
#[ test ]
fn test_call_new_definition_wrong_vault_id_2 ( ) {
let pre_states = vec! [
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBWrongId ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPUninit ) ,
] ;
let _post_states = new_definition ( & pre_states ,
& [ helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) , ] ,
AMM_PROGRAM_ID ,
) ;
}
#[ should_panic(expected = " Cannot initialize an active Pool Definition " ) ]
#[ test ]
fn test_call_new_definition_cannot_initialize_active_pool ( ) {
let pre_states = vec! [
helper_account_constructor ( AccountEnum ::PoolDefinitionActive ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPUninit ) ,
] ;
let _post_states = new_definition ( & pre_states ,
& [ helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) , ] ,
AMM_PROGRAM_ID ,
) ;
}
#[ should_panic(expected = " Cannot initialize an active Pool Definition " ) ]
#[ test ]
fn test_call_new_definition_chain_call_successful ( ) {
let pre_states = vec! [
helper_account_constructor ( AccountEnum ::PoolDefinitionActive ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPUninit ) ,
] ;
let ( post_states , chained_calls ) = new_definition ( & pre_states ,
& [ helper_balance_constructor ( BalanceEnum ::VaultAReserveInit ) ,
helper_balance_constructor ( BalanceEnum ::VaultBReserveInit ) , ] ,
AMM_PROGRAM_ID ,
) ;
let pool_post = post_states [ 0 ] . clone ( ) ;
assert! ( helper_account_constructor ( AccountEnum ::PoolDefinitionAddSuccessful ) . account = =
* pool_post . account ( ) ) ;
let chained_call_lp = chained_calls [ 0 ] . clone ( ) ;
let chained_call_b = chained_calls [ 1 ] . clone ( ) ;
let chained_call_a = chained_calls [ 2 ] . clone ( ) ;
assert! ( chained_call_a = = helper_chained_call_constructor ( ChainedCallsEnum ::CcNewDefinitionTokenA ) ) ;
assert! ( chained_call_b = = helper_chained_call_constructor ( ChainedCallsEnum ::CcNewDefinitionTokenB ) ) ;
assert! ( chained_call_lp = = helper_chained_call_constructor ( ChainedCallsEnum ::CcNewDefinitionLP ) ) ;
}
2025-11-18 14:43:40 -05:00
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
fn test_call_remove_liquidity_with_invalid_number_of_accounts_2 ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
2025-12-04 21:53:58 -05:00
] ;
let _post_states = remove_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::RemoveAmountLP ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountA ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountB ) ] ,
2025-12-04 21:53:58 -05:00
) ;
2025-11-18 14:43:40 -05:00
}
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
fn test_call_remove_liquidity_with_invalid_number_of_accounts_3 ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
2025-12-04 21:53:58 -05:00
] ;
let _post_states = remove_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::RemoveAmountLP ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountA ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountB ) ] ,
2025-12-04 21:53:58 -05:00
) ;
2025-11-18 14:43:40 -05:00
}
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
fn test_call_remove_liquidity_with_invalid_number_of_accounts_4 ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
2025-12-04 21:53:58 -05:00
] ;
let _post_states = remove_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::RemoveAmountLP ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountA ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountB ) ] ,
2025-12-04 21:53:58 -05:00
) ;
}
2025-11-18 14:43:40 -05:00
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
fn test_call_remove_liquidity_with_invalid_number_of_accounts_5 ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
2025-12-04 21:53:58 -05:00
] ;
let _post_states = remove_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::RemoveAmountLP ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountA ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountB ) ] ,
2025-12-04 21:53:58 -05:00
) ;
2025-11-18 14:43:40 -05:00
}
2025-12-04 21:53:58 -05:00
#[ should_panic(expected = " Invalid number of input accounts " ) ]
2025-11-18 14:43:40 -05:00
#[ test ]
2025-12-04 21:53:58 -05:00
fn test_call_remove_liquidity_with_invalid_number_of_accounts_6 ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
2025-12-04 21:53:58 -05:00
] ;
let _post_states = remove_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::RemoveAmountLP ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountA ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountB ) ] ,
2025-12-04 21:53:58 -05:00
) ;
}
#[ should_panic(expected = " Vault A was not provided " ) ]
#[ test ]
fn test_call_remove_liquidity_vault_a_omitted ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAWrongAccId ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-04 21:53:58 -05:00
] ;
let _post_states = remove_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::RemoveAmountLP ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountA ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountB ) ] ,
2025-12-04 21:53:58 -05:00
) ;
}
#[ should_panic(expected = " Vault B was not provided " ) ]
#[ test ]
fn test_call_remove_liquidity_vault_b_omitted ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBWrongAccId ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-04 21:53:58 -05:00
] ;
let _post_states = remove_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::RemoveAmountLP ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountA ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountB ) ] ,
2025-12-04 21:53:58 -05:00
) ;
}
2025-12-06 20:03:05 -05:00
#[ should_panic(expected = " LP definition mismatch " ) ]
#[ test ]
fn test_call_remove_liquidity_lp_def_mismatch ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPWrongAccId ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-06 20:03:05 -05:00
] ;
let _post_states = remove_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::RemoveAmountLP ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountA ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountB ) ] ,
2025-12-06 20:03:05 -05:00
) ;
}
2025-12-04 21:53:58 -05:00
2025-12-06 14:52:18 -05:00
#[ should_panic(expected = " Invalid liquidity account provided " ) ]
2025-12-04 21:53:58 -05:00
#[ test ]
2025-12-06 14:52:18 -05:00
fn test_call_remove_liquidity_insufficient_liquidity_amount ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) , //different token account than lp to create desired error
2025-12-04 21:53:58 -05:00
] ;
2025-12-06 14:52:18 -05:00
let _post_states = remove_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::RemoveAmountLP ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountA ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountB ) ] ,
2025-12-04 21:53:58 -05:00
) ;
}
2025-12-06 14:52:18 -05:00
#[ should_panic(expected = " Insufficient minimal withdraw amount (Token A) provided for liquidity amount " ) ]
2025-11-18 14:43:40 -05:00
#[ test ]
2025-12-06 14:52:18 -05:00
fn test_call_remove_liquidity_insufficient_balance_1 ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-04 21:53:58 -05:00
] ;
2025-12-06 14:52:18 -05:00
let _post_states = remove_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::RemoveAmountLP1 ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountA ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountB ) ] ,
2025-12-04 21:53:58 -05:00
) ;
}
2025-11-18 14:43:40 -05:00
2025-12-06 14:52:18 -05:00
#[ should_panic(expected = " Insufficient minimal withdraw amount (Token B) provided for liquidity amount " ) ]
2025-12-04 21:53:58 -05:00
#[ test ]
2025-12-06 14:52:18 -05:00
fn test_call_remove_liquidity_insufficient_balance_2 ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-04 21:53:58 -05:00
] ;
2025-12-06 14:52:18 -05:00
let _post_states = remove_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::RemoveAmountLP ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountA ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountB ) ] ,
2025-12-04 21:53:58 -05:00
) ;
}
2025-11-20 21:02:18 -05:00
2025-12-06 14:52:18 -05:00
#[ should_panic(expected = " Minimum withdraw amount must be nonzero " ) ]
2025-12-04 21:53:58 -05:00
#[ test ]
2025-12-06 14:52:18 -05:00
fn test_call_remove_liquidity_min_bal_zero_1 ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-04 21:53:58 -05:00
] ;
2025-12-06 14:52:18 -05:00
let _post_states = remove_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::RemoveAmountLP ) ,
2025-12-06 14:52:18 -05:00
0 ,
2025-12-07 20:34:26 -05:00
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountB ) ] ,
2025-12-04 21:53:58 -05:00
) ;
}
2025-11-20 21:02:18 -05:00
2025-12-06 14:52:18 -05:00
#[ should_panic(expected = " Minimum withdraw amount must be nonzero " ) ]
2025-12-04 21:53:58 -05:00
#[ test ]
2025-12-06 14:52:18 -05:00
fn test_call_remove_liquidity_min_bal_zero_2 ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-04 21:53:58 -05:00
] ;
2025-12-06 14:52:18 -05:00
let _post_states = remove_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::RemoveAmountLP ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountA ) ,
2025-12-06 14:52:18 -05:00
0 ] ,
2025-12-04 21:53:58 -05:00
) ;
}
2025-11-20 21:02:18 -05:00
2025-12-06 14:52:18 -05:00
#[ should_panic(expected = " Liquidity amount must be nonzero " ) ]
2025-12-04 21:53:58 -05:00
#[ test ]
2025-12-06 14:52:18 -05:00
fn test_call_remove_liquidity_lp_bal_zero ( ) {
2025-12-04 21:53:58 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-04 21:53:58 -05:00
] ;
2025-12-06 14:52:18 -05:00
let _post_states = remove_liquidity ( & pre_states ,
& [ 0 ,
2025-12-07 20:34:26 -05:00
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountA ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountB ) , ] ,
2025-12-06 14:52:18 -05:00
) ;
}
#[ test ]
fn test_call_remove_liquidity_chained_call_successful ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-06 14:52:18 -05:00
] ;
let ( post_states , chained_calls ) = remove_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::RemoveAmountLP ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountA ) ,
helper_balance_constructor ( BalanceEnum ::RemoveMinAmountBLow ) , ] ,
2025-12-06 14:52:18 -05:00
) ;
let pool_post = post_states [ 0 ] . clone ( ) ;
2025-12-07 20:34:26 -05:00
assert! ( helper_account_constructor ( AccountEnum ::PoolDefinitionRemoveSuccessful ) . account = =
* pool_post . account ( ) ) ;
2025-12-06 14:52:18 -05:00
let chained_call_lp = chained_calls [ 0 ] . clone ( ) ;
let chained_call_b = chained_calls [ 1 ] . clone ( ) ;
let chained_call_a = chained_calls [ 2 ] . clone ( ) ;
2025-12-07 20:34:26 -05:00
assert! ( chained_call_a = = helper_chained_call_constructor ( ChainedCallsEnum ::CcRemoveTokenA ) ) ;
assert! ( chained_call_b = = helper_chained_call_constructor ( ChainedCallsEnum ::CcRemoveTokenB ) ) ;
assert! ( chained_call_lp . instruction_data = = helper_chained_call_constructor ( ChainedCallsEnum ::CcRemovePoolLP ) . instruction_data ) ;
2025-12-06 14:52:18 -05:00
}
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
fn test_call_add_liquidity_with_invalid_number_of_accounts_1 ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountb ) ,
helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) , ] ,
2025-12-04 21:53:58 -05:00
) ;
}
2025-12-06 14:52:18 -05:00
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
fn test_call_add_liquidity_with_invalid_number_of_accounts_2 ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountb ) ,
helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) , ] ,
2025-12-06 14:52:18 -05:00
) ;
}
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
fn test_call_add_liquidity_with_invalid_number_of_accounts_3 ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountb ) ,
helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) , ] ,
2025-12-06 14:52:18 -05:00
) ;
}
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
fn test_call_add_liquidity_with_invalid_number_of_accounts_4 ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountb ) ,
helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) , ] ,
2025-12-06 14:52:18 -05:00
) ;
}
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
fn test_call_add_liquidity_with_invalid_number_of_accounts_5 ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountb ) ,
helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) , ] ,
2025-12-06 14:52:18 -05:00
) ;
}
2025-11-20 21:02:18 -05:00
2025-12-06 14:52:18 -05:00
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
fn test_call_add_liquidity_with_invalid_number_of_accounts_6 ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountb ) ,
helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) , ] ,
2025-12-06 14:52:18 -05:00
) ;
}
2025-12-04 21:53:58 -05:00
#[ should_panic(expected = " Invalid number of input balances " ) ]
#[ test ]
fn test_call_add_liquidity_invalid_number_of_balances_1 ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-04 21:53:58 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) , ] ,
2025-12-04 21:53:58 -05:00
) ;
}
2025-11-18 14:43:40 -05:00
2025-12-04 21:53:58 -05:00
#[ should_panic(expected = " Vault A was not provided " ) ]
#[ test ]
fn test_call_add_liquidity_vault_a_omitted ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAWrongAccId ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-04 21:53:58 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountb ) ,
helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) , ] ,
2025-12-04 21:53:58 -05:00
) ;
}
2025-11-18 14:43:40 -05:00
2025-12-04 21:53:58 -05:00
#[ should_panic(expected = " Vault B was not provided " ) ]
#[ test ]
fn test_call_add_liquidity_vault_b_omitted ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBWrongAccId ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-04 21:53:58 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountb ) ,
helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) , ] ,
2025-12-04 21:53:58 -05:00
) ;
}
2025-11-18 14:43:40 -05:00
2025-12-06 20:03:05 -05:00
#[ should_panic(expected = " LP definition mismatch " ) ]
#[ test ]
fn test_call_add_liquidity_lp_def_mismatch ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPWrongAccId ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-06 20:03:05 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountb ) ,
helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) , ] ,
2025-12-06 20:03:05 -05:00
) ;
}
2025-12-04 21:53:58 -05:00
#[ should_panic(expected = " Both max-balances must be nonzero " ) ]
#[ test ]
fn test_call_add_liquidity_zero_balance_1 ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-04 21:53:58 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) ,
2025-12-06 20:03:05 -05:00
0 ,
2025-12-07 20:34:26 -05:00
helper_balance_constructor ( BalanceEnum ::AddMaxAmountb ) , ] ,
2025-12-04 21:53:58 -05:00
) ;
2025-11-18 14:43:40 -05:00
}
2025-12-04 21:53:58 -05:00
#[ should_panic(expected = " Both max-balances must be nonzero " ) ]
#[ test ]
fn test_call_add_liquidity_zero_balance_2 ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-04 21:53:58 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
2025-12-06 14:52:18 -05:00
0 ,
2025-12-07 20:34:26 -05:00
helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) , ] ,
2025-12-04 21:53:58 -05:00
) ;
}
2025-12-06 14:52:18 -05:00
#[ should_panic(expected = " Min-lp must be nonzero " ) ]
2025-11-18 14:43:40 -05:00
#[ test ]
2025-12-06 14:52:18 -05:00
fn test_call_add_liquidity_zero_min_lp ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-06 20:03:05 -05:00
& [ 0 ,
2025-12-07 20:34:26 -05:00
helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountb ) , ] , ) ;
2025-12-06 14:52:18 -05:00
}
2025-11-20 21:02:18 -05:00
2025-12-06 14:52:18 -05:00
#[ should_panic(expected = " Vaults' balances must be at least the reserve amounts " ) ]
2025-11-20 21:02:18 -05:00
#[ test ]
2025-12-06 14:52:18 -05:00
fn test_call_add_liquidity_vault_insufficient_balance_1 ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInitZero ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountb ) ,
helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) , ] ,
2025-12-06 14:52:18 -05:00
) ;
}
#[ should_panic(expected = " Vaults' balances must be at least the reserve amounts " ) ]
2025-11-20 21:02:18 -05:00
#[ test ]
2025-12-06 14:52:18 -05:00
fn test_call_add_liquidity_vault_insufficient_balance_2 ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInitZero ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountb ) ,
helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) , ] ,
2025-12-06 14:52:18 -05:00
) ;
}
#[ should_panic(expected = " A trade amount is 0 " ) ]
2025-11-20 21:02:18 -05:00
#[ test ]
2025-12-06 14:52:18 -05:00
fn test_call_add_liquidity_actual_amount_zero_1 ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInitReserveALow ) ,
helper_account_constructor ( AccountEnum ::VaultAInitLow ) ,
helper_account_constructor ( AccountEnum ::VaultBInitHigh ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountb ) ,
helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) , ] ,
2025-12-06 14:52:18 -05:00
) ;
}
#[ should_panic(expected = " A trade amount is 0 " ) ]
2025-11-20 21:02:18 -05:00
#[ test ]
2025-12-06 14:52:18 -05:00
fn test_call_add_liquidity_actual_amount_zero_2 ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInitReserveBLow ) ,
helper_account_constructor ( AccountEnum ::VaultAInitHigh ) ,
helper_account_constructor ( AccountEnum ::VaultBInitLow ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountALow ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountBLow ) ,
helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) , ] ,
2025-12-06 14:52:18 -05:00
) ;
2025-11-20 21:02:18 -05:00
}
#[ should_panic(expected = " Reserves must be nonzero " ) ]
#[ test ]
2025-11-25 23:06:47 -05:00
fn test_call_add_liquidity_reserves_zero_1 ( ) {
2025-12-06 14:52:18 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInitReserveAZero ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountb ) ,
helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) , ] ,
2025-12-06 14:52:18 -05:00
) ;
2025-11-25 23:06:47 -05:00
}
2025-11-26 21:44:57 -05:00
2025-11-25 23:06:47 -05:00
#[ should_panic(expected = " Reserves must be nonzero " ) ]
#[ test ]
2025-12-06 14:52:18 -05:00
fn test_call_add_liquidity_reserves_zero_2 ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInitReserveBZero ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountb ) ,
helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) , ] ,
2025-12-06 14:52:18 -05:00
) ;
2025-11-20 21:02:18 -05:00
}
2025-12-06 14:52:18 -05:00
#[ should_panic(expected = " Payable LP must be nonzero " ) ]
2025-11-25 23:06:47 -05:00
#[ test ]
2025-12-06 14:52:18 -05:00
fn test_call_add_liquidity_payable_lp_zero ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionAddZeroLP ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountALow ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountBLow ) ,
helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) , ] ,
2025-12-06 14:52:18 -05:00
) ;
2025-11-26 21:44:57 -05:00
}
2025-12-06 14:52:18 -05:00
2025-11-26 21:44:57 -05:00
#[ test ]
2025-12-06 14:52:18 -05:00
fn test_call_add_liquidity_successful_chain_call ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::PoolLPInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
helper_account_constructor ( AccountEnum ::UserHoldingLPInit ) ,
2025-12-06 14:52:18 -05:00
] ;
let ( post_states , chained_calls ) = add_liquidity ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMinAmountLP ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountb ) , ] ,
2025-12-06 14:52:18 -05:00
) ;
2025-11-26 21:44:57 -05:00
2025-12-06 14:52:18 -05:00
let pool_post = post_states [ 0 ] . clone ( ) ;
2025-11-26 21:44:57 -05:00
2025-12-07 20:34:26 -05:00
assert! ( helper_account_constructor ( AccountEnum ::PoolDefinitionAddSuccessful ) . account = =
* pool_post . account ( ) ) ;
2025-11-26 21:44:57 -05:00
let chained_call_lp = chained_calls [ 0 ] . clone ( ) ;
let chained_call_b = chained_calls [ 1 ] . clone ( ) ;
let chained_call_a = chained_calls [ 2 ] . clone ( ) ;
2025-12-07 20:34:26 -05:00
assert! ( chained_call_a = = helper_chained_call_constructor ( ChainedCallsEnum ::CcAddTokenA ) ) ;
assert! ( chained_call_b = = helper_chained_call_constructor ( ChainedCallsEnum ::CcAddTokenB ) ) ;
assert! ( chained_call_lp = = helper_chained_call_constructor ( ChainedCallsEnum ::CcAddPoolLP ) ) ;
2025-11-26 21:44:57 -05:00
}
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
fn test_call_swap_with_invalid_number_of_accounts_1 ( ) {
2025-12-06 14:52:18 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = swap ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::MinAmountOut ) ] ,
helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
2025-12-06 14:52:18 -05:00
) ;
2025-11-26 21:44:57 -05:00
}
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
fn test_call_swap_with_invalid_number_of_accounts_2 ( ) {
2025-12-06 14:52:18 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = swap ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::MinAmountOut ) ] ,
helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
2025-12-06 14:52:18 -05:00
) ;
2025-11-26 21:44:57 -05:00
}
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
fn test_call_swap_with_invalid_number_of_accounts_3 ( ) {
2025-12-06 14:52:18 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = swap ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::MinAmountOut ) ] ,
helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
2025-12-06 14:52:18 -05:00
) ;
2025-11-25 23:06:47 -05:00
}
#[ should_panic(expected = " Invalid number of input accounts " ) ]
#[ test ]
fn test_call_swap_with_invalid_number_of_accounts_4 ( ) {
2025-12-06 14:52:18 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = swap ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::MinAmountOut ) ] ,
helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
2025-12-06 14:52:18 -05:00
) ;
}
#[ should_panic(expected = " Invalid number of amounts provided " ) ]
#[ test ]
fn test_call_swap_with_invalid_number_of_amounts ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = swap ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ] ,
helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
2025-12-06 14:52:18 -05:00
) ;
2025-11-25 23:06:47 -05:00
}
2025-12-02 15:20:16 -05:00
#[ should_panic(expected = " AccountId is not a token type for the pool " ) ]
2025-11-20 21:02:18 -05:00
#[ test ]
fn test_call_swap_incorrect_token_type ( ) {
2025-12-06 14:52:18 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = swap ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::MinAmountOut ) ] ,
helper_id_constructor ( IdEnum ::TokenLPDefinitionId ) ,
2025-12-06 14:52:18 -05:00
) ;
2025-11-20 21:02:18 -05:00
}
#[ should_panic(expected = " Vault A was not provided " ) ]
#[ test ]
fn test_call_swap_vault_a_omitted ( ) {
2025-12-06 14:52:18 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAWrongAccId ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = swap ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::MinAmountOut ) ] ,
helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
2025-12-06 14:52:18 -05:00
) ;
2025-11-20 21:02:18 -05:00
}
#[ should_panic(expected = " Vault B was not provided " ) ]
#[ test ]
fn test_call_swap_vault_b_omitted ( ) {
2025-12-06 14:52:18 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBWrongAccId ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = swap ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::MinAmountOut ) ] ,
helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
2025-12-06 14:52:18 -05:00
) ;
2025-11-18 14:43:40 -05:00
}
2025-11-26 21:44:57 -05:00
2025-12-06 14:52:18 -05:00
#[ should_panic(expected = " Reserve for Token A exceeds vault balance " ) ]
2025-11-26 21:44:57 -05:00
#[ test ]
2025-12-06 14:52:18 -05:00
fn test_call_swap_reserves_vault_mismatch_1 ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInitLow ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = swap ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::MinAmountOut ) ] ,
helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
2025-12-06 14:52:18 -05:00
) ;
}
2025-11-26 21:44:57 -05:00
2025-12-06 14:52:18 -05:00
#[ should_panic(expected = " Reserve for Token B exceeds vault balance " ) ]
#[ test ]
2025-12-08 22:05:51 -05:00
fn test_call_swap_reserves_vault_mismatch_2 ( ) {
2025-12-06 14:52:18 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInitLow ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = swap ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::MinAmountOut ) ] ,
helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
2025-12-06 14:52:18 -05:00
) ;
}
2025-11-26 21:44:57 -05:00
2025-12-08 22:05:51 -05:00
#[ should_panic(expected = " Pool is inactive " ) ]
#[ test ]
fn test_call_swap_ianctive ( ) {
let pre_states = vec! [
helper_account_constructor ( AccountEnum ::PoolDefinitionInactive ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
] ;
let _post_states = swap ( & pre_states ,
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::MinAmountOut ) ] ,
helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
) ;
}
2025-12-06 14:52:18 -05:00
#[ should_panic(expected = " Withdraw amount is less than minimal amount out " ) ]
#[ test ]
fn test_call_swap_below_min_out ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
2025-12-06 14:52:18 -05:00
] ;
let _post_states = swap ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::MinAmountOut ) ] ,
helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
2025-12-06 14:52:18 -05:00
) ;
}
2025-11-26 21:44:57 -05:00
2025-12-06 14:52:18 -05:00
#[ test ]
fn test_call_swap_successful_chain_call_1 ( ) {
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
2025-12-06 14:52:18 -05:00
] ;
let ( post_states , chained_calls ) = swap ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountA ) ,
helper_balance_constructor ( BalanceEnum ::AddMaxAmountALow ) ] ,
helper_id_constructor ( IdEnum ::TokenADefinitionId ) ,
2025-12-06 14:52:18 -05:00
) ;
let pool_post = post_states [ 0 ] . clone ( ) ;
2025-11-26 21:44:57 -05:00
2025-12-07 20:34:26 -05:00
assert! ( helper_account_constructor ( AccountEnum ::PoolDefinitionSwapTest1 ) . account = =
* pool_post . account ( ) ) ;
2025-12-06 14:52:18 -05:00
let chained_call_a = chained_calls [ 0 ] . clone ( ) ;
let chained_call_b = chained_calls [ 1 ] . clone ( ) ;
2025-12-07 20:34:26 -05:00
assert! ( chained_call_a = = helper_chained_call_constructor ( ChainedCallsEnum ::CcSwapTokenATest1 ) ) ;
assert! ( chained_call_b = = helper_chained_call_constructor ( ChainedCallsEnum ::CcSwapTokenBTest1 ) ) ;
2025-11-26 21:44:57 -05:00
}
#[ test ]
fn test_call_swap_successful_chain_call_2 ( ) {
2025-12-06 14:52:18 -05:00
let pre_states = vec! [
2025-12-07 20:34:26 -05:00
helper_account_constructor ( AccountEnum ::PoolDefinitionInit ) ,
helper_account_constructor ( AccountEnum ::VaultAInit ) ,
helper_account_constructor ( AccountEnum ::VaultBInit ) ,
helper_account_constructor ( AccountEnum ::UserHoldingA ) ,
helper_account_constructor ( AccountEnum ::UserHoldingB ) ,
2025-12-06 14:52:18 -05:00
] ;
let ( post_states , chained_calls ) = swap ( & pre_states ,
2025-12-07 20:34:26 -05:00
& [ helper_balance_constructor ( BalanceEnum ::AddMaxAmountb ) ,
helper_balance_constructor ( BalanceEnum ::MinAmountOut ) ] ,
helper_id_constructor ( IdEnum ::TokenBDefinitionId ) ,
2025-12-06 14:52:18 -05:00
) ;
let pool_post = post_states [ 0 ] . clone ( ) ;
2025-12-07 20:34:26 -05:00
assert! ( helper_account_constructor ( AccountEnum ::PoolDefinitionSwapTest2 ) . account = =
* pool_post . account ( ) ) ;
2025-12-06 14:52:18 -05:00
let chained_call_a = chained_calls [ 1 ] . clone ( ) ;
let chained_call_b = chained_calls [ 0 ] . clone ( ) ;
2025-12-07 20:34:26 -05:00
assert! ( chained_call_a = = helper_chained_call_constructor ( ChainedCallsEnum ::CcSwapTokenATest2 ) ) ;
assert! ( chained_call_b = = helper_chained_call_constructor ( ChainedCallsEnum ::CcSwapTokenBTest2 ) ) ;
2025-12-06 14:52:18 -05:00
}
2025-12-07 20:34:26 -05:00
2025-11-26 21:44:57 -05:00
}