lez-programs/amm/src/sync.rs
Ricardo Guilherme Schmidt e61cd594b5 feat(amm): add SyncReserves instruction
Adds a new `SyncReserves` instruction that updates a pool's recorded
reserves to match the actual vault balances. This allows the pool to
absorb donations (direct token transfers to vaults) without breaking
the invariant — only upward adjustments are permitted; vaults may
not be under-collateralized relative to reserves.

Vault reading helpers (`read_fungible_holding`,
`read_vault_fungible_balances`) are implemented in `amm_core` so they
can be shared across instructions without crossing crate boundaries.
2026-04-09 14:48:35 +02:00

53 lines
1.6 KiB
Rust

use amm_core::{read_vault_fungible_balances, PoolDefinition};
use nssa_core::{
account::{AccountWithMetadata, Data},
program::{AccountPostState, ChainedCall},
};
pub fn sync_reserves(
pool: AccountWithMetadata,
vault_a: AccountWithMetadata,
vault_b: AccountWithMetadata,
) -> (Vec<AccountPostState>, Vec<ChainedCall>) {
let pool_def_data = PoolDefinition::try_from(&pool.account.data)
.expect("Sync reserves: AMM Program expects a valid Pool Definition Account");
assert!(pool_def_data.active, "Pool is inactive");
assert_eq!(
vault_a.account_id, pool_def_data.vault_a_id,
"Vault A was not provided"
);
assert_eq!(
vault_b.account_id, pool_def_data.vault_b_id,
"Vault B was not provided"
);
let (vault_a_balance, vault_b_balance) =
read_vault_fungible_balances("Sync reserves", &vault_a, &vault_b);
assert!(
vault_a_balance >= pool_def_data.reserve_a,
"Sync reserves: vault A balance is less than its reserve"
);
assert!(
vault_b_balance >= pool_def_data.reserve_b,
"Sync reserves: vault B balance is less than its reserve"
);
let mut pool_post = pool.account.clone();
let pool_post_definition = PoolDefinition {
reserve_a: vault_a_balance,
reserve_b: vault_b_balance,
..pool_def_data
};
pool_post.data = Data::from(&pool_post_definition);
(
vec![
AccountPostState::new(pool_post),
AccountPostState::new(vault_a.account.clone()),
AccountPostState::new(vault_b.account.clone()),
],
Vec::new(),
)
}