From 7d31b0694e035b4c29eef93c4ec57d5330d00af6 Mon Sep 17 00:00:00 2001 From: crypto-vincent Date: Tue, 8 Oct 2024 17:34:56 +0900 Subject: [PATCH] Credix liquidity exchange IX (#331) This PR introduces a permissionless IX that allows any user to buy credix_lp liquidity directly from the on-chain program using USDC that will be deposited into the identity_depository. This allows anyone to take over the liquidity risks from the uxd-program while keeping the proper redeemable backing. --- programs/uxd/src/events.rs | 17 + ...nge_liquidity_with_credix_lp_depository.rs | 326 ++++++++++++++++++ .../uxd/src/instructions/credix_lp/mod.rs | 2 + programs/uxd/src/lib.rs | 12 + .../api/program_credix/instructions/mod.rs | 2 + .../process_thaw_freeze_token_account.rs | 42 +++ .../api/program_uxd/instructions/mod.rs | 2 + ...nge_liquidity_with_credix_lp_depository.rs | 211 ++++++++++++ .../uxd/tests/integration_tests/suites/mod.rs | 1 + ...credix_lp_depository_exchange_liquidity.rs | 300 ++++++++++++++++ .../suites/test_ensure_devnet.rs | 2 +- target/idl/uxd.json | 150 ++++++-- target/types/uxd.ts | 300 +++++++++++++--- 13 files changed, 1297 insertions(+), 70 deletions(-) create mode 100644 programs/uxd/src/instructions/credix_lp/exchange_liquidity_with_credix_lp_depository.rs create mode 100644 programs/uxd/tests/integration_tests/api/program_credix/instructions/process_thaw_freeze_token_account.rs create mode 100644 programs/uxd/tests/integration_tests/api/program_uxd/instructions/process_exchange_liquidity_with_credix_lp_depository.rs create mode 100644 programs/uxd/tests/integration_tests/suites/test_credix_lp_depository_exchange_liquidity.rs diff --git a/programs/uxd/src/events.rs b/programs/uxd/src/events.rs index fa26e3dbb..fdc174bae 100644 --- a/programs/uxd/src/events.rs +++ b/programs/uxd/src/events.rs @@ -295,6 +295,23 @@ pub struct CollectProfitsOfCredixLpDepositoryEvent { pub collateral_amount: u64, } +/// Event called in [instructions::exchange_liquidity_with_credix_lp_depository::handler]. +#[event] +pub struct ExchangeLiquidityWithCredixLpDepositoryEvent { + #[index] + pub controller_version: u8, + #[index] + pub depository_version: u8, + #[index] + pub controller: Pubkey, + #[index] + pub depository: Pubkey, + /// The collateral amount in native units. (input) + pub collateral_amount: u64, + /// The shares amount in native units. (output) + pub shares_amount: u64, +} + /// Event called in [instructions::rebalance_create_withdraw_request_from_credix_lp_depository::handler]. #[event] pub struct RebalanceCreateWithdrawRequestFromCredixLpDepositoryEvent { diff --git a/programs/uxd/src/instructions/credix_lp/exchange_liquidity_with_credix_lp_depository.rs b/programs/uxd/src/instructions/credix_lp/exchange_liquidity_with_credix_lp_depository.rs new file mode 100644 index 000000000..9dfc9deef --- /dev/null +++ b/programs/uxd/src/instructions/credix_lp/exchange_liquidity_with_credix_lp_depository.rs @@ -0,0 +1,326 @@ +use anchor_lang::prelude::*; +use anchor_spl::token; +use anchor_spl::token::Mint; +use anchor_spl::token::Token; +use anchor_spl::token::TokenAccount; +use anchor_spl::token::Transfer; + +use crate::error::UxdError; +use crate::events::ExchangeLiquidityWithCredixLpDepositoryEvent; +use crate::state::controller::Controller; +use crate::state::credix_lp_depository::CredixLpDepository; +use crate::state::identity_depository::IdentityDepository; +use crate::utils::checked_add; +use crate::utils::checked_as_u64; +use crate::utils::checked_sub; +use crate::utils::compute_decrease; +use crate::utils::compute_increase; +use crate::validate_is_program_frozen; +use crate::CONTROLLER_NAMESPACE; +use crate::CREDIX_LP_DEPOSITORY_NAMESPACE; +use crate::IDENTITY_DEPOSITORY_COLLATERAL_NAMESPACE; +use crate::IDENTITY_DEPOSITORY_NAMESPACE; + +#[derive(Accounts)] +pub struct ExchangeLiquidityWithCredixLpDepository<'info> { + /// #1 + #[account(mut)] + pub payer: Signer<'info>, + + /// #2 + pub user: Signer<'info>, + + /// #3 + #[account( + mut, + seeds = [CONTROLLER_NAMESPACE], + bump = controller.load()?.bump, + constraint = controller.load()?.identity_depository == identity_depository.key() @UxdError::InvalidDepository, + constraint = controller.load()?.credix_lp_depository == credix_lp_depository.key() @UxdError::InvalidDepository, + )] + pub controller: AccountLoader<'info, Controller>, + + /// #4 + #[account( + mut, + seeds = [IDENTITY_DEPOSITORY_NAMESPACE], + bump = identity_depository.load()?.bump, + )] + pub identity_depository: AccountLoader<'info, IdentityDepository>, + + /// #5 + #[account( + mut, + seeds = [IDENTITY_DEPOSITORY_COLLATERAL_NAMESPACE], + token::authority = identity_depository, + token::mint = identity_depository.load()?.collateral_mint, + bump = identity_depository.load()?.collateral_vault_bump, + )] + pub identity_depository_collateral: Box>, + + /// #6 + #[account( + mut, + seeds = [CREDIX_LP_DEPOSITORY_NAMESPACE, credix_lp_depository.load()?.credix_global_market_state.key().as_ref(), credix_lp_depository.load()?.collateral_mint.as_ref()], + bump = credix_lp_depository.load()?.bump, + has_one = controller @UxdError::InvalidController, + has_one = collateral_mint @UxdError::InvalidCollateralMint, + constraint = credix_lp_depository.load()?.depository_shares == credix_lp_depository_shares.key() @UxdError::InvalidDepositoryShares, + constraint = credix_lp_depository.load()?.credix_shares_mint == credix_shares_mint.key() @UxdError::InvalidCredixSharesMint, + )] + pub credix_lp_depository: AccountLoader<'info, CredixLpDepository>, + + /// #7 + #[account(mut)] + pub credix_lp_depository_shares: Box>, + + /// #8 + #[account( + mut, + token::mint = collateral_mint, + token::authority = user, + )] + pub user_collateral: Box>, + + /// #9 + #[account( + mut, + token::mint = credix_shares_mint, + constraint = receiver_credix_shares.key() != credix_lp_depository_shares.key() + )] + pub receiver_credix_shares: Box>, + + /// #10 + pub collateral_mint: Box>, + + /// #11 + pub credix_shares_mint: Box>, + + /// #12 + pub system_program: Program<'info, System>, + /// #13 + pub token_program: Program<'info, Token>, +} + +pub(crate) fn handler( + ctx: Context, + collateral_amount: u64, +) -> Result<()> { + // --------------------------------------------------------------------- + // -- Phase 1 + // -- Fetch all current onchain state + // -- Compute the amount of shares and collateral exchanged + // --------------------------------------------------------------------- + + // Read all states before exchange + let identity_depository_collateral_amount_before = + ctx.accounts.identity_depository_collateral.amount; + let credix_lp_depository_shares_amount_before = ctx.accounts.credix_lp_depository_shares.amount; + let user_collateral_amount_before = ctx.accounts.user_collateral.amount; + let receiver_credix_shares_amount_before = ctx.accounts.receiver_credix_shares.amount; + + // Compute the amount of shares we will exchange for the provided collateral + let redeemable_amount_under_management = ctx + .accounts + .credix_lp_depository + .load()? + .redeemable_amount_under_management; + let available_shares_amount = ctx.accounts.credix_lp_depository_shares.amount; + let exchanged_shares_amount = checked_as_u64( + u128::from(available_shares_amount) * u128::from(collateral_amount) + / redeemable_amount_under_management, + )?; + + msg!( + "[redeemable_amount_under_management:{}]", + redeemable_amount_under_management + ); + msg!("[collateral_amount:{}]", collateral_amount); + msg!("[available_shares_amount:{}]", available_shares_amount); + msg!("[exchanged_shares_amount:{}]", exchanged_shares_amount); + + // Check the amount swapped is non-zero + require!( + exchanged_shares_amount > 0, + UxdError::InvalidCollateralAmount + ); + + // --------------------------------------------------------------------- + // -- Phase 2 + // -- Actually runs the onchain mutation based on computed parameters + // --------------------------------------------------------------------- + + // Make depository signer + let credix_global_market_state = ctx + .accounts + .credix_lp_depository + .load()? + .credix_global_market_state; + let collateral_mint = ctx.accounts.credix_lp_depository.load()?.collateral_mint; + let credix_lp_depository_pda_signer: &[&[&[u8]]] = &[&[ + CREDIX_LP_DEPOSITORY_NAMESPACE, + credix_global_market_state.as_ref(), + collateral_mint.as_ref(), + &[ctx.accounts.credix_lp_depository.load()?.bump], + ]]; + + msg!("[collateral_transfer:{}]", collateral_amount); + token::transfer( + ctx.accounts + .into_transfer_user_collateral_to_identity_depository_collateral_context(), + collateral_amount, + )?; + + msg!("[shares_transfer:{}]", exchanged_shares_amount); + token::transfer( + ctx.accounts + .into_transfer_credix_lp_depository_shares_to_receiver_credix_shares_context() + .with_signer(credix_lp_depository_pda_signer), + exchanged_shares_amount, + )?; + + // Refresh account states after withdrawal + ctx.accounts.identity_depository_collateral.reload()?; + ctx.accounts.credix_lp_depository_shares.reload()?; + ctx.accounts.user_collateral.reload()?; + ctx.accounts.receiver_credix_shares.reload()?; + + // --------------------------------------------------------------------- + // -- Phase 3 + // -- Strictly verify that the onchain state + // -- after mutation exactly match previous predictions + // --------------------------------------------------------------------- + + // Read all states after exchange + let identity_depository_collateral_amount_after = + ctx.accounts.identity_depository_collateral.amount; + let credix_lp_depository_shares_amount_after = ctx.accounts.credix_lp_depository_shares.amount; + let user_collateral_amount_after = ctx.accounts.user_collateral.amount; + let receiver_credix_shares_amount_after = ctx.accounts.receiver_credix_shares.amount; + + // Compute changes in states + let identity_depository_collateral_amount_increase = compute_increase( + identity_depository_collateral_amount_before, + identity_depository_collateral_amount_after, + )?; + let credix_lp_depository_shares_amount_decrease = compute_decrease( + credix_lp_depository_shares_amount_before, + credix_lp_depository_shares_amount_after, + )?; + let user_collateral_amount_decrease = + compute_decrease(user_collateral_amount_before, user_collateral_amount_after)?; + let receiver_credix_shares_amount_increase = compute_increase( + receiver_credix_shares_amount_before, + receiver_credix_shares_amount_after, + )?; + + // Log deltas for debriefing the changes + msg!( + "[identity_depository_collateral_amount_increase:{}]", + identity_depository_collateral_amount_increase + ); + msg!( + "[credix_lp_depository_shares_amount_decrease:{}]", + credix_lp_depository_shares_amount_decrease + ); + msg!( + "[user_collateral_amount_decrease:{}]", + user_collateral_amount_decrease + ); + msg!( + "[receiver_credix_shares_amount_increase:{}]", + receiver_credix_shares_amount_increase + ); + + // Fact check + require!( + identity_depository_collateral_amount_increase == collateral_amount, + UxdError::CollateralDepositAmountsDoesntMatch + ); + require!( + credix_lp_depository_shares_amount_decrease == exchanged_shares_amount, + UxdError::CollateralDepositDoesntMatchTokenValue + ); + require!( + user_collateral_amount_decrease == collateral_amount, + UxdError::CollateralDepositAmountsDoesntMatch + ); + require!( + receiver_credix_shares_amount_increase == exchanged_shares_amount, + UxdError::CollateralDepositDoesntMatchTokenValue + ); + + // --------------------------------------------------------------------- + // -- Phase 4 + // -- Emit resulting event, and update onchain accounting + // --------------------------------------------------------------------- + + // Emit event + emit!(ExchangeLiquidityWithCredixLpDepositoryEvent { + controller_version: ctx.accounts.controller.load()?.version, + depository_version: ctx.accounts.credix_lp_depository.load()?.version, + controller: ctx.accounts.controller.key(), + depository: ctx.accounts.credix_lp_depository.key(), + collateral_amount, + shares_amount: exchanged_shares_amount, + }); + + // Accounting for identity_depository + let mut identity_depository = ctx.accounts.identity_depository.load_mut()?; + identity_depository.collateral_amount_deposited = checked_add( + identity_depository.collateral_amount_deposited, + collateral_amount.into(), + )?; + identity_depository.redeemable_amount_under_management = checked_add( + identity_depository.redeemable_amount_under_management, + collateral_amount.into(), + )?; + + // Accounting for credix_lp_depository + let mut credix_lp_depository = ctx.accounts.credix_lp_depository.load_mut()?; + credix_lp_depository.collateral_amount_deposited = checked_sub( + credix_lp_depository.collateral_amount_deposited, + collateral_amount.into(), + )?; + credix_lp_depository.redeemable_amount_under_management = checked_sub( + credix_lp_depository.redeemable_amount_under_management, + collateral_amount.into(), + )?; + + // Done + Ok(()) +} + +// Into functions +impl<'info> ExchangeLiquidityWithCredixLpDepository<'info> { + pub fn into_transfer_user_collateral_to_identity_depository_collateral_context( + &self, + ) -> CpiContext<'_, '_, '_, 'info, token::Transfer<'info>> { + let cpi_accounts = Transfer { + from: self.user_collateral.to_account_info(), + to: self.identity_depository_collateral.to_account_info(), + authority: self.user.to_account_info(), + }; + let cpi_program = self.token_program.to_account_info(); + CpiContext::new(cpi_program, cpi_accounts) + } + pub fn into_transfer_credix_lp_depository_shares_to_receiver_credix_shares_context( + &self, + ) -> CpiContext<'_, '_, '_, 'info, token::Transfer<'info>> { + let cpi_accounts = Transfer { + from: self.credix_lp_depository_shares.to_account_info(), + to: self.receiver_credix_shares.to_account_info(), + authority: self.credix_lp_depository.to_account_info(), + }; + let cpi_program = self.token_program.to_account_info(); + CpiContext::new(cpi_program, cpi_accounts) + } +} + +// Validate +impl<'info> ExchangeLiquidityWithCredixLpDepository<'info> { + pub(crate) fn validate(&self) -> Result<()> { + validate_is_program_frozen(self.controller.load()?)?; + Ok(()) + } +} diff --git a/programs/uxd/src/instructions/credix_lp/mod.rs b/programs/uxd/src/instructions/credix_lp/mod.rs index 10f503f9c..70fb018d5 100644 --- a/programs/uxd/src/instructions/credix_lp/mod.rs +++ b/programs/uxd/src/instructions/credix_lp/mod.rs @@ -1,5 +1,6 @@ pub mod collect_profits_of_credix_lp_depository; pub mod edit_credix_lp_depository; +pub mod exchange_liquidity_with_credix_lp_depository; pub mod mint_with_credix_lp_depository; pub mod rebalance_create_withdraw_request_from_credix_lp_depository; pub mod rebalance_redeem_withdraw_request_from_credix_lp_depository; @@ -8,6 +9,7 @@ pub mod register_credix_lp_depository; pub use collect_profits_of_credix_lp_depository::*; pub use edit_credix_lp_depository::*; +pub use exchange_liquidity_with_credix_lp_depository::*; pub use mint_with_credix_lp_depository::*; pub use rebalance_create_withdraw_request_from_credix_lp_depository::*; pub use rebalance_redeem_withdraw_request_from_credix_lp_depository::*; diff --git a/programs/uxd/src/lib.rs b/programs/uxd/src/lib.rs index 0ae97eba0..e5c2e17e6 100644 --- a/programs/uxd/src/lib.rs +++ b/programs/uxd/src/lib.rs @@ -272,6 +272,18 @@ pub mod uxd { instructions::collect_profits_of_credix_lp_depository::handler(ctx) } + // Allow exchanging illiquid tokens locked with liquid tokens, pro-rata of LTV + #[access_control( + ctx.accounts.validate() + )] + pub fn exchange_liquidity_with_credix_lp_depository( + ctx: Context, + collateral_amount: u64, + ) -> Result<()> { + msg!("[exchange_liquidity_with_credix_lp_depository]"); + instructions::exchange_liquidity_with_credix_lp_depository::handler(ctx, collateral_amount) + } + // Create a rebalance request to collect profits and overflow from credix depository #[access_control( ctx.accounts.validate() diff --git a/programs/uxd/tests/integration_tests/api/program_credix/instructions/mod.rs b/programs/uxd/tests/integration_tests/api/program_credix/instructions/mod.rs index fef051b77..38d16ca19 100644 --- a/programs/uxd/tests/integration_tests/api/program_credix/instructions/mod.rs +++ b/programs/uxd/tests/integration_tests/api/program_credix/instructions/mod.rs @@ -11,6 +11,7 @@ pub mod process_repay_deal; pub mod process_set_locked_liquidity; pub mod process_set_repayment_schedule; pub mod process_set_tranches; +pub mod process_thaw_freeze_token_account; pub mod process_update_global_market_state; pub mod process_withdraw_from_deal; @@ -27,5 +28,6 @@ pub use process_repay_deal::*; pub use process_set_locked_liquidity::*; pub use process_set_repayment_schedule::*; pub use process_set_tranches::*; +pub use process_thaw_freeze_token_account::*; pub use process_update_global_market_state::*; pub use process_withdraw_from_deal::*; diff --git a/programs/uxd/tests/integration_tests/api/program_credix/instructions/process_thaw_freeze_token_account.rs b/programs/uxd/tests/integration_tests/api/program_credix/instructions/process_thaw_freeze_token_account.rs new file mode 100644 index 000000000..e702c57e1 --- /dev/null +++ b/programs/uxd/tests/integration_tests/api/program_credix/instructions/process_thaw_freeze_token_account.rs @@ -0,0 +1,42 @@ +use anchor_lang::InstructionData; +use anchor_lang::ToAccountMetas; +use solana_sdk::instruction::Instruction; +use solana_sdk::pubkey::Pubkey; +use solana_sdk::signature::Keypair; +use solana_sdk::signer::Signer; + +use crate::integration_tests::api::program_context; +use crate::integration_tests::api::program_credix; + +pub async fn process_thaw_freeze_token_account( + program_context: &mut Box, + multisig: &Keypair, + token_account: &Pubkey, + freeze: bool, +) -> Result<(), program_context::ProgramError> { + // Find needed accounts + let market_seeds = program_credix::accounts::find_market_seeds(); + let program_state = program_credix::accounts::find_program_state_pda().0; + let global_market_state = + program_credix::accounts::find_global_market_state_pda(&market_seeds).0; + let signing_authority = program_credix::accounts::find_signing_authority_pda(&market_seeds).0; + let lp_token_mint = program_credix::accounts::find_lp_token_mint_pda(&market_seeds).0; + + // Execute IX + let accounts = credix_client::accounts::ThawFreezeTokenAccount { + owner: multisig.pubkey(), + program_state, + global_market_state, + signing_authority, + token_account: *token_account, + mint: lp_token_mint, + token_program: anchor_spl::token::ID, + }; + let payload = credix_client::instruction::ThawFreezeTokenAccount { _freeze: freeze }; + let instruction = Instruction { + program_id: credix_client::id(), + accounts: accounts.to_account_metas(None), + data: payload.data(), + }; + program_context::process_instruction(program_context, instruction, multisig).await +} diff --git a/programs/uxd/tests/integration_tests/api/program_uxd/instructions/mod.rs b/programs/uxd/tests/integration_tests/api/program_uxd/instructions/mod.rs index 6c9993961..9c19f06e6 100644 --- a/programs/uxd/tests/integration_tests/api/program_uxd/instructions/mod.rs +++ b/programs/uxd/tests/integration_tests/api/program_uxd/instructions/mod.rs @@ -3,6 +3,7 @@ pub mod process_edit_controller; pub mod process_edit_credix_lp_depository; pub mod process_edit_identity_depository; pub mod process_edit_mercurial_vault_depository; +pub mod process_exchange_liquidity_with_credix_lp_depository; pub mod process_initialize_controller; pub mod process_initialize_identity_depository; pub mod process_mint; @@ -22,6 +23,7 @@ pub use process_edit_controller::*; pub use process_edit_credix_lp_depository::*; pub use process_edit_identity_depository::*; pub use process_edit_mercurial_vault_depository::*; +pub use process_exchange_liquidity_with_credix_lp_depository::*; pub use process_initialize_controller::*; pub use process_initialize_identity_depository::*; pub use process_mint::*; diff --git a/programs/uxd/tests/integration_tests/api/program_uxd/instructions/process_exchange_liquidity_with_credix_lp_depository.rs b/programs/uxd/tests/integration_tests/api/program_uxd/instructions/process_exchange_liquidity_with_credix_lp_depository.rs new file mode 100644 index 000000000..f6b95bca0 --- /dev/null +++ b/programs/uxd/tests/integration_tests/api/program_uxd/instructions/process_exchange_liquidity_with_credix_lp_depository.rs @@ -0,0 +1,211 @@ +use anchor_lang::InstructionData; +use anchor_lang::ToAccountMetas; +use solana_sdk::instruction::Instruction; +use solana_sdk::pubkey::Pubkey; +use solana_sdk::signature::Keypair; +use solana_sdk::signer::Signer; +use spl_token::state::Account; + +use uxd::state::CredixLpDepository; +use uxd::state::IdentityDepository; + +use crate::integration_tests::api::program_context; +use crate::integration_tests::api::program_credix; +use crate::integration_tests::api::program_uxd; + +#[allow(clippy::too_many_arguments)] +pub async fn process_exchange_liquidity_with_credix_lp_depository( + program_context: &mut Box, + payer: &Keypair, + collateral_mint: &Pubkey, + user: &Keypair, + user_collateral: &Pubkey, + receiver_credix_shares: &Pubkey, + collateral_amount: u64, +) -> Result<(), program_context::ProgramError> { + // Find needed accounts + let controller = program_uxd::accounts::find_controller_pda().0; + + let identity_depository = program_uxd::accounts::find_identity_depository_pda().0; + let identity_depository_collateral = + program_uxd::accounts::find_identity_depository_collateral_vault_pda().0; + + let credix_market_seeds = program_credix::accounts::find_market_seeds(); + let credix_global_market_state = + program_credix::accounts::find_global_market_state_pda(&credix_market_seeds).0; + let credix_lp_depository = program_uxd::accounts::find_credix_lp_depository_pda( + collateral_mint, + &credix_global_market_state, + ) + .0; + let credix_shares_mint = + program_credix::accounts::find_lp_token_mint_pda(&credix_market_seeds).0; + let credix_lp_depository_shares = program_uxd::accounts::find_credix_lp_depository_shares( + &credix_lp_depository, + &credix_shares_mint, + ); + + // Read state before + let identity_depository_before = program_context::read_account_anchor::( + program_context, + &identity_depository, + ) + .await?; + let credix_lp_depository_before = program_context::read_account_anchor::( + program_context, + &credix_lp_depository, + ) + .await?; + + let identity_depository_collateral_amount_before = + program_context::read_account_packed::( + program_context, + &identity_depository_collateral, + ) + .await? + .amount; + let credix_lp_depository_shares_amount_before = + program_context::read_account_packed::( + program_context, + &credix_lp_depository_shares, + ) + .await? + .amount; + let user_collateral_amount_before = + program_context::read_account_packed::(program_context, user_collateral) + .await? + .amount; + let receiver_credix_shares_amount_before = + program_context::read_account_packed::(program_context, receiver_credix_shares) + .await? + .amount; + + // Execute IX + let accounts = uxd::accounts::ExchangeLiquidityWithCredixLpDepository { + payer: payer.pubkey(), + controller, + identity_depository, + identity_depository_collateral, + credix_lp_depository, + credix_lp_depository_shares, + collateral_mint: *collateral_mint, + credix_shares_mint, + user: user.pubkey(), + user_collateral: *user_collateral, + receiver_credix_shares: *receiver_credix_shares, + system_program: solana_sdk::system_program::ID, + token_program: anchor_spl::token::ID, + }; + let payload = uxd::instruction::ExchangeLiquidityWithCredixLpDepository { collateral_amount }; + let instruction = Instruction { + program_id: uxd::id(), + accounts: accounts.to_account_metas(None), + data: payload.data(), + }; + program_context::process_instruction_with_signers(program_context, instruction, payer, &[user]) + .await?; + + // Read state after + let identity_depository_after = program_context::read_account_anchor::( + program_context, + &identity_depository, + ) + .await?; + let credix_lp_depository_after = program_context::read_account_anchor::( + program_context, + &credix_lp_depository, + ) + .await?; + + let identity_depository_collateral_amount_after = + program_context::read_account_packed::( + program_context, + &identity_depository_collateral, + ) + .await? + .amount; + let credix_lp_depository_shares_amount_after = program_context::read_account_packed::( + program_context, + &credix_lp_depository_shares, + ) + .await? + .amount; + let user_collateral_amount_after = + program_context::read_account_packed::(program_context, user_collateral) + .await? + .amount; + let receiver_credix_shares_amount_after = + program_context::read_account_packed::(program_context, receiver_credix_shares) + .await? + .amount; + + // credix_lp_depository.redeemable_amount_under_management must have decreased by the exchanged amount + let credix_lp_depository_redeemable_amount_under_management_before = + u64::try_from(credix_lp_depository_before.redeemable_amount_under_management).unwrap(); + let credix_lp_depository_redeemable_amount_under_management_after = + u64::try_from(credix_lp_depository_after.redeemable_amount_under_management).unwrap(); + assert_eq!( + credix_lp_depository_redeemable_amount_under_management_before - collateral_amount, + credix_lp_depository_redeemable_amount_under_management_after, + ); + // credix_lp_depository.collateral_amount_deposited must have decreased by the exchanged amount + let credix_lp_depository_collateral_amount_deposited_before = + u64::try_from(credix_lp_depository_before.collateral_amount_deposited).unwrap(); + let credix_lp_depository_collateral_amount_deposited_after = + u64::try_from(credix_lp_depository_after.collateral_amount_deposited).unwrap(); + assert_eq!( + credix_lp_depository_collateral_amount_deposited_before - collateral_amount, + credix_lp_depository_collateral_amount_deposited_after, + ); + + // identity_depository.redeemable_amount_under_management must have increased by the exchanged amount + let identity_depository_redeemable_amount_under_management_before = + u64::try_from(identity_depository_before.redeemable_amount_under_management).unwrap(); + let identity_depository_redeemable_amount_under_management_after = + u64::try_from(identity_depository_after.redeemable_amount_under_management).unwrap(); + assert_eq!( + identity_depository_redeemable_amount_under_management_before + collateral_amount, + identity_depository_redeemable_amount_under_management_after, + ); + // identity_depository.collateral_amount_deposited must have increased by the exchanged amount + let identity_depository_collateral_amount_deposited_before = + u64::try_from(identity_depository_before.collateral_amount_deposited).unwrap(); + let identity_depository_collateral_amount_deposited_after = + u64::try_from(identity_depository_after.collateral_amount_deposited).unwrap(); + assert_eq!( + identity_depository_collateral_amount_deposited_before + collateral_amount, + identity_depository_collateral_amount_deposited_after, + ); + + // identity_depository_collateral.amount must have increased by the exchanged amount + assert_eq!( + identity_depository_collateral_amount_before + collateral_amount, + identity_depository_collateral_amount_after, + ); + // user_collateral.amount must have decreased by the exchanged amount + assert_eq!( + user_collateral_amount_before - collateral_amount, + user_collateral_amount_after, + ); + + // Expected transacted shares amount + let exchanged_shares_amount = u64::try_from( + u128::from(credix_lp_depository_shares_amount_before) * u128::from(collateral_amount) + / credix_lp_depository_before.redeemable_amount_under_management, + ) + .unwrap(); + + // credix_lp_depository_shares.amount must have decreased by the computed shares amount + assert_eq!( + credix_lp_depository_shares_amount_before - exchanged_shares_amount, + credix_lp_depository_shares_amount_after, + ); + // receiver_credix_shares.amount must have increased by the computed shares amount + assert_eq!( + receiver_credix_shares_amount_before + exchanged_shares_amount, + receiver_credix_shares_amount_after, + ); + + // Done + Ok(()) +} diff --git a/programs/uxd/tests/integration_tests/suites/mod.rs b/programs/uxd/tests/integration_tests/suites/mod.rs index b0a505593..bd4da065c 100644 --- a/programs/uxd/tests/integration_tests/suites/mod.rs +++ b/programs/uxd/tests/integration_tests/suites/mod.rs @@ -1,5 +1,6 @@ pub mod test_controller_edit; pub mod test_credix_lp_depository_edit; +pub mod test_credix_lp_depository_exchange_liquidity; pub mod test_credix_lp_depository_mint; pub mod test_credix_lp_depository_rebalance_illiquid; pub mod test_credix_lp_depository_rebalance_liquid; diff --git a/programs/uxd/tests/integration_tests/suites/test_credix_lp_depository_exchange_liquidity.rs b/programs/uxd/tests/integration_tests/suites/test_credix_lp_depository_exchange_liquidity.rs new file mode 100644 index 000000000..793f056f2 --- /dev/null +++ b/programs/uxd/tests/integration_tests/suites/test_credix_lp_depository_exchange_liquidity.rs @@ -0,0 +1,300 @@ +use solana_program_test::tokio; +use solana_sdk::signer::keypair::Keypair; +use solana_sdk::signer::Signer; + +use uxd::instructions::EditControllerFields; +use uxd::instructions::EditCredixLpDepositoryFields; +use uxd::instructions::EditDepositoriesRoutingWeightBps; +use uxd::instructions::EditIdentityDepositoryFields; +use uxd::instructions::EditMercurialVaultDepositoryFields; + +use crate::integration_tests::api::program_context; +use crate::integration_tests::api::program_credix; +use crate::integration_tests::api::program_spl; +use crate::integration_tests::api::program_uxd; +use crate::integration_tests::utils::ui_amount_to_native_amount; + +#[tokio::test] +async fn test_credix_lp_depository_exchange_liquidity() -> Result<(), program_context::ProgramError> +{ + // --------------------------------------------------------------------- + // -- Phase 1 + // -- Setup basic context and accounts needed for this test suite + // --------------------------------------------------------------------- + + let mut program_context: Box = + Box::new(program_context::create_program_test_context().await); + + // Fund payer + let payer = Keypair::new(); + program_context + .process_airdrop(&payer.pubkey(), 1_000_000_000_000) + .await?; + + // Hardcode mints decimals + let collateral_mint_decimals = 6; + let redeemable_mint_decimals = 6; + + // Important account keys + let authority = Keypair::new(); + let collateral_mint = Keypair::new(); + let mercurial_vault_lp_mint = Keypair::new(); + let credix_multisig = Keypair::new(); + + // Initialize basic UXD program state + program_uxd::procedures::process_deploy_program( + &mut program_context, + &payer, + &authority, + &collateral_mint, + &mercurial_vault_lp_mint, + &credix_multisig, + collateral_mint_decimals, + redeemable_mint_decimals, + ) + .await?; + + // Main actor + let user = Keypair::new(); + let profits_beneficiary = Keypair::new(); + + // Create a collateral account for our user + let user_collateral = program_spl::instructions::process_associated_token_account_get_or_init( + &mut program_context, + &payer, + &collateral_mint.pubkey(), + &user.pubkey(), + ) + .await?; + // Create a redeemable account for our user + let user_redeemable = program_spl::instructions::process_associated_token_account_get_or_init( + &mut program_context, + &payer, + &program_uxd::accounts::find_redeemable_mint_pda().0, + &user.pubkey(), + ) + .await?; + + // Create a collateral account for our profits_beneficiary + let profits_beneficiary_collateral = + program_spl::instructions::process_associated_token_account_get_or_init( + &mut program_context, + &payer, + &collateral_mint.pubkey(), + &profits_beneficiary.pubkey(), + ) + .await?; + + // Useful amounts used during testing scenario + let amount_we_use_as_supply_cap = + ui_amount_to_native_amount(50_000_000, redeemable_mint_decimals); + + let amount_of_collateral_airdropped_to_user = + ui_amount_to_native_amount(1_000_000_000, collateral_mint_decimals); + let amount_the_user_should_be_able_to_mint = + ui_amount_to_native_amount(50_000_000, collateral_mint_decimals); + + // --------------------------------------------------------------------- + // -- Phase 2 + // -- Prepare the program state to be ready, + // -- Set all depository caps for proper target computation + // -- Mint a bunch of redeemable to fill up all depositories + // --------------------------------------------------------------------- + + // Airdrop collateral to our user + program_spl::instructions::process_token_mint_to( + &mut program_context, + &payer, + &collateral_mint.pubkey(), + &collateral_mint, + &user_collateral, + amount_of_collateral_airdropped_to_user, + ) + .await?; + + // Set the controller cap and the weights + program_uxd::instructions::process_edit_controller( + &mut program_context, + &payer, + &authority, + &EditControllerFields { + redeemable_global_supply_cap: Some(amount_we_use_as_supply_cap.into()), + depositories_routing_weight_bps: Some(EditDepositoriesRoutingWeightBps { + identity_depository_weight_bps: 50 * 100, + mercurial_vault_depository_weight_bps: 25 * 100, + credix_lp_depository_weight_bps: 25 * 100, + }), + router_depositories: None, + outflow_limit_per_epoch_amount: None, + outflow_limit_per_epoch_bps: None, + slots_per_epoch: None, + }, + ) + .await?; + + // Now we set the router depositories to the correct PDAs + program_uxd::procedures::process_set_router_depositories( + &mut program_context, + &payer, + &authority, + &collateral_mint.pubkey(), + ) + .await?; + + // Set the identity_depository cap and make sure minting is not disabled + program_uxd::instructions::process_edit_identity_depository( + &mut program_context, + &payer, + &authority, + &EditIdentityDepositoryFields { + redeemable_amount_under_management_cap: Some(amount_we_use_as_supply_cap.into()), + minting_disabled: Some(false), + }, + ) + .await?; + + // Set the mercurial_vault_depository cap and make sure minting is not disabled + program_uxd::instructions::process_edit_mercurial_vault_depository( + &mut program_context, + &payer, + &authority, + &collateral_mint.pubkey(), + &EditMercurialVaultDepositoryFields { + redeemable_amount_under_management_cap: Some(amount_we_use_as_supply_cap.into()), + minting_fee_in_bps: Some(0), + redeeming_fee_in_bps: Some(0), + minting_disabled: Some(false), + profits_beneficiary_collateral: Some(profits_beneficiary_collateral), + }, + ) + .await?; + + // Set the credix_lp_depository cap and make sure minting is not disabled + program_uxd::instructions::process_edit_credix_lp_depository( + &mut program_context, + &payer, + &authority, + &collateral_mint.pubkey(), + &EditCredixLpDepositoryFields { + redeemable_amount_under_management_cap: Some(amount_we_use_as_supply_cap.into()), + minting_fee_in_bps: Some(0), + redeeming_fee_in_bps: Some(0), + minting_disabled: Some(false), + profits_beneficiary_collateral: Some(profits_beneficiary_collateral), + }, + ) + .await?; + + // Minted amounts + let identity_depository_collateral_amount_minted = amount_the_user_should_be_able_to_mint / 2; // identity_depository 50% weight + let mercurial_vault_depository_collateral_amount_minted = + amount_the_user_should_be_able_to_mint / 4; // mercurial_vault_depository 25% weight + let credix_lp_depository_collateral_amount_minted = amount_the_user_should_be_able_to_mint / 4; // credix_lp_depository 25% weight + + // Minting on should work now that everything is set + program_uxd::instructions::process_mint( + &mut program_context, + &payer, + &collateral_mint.pubkey(), + &mercurial_vault_lp_mint.pubkey(), + &user, + &user_collateral, + &user_redeemable, + amount_the_user_should_be_able_to_mint, + identity_depository_collateral_amount_minted, + mercurial_vault_depository_collateral_amount_minted, + credix_lp_depository_collateral_amount_minted, + ) + .await?; + + // --------------------------------------------------------------------- + // -- Phase 3 + // -- User will now trade USDC for all the liquidity in the credix_lp_depository + // -- User will send the credix shares to an external wallet's account + // --------------------------------------------------------------------- + + // Resolve credix's important PDAs + let credix_market_seeds = program_credix::accounts::find_market_seeds(); + let credix_global_market_state = + program_credix::accounts::find_global_market_state_pda(&credix_market_seeds).0; + let credix_lp_depository = program_uxd::accounts::find_credix_lp_depository_pda( + &collateral_mint.pubkey(), + &credix_global_market_state, + ) + .0; + let credix_shares_mint = + program_credix::accounts::find_lp_token_mint_pda(&credix_market_seeds).0; + let credix_lp_depository_shares = program_uxd::accounts::find_credix_lp_depository_shares( + &credix_lp_depository, + &credix_shares_mint, + ); + + // Create receiver's shares ATA + let receiver = Keypair::new(); + let receiver_credix_shares = + program_spl::instructions::process_associated_token_account_get_or_init( + &mut program_context, + &payer, + &credix_shares_mint, + &receiver.pubkey(), + ) + .await?; + + // Thaw the accounts involved in the exchange + program_credix::instructions::process_thaw_freeze_token_account( + &mut program_context, + &credix_multisig, + &credix_lp_depository_shares, + false, + ) + .await?; + program_credix::instructions::process_thaw_freeze_token_account( + &mut program_context, + &credix_multisig, + &receiver_credix_shares, + false, + ) + .await?; + + // Exchanging 0 should fail + assert!( + program_uxd::instructions::process_exchange_liquidity_with_credix_lp_depository( + &mut program_context, + &payer, + &collateral_mint.pubkey(), + &user, + &user_collateral, + &receiver_credix_shares, + 0, + ) + .await + .is_err() + ); + + // Proceed to the exchange in 2 separate partial transaction + let credix_lp_depository_redeemable_amount_under_management = + credix_lp_depository_collateral_amount_minted - 1; // precision-loss + program_uxd::instructions::process_exchange_liquidity_with_credix_lp_depository( + &mut program_context, + &payer, + &collateral_mint.pubkey(), + &user, + &user_collateral, + &receiver_credix_shares, + credix_lp_depository_redeemable_amount_under_management / 2, + ) + .await?; + program_uxd::instructions::process_exchange_liquidity_with_credix_lp_depository( + &mut program_context, + &payer, + &collateral_mint.pubkey(), + &user, + &user_collateral, + &receiver_credix_shares, + credix_lp_depository_redeemable_amount_under_management / 2, + ) + .await?; + + // Done + Ok(()) +} diff --git a/programs/uxd/tests/integration_tests/suites/test_ensure_devnet.rs b/programs/uxd/tests/integration_tests/suites/test_ensure_devnet.rs index 547025e18..9e1f13c14 100644 --- a/programs/uxd/tests/integration_tests/suites/test_ensure_devnet.rs +++ b/programs/uxd/tests/integration_tests/suites/test_ensure_devnet.rs @@ -297,7 +297,7 @@ async fn test_ensure_devnet() -> Result<(), program_context::ProgramError> { .await?; // --------------------------------------------------------------------- - // -- Check that all mints work + // -- Check that all mints/redeen work // --------------------------------------------------------------------- program_uxd::instructions::process_mint_with_identity_depository( diff --git a/target/idl/uxd.json b/target/idl/uxd.json index 1f92df7d7..ec4f5613b 100644 --- a/target/idl/uxd.json +++ b/target/idl/uxd.json @@ -1,5 +1,5 @@ { - "version": "8.2.0", + "version": "8.3.0", "name": "uxd", "instructions": [ { @@ -1744,6 +1744,95 @@ ], "args": [] }, + { + "name": "exchangeLiquidityWithCredixLpDepository", + "accounts": [ + { + "name": "payer", + "isMut": true, + "isSigner": true, + "docs": ["#1"] + }, + { + "name": "user", + "isMut": false, + "isSigner": true, + "docs": ["#2"] + }, + { + "name": "controller", + "isMut": true, + "isSigner": false, + "docs": ["#3"] + }, + { + "name": "identityDepository", + "isMut": true, + "isSigner": false, + "docs": ["#4"] + }, + { + "name": "identityDepositoryCollateral", + "isMut": true, + "isSigner": false, + "docs": ["#5"] + }, + { + "name": "credixLpDepository", + "isMut": true, + "isSigner": false, + "docs": ["#6"] + }, + { + "name": "credixLpDepositoryShares", + "isMut": true, + "isSigner": false, + "docs": ["#7"] + }, + { + "name": "userCollateral", + "isMut": true, + "isSigner": false, + "docs": ["#8"] + }, + { + "name": "receiverCredixShares", + "isMut": true, + "isSigner": false, + "docs": ["#9"] + }, + { + "name": "collateralMint", + "isMut": false, + "isSigner": false, + "docs": ["#10"] + }, + { + "name": "credixSharesMint", + "isMut": false, + "isSigner": false, + "docs": ["#11"] + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false, + "docs": ["#12"] + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false, + "docs": ["#13"] + } + ], + "args": [ + { + "name": "collateralAmount", + "type": "u64" + } + ] + }, { "name": "rebalanceCreateWithdrawRequestFromCredixLpDepository", "accounts": [ @@ -2100,29 +2189,9 @@ { "name": "unused4", "type": { - "array": ["u8", 8] + "array": ["u8", 266] } }, - { - "name": "registeredMercurialVaultDepositories", - "type": { - "array": ["publicKey", 4] - } - }, - { - "name": "registeredMercurialVaultDepositoriesCount", - "type": "u8" - }, - { - "name": "registeredCredixLpDepositories", - "type": { - "array": ["publicKey", 4] - } - }, - { - "name": "registeredCredixLpDepositoriesCount", - "type": "u8" - }, { "name": "profitsTotalCollected", "type": "u128" @@ -3200,6 +3269,41 @@ } ] }, + { + "name": "ExchangeLiquidityWithCredixLpDepositoryEvent", + "fields": [ + { + "name": "controllerVersion", + "type": "u8", + "index": true + }, + { + "name": "depositoryVersion", + "type": "u8", + "index": true + }, + { + "name": "controller", + "type": "publicKey", + "index": true + }, + { + "name": "depository", + "type": "publicKey", + "index": true + }, + { + "name": "collateralAmount", + "type": "u64", + "index": false + }, + { + "name": "sharesAmount", + "type": "u64", + "index": false + } + ] + }, { "name": "RebalanceCreateWithdrawRequestFromCredixLpDepositoryEvent", "fields": [ @@ -3500,7 +3604,7 @@ { "code": 6033, "name": "InvalidDepository", - "msg": "The Depository provided is not registered with the Controller." + "msg": "The Depository provided is not matching the one stored in the Controller." }, { "code": 6034, diff --git a/target/types/uxd.ts b/target/types/uxd.ts index a62e088fb..97c46f255 100644 --- a/target/types/uxd.ts +++ b/target/types/uxd.ts @@ -1,5 +1,5 @@ export type Uxd = { - version: '8.2.0'; + version: '8.3.0'; name: 'uxd'; instructions: [ { @@ -1742,6 +1742,95 @@ export type Uxd = { ]; args: []; }, + { + name: 'exchangeLiquidityWithCredixLpDepository'; + accounts: [ + { + name: 'payer'; + isMut: true; + isSigner: true; + docs: ['#1']; + }, + { + name: 'user'; + isMut: false; + isSigner: true; + docs: ['#2']; + }, + { + name: 'controller'; + isMut: true; + isSigner: false; + docs: ['#3']; + }, + { + name: 'identityDepository'; + isMut: true; + isSigner: false; + docs: ['#4']; + }, + { + name: 'identityDepositoryCollateral'; + isMut: true; + isSigner: false; + docs: ['#5']; + }, + { + name: 'credixLpDepository'; + isMut: true; + isSigner: false; + docs: ['#6']; + }, + { + name: 'credixLpDepositoryShares'; + isMut: true; + isSigner: false; + docs: ['#7']; + }, + { + name: 'userCollateral'; + isMut: true; + isSigner: false; + docs: ['#8']; + }, + { + name: 'receiverCredixShares'; + isMut: true; + isSigner: false; + docs: ['#9']; + }, + { + name: 'collateralMint'; + isMut: false; + isSigner: false; + docs: ['#10']; + }, + { + name: 'credixSharesMint'; + isMut: false; + isSigner: false; + docs: ['#11']; + }, + { + name: 'systemProgram'; + isMut: false; + isSigner: false; + docs: ['#12']; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + docs: ['#13']; + } + ]; + args: [ + { + name: 'collateralAmount'; + type: 'u64'; + } + ]; + }, { name: 'rebalanceCreateWithdrawRequestFromCredixLpDepository'; accounts: [ @@ -2098,29 +2187,9 @@ export type Uxd = { { name: 'unused4'; type: { - array: ['u8', 8]; + array: ['u8', 266]; }; }, - { - name: 'registeredMercurialVaultDepositories'; - type: { - array: ['publicKey', 4]; - }; - }, - { - name: 'registeredMercurialVaultDepositoriesCount'; - type: 'u8'; - }, - { - name: 'registeredCredixLpDepositories'; - type: { - array: ['publicKey', 4]; - }; - }, - { - name: 'registeredCredixLpDepositoriesCount'; - type: 'u8'; - }, { name: 'profitsTotalCollected'; type: 'u128'; @@ -3198,6 +3267,41 @@ export type Uxd = { } ]; }, + { + name: 'ExchangeLiquidityWithCredixLpDepositoryEvent'; + fields: [ + { + name: 'controllerVersion'; + type: 'u8'; + index: true; + }, + { + name: 'depositoryVersion'; + type: 'u8'; + index: true; + }, + { + name: 'controller'; + type: 'publicKey'; + index: true; + }, + { + name: 'depository'; + type: 'publicKey'; + index: true; + }, + { + name: 'collateralAmount'; + type: 'u64'; + index: false; + }, + { + name: 'sharesAmount'; + type: 'u64'; + index: false; + } + ]; + }, { name: 'RebalanceCreateWithdrawRequestFromCredixLpDepositoryEvent'; fields: [ @@ -3498,7 +3602,7 @@ export type Uxd = { { code: 6033; name: 'InvalidDepository'; - msg: 'The Depository provided is not registered with the Controller.'; + msg: 'The Depository provided is not matching the one stored in the Controller.'; }, { code: 6034; @@ -3629,7 +3733,7 @@ export type Uxd = { }; export const IDL: Uxd = { - version: '8.2.0', + version: '8.3.0', name: 'uxd', instructions: [ { @@ -5372,6 +5476,95 @@ export const IDL: Uxd = { ], args: [], }, + { + name: 'exchangeLiquidityWithCredixLpDepository', + accounts: [ + { + name: 'payer', + isMut: true, + isSigner: true, + docs: ['#1'], + }, + { + name: 'user', + isMut: false, + isSigner: true, + docs: ['#2'], + }, + { + name: 'controller', + isMut: true, + isSigner: false, + docs: ['#3'], + }, + { + name: 'identityDepository', + isMut: true, + isSigner: false, + docs: ['#4'], + }, + { + name: 'identityDepositoryCollateral', + isMut: true, + isSigner: false, + docs: ['#5'], + }, + { + name: 'credixLpDepository', + isMut: true, + isSigner: false, + docs: ['#6'], + }, + { + name: 'credixLpDepositoryShares', + isMut: true, + isSigner: false, + docs: ['#7'], + }, + { + name: 'userCollateral', + isMut: true, + isSigner: false, + docs: ['#8'], + }, + { + name: 'receiverCredixShares', + isMut: true, + isSigner: false, + docs: ['#9'], + }, + { + name: 'collateralMint', + isMut: false, + isSigner: false, + docs: ['#10'], + }, + { + name: 'credixSharesMint', + isMut: false, + isSigner: false, + docs: ['#11'], + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + docs: ['#12'], + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + docs: ['#13'], + }, + ], + args: [ + { + name: 'collateralAmount', + type: 'u64', + }, + ], + }, { name: 'rebalanceCreateWithdrawRequestFromCredixLpDepository', accounts: [ @@ -5728,29 +5921,9 @@ export const IDL: Uxd = { { name: 'unused4', type: { - array: ['u8', 8], + array: ['u8', 266], }, }, - { - name: 'registeredMercurialVaultDepositories', - type: { - array: ['publicKey', 4], - }, - }, - { - name: 'registeredMercurialVaultDepositoriesCount', - type: 'u8', - }, - { - name: 'registeredCredixLpDepositories', - type: { - array: ['publicKey', 4], - }, - }, - { - name: 'registeredCredixLpDepositoriesCount', - type: 'u8', - }, { name: 'profitsTotalCollected', type: 'u128', @@ -6828,6 +7001,41 @@ export const IDL: Uxd = { }, ], }, + { + name: 'ExchangeLiquidityWithCredixLpDepositoryEvent', + fields: [ + { + name: 'controllerVersion', + type: 'u8', + index: true, + }, + { + name: 'depositoryVersion', + type: 'u8', + index: true, + }, + { + name: 'controller', + type: 'publicKey', + index: true, + }, + { + name: 'depository', + type: 'publicKey', + index: true, + }, + { + name: 'collateralAmount', + type: 'u64', + index: false, + }, + { + name: 'sharesAmount', + type: 'u64', + index: false, + }, + ], + }, { name: 'RebalanceCreateWithdrawRequestFromCredixLpDepositoryEvent', fields: [ @@ -7128,7 +7336,7 @@ export const IDL: Uxd = { { code: 6033, name: 'InvalidDepository', - msg: 'The Depository provided is not registered with the Controller.', + msg: 'The Depository provided is not matching the one stored in the Controller.', }, { code: 6034,