Skip to content

Instantly share code, notes, and snippets.

@dicethedev
Created June 3, 2026 15:52
Show Gist options
  • Select an option

  • Save dicethedev/b1c2a4f78b7d9a99f0147fda1dc50fac to your computer and use it in GitHub Desktop.

Select an option

Save dicethedev/b1c2a4f78b7d9a99f0147fda1dc50fac to your computer and use it in GitHub Desktop.
Prop AMM curve using virtual liquidity, side-aware inventory fees, and bounded spreads to improve retail routing while protecting against inventory-worsening flow.
use pinocchio::{account_info::AccountInfo, entrypoint, pubkey::Pubkey, ProgramResult};
use prop_amm_submission_sdk::{set_return_data_bytes, set_return_data_u64};
const NAME: &str = "Noise Tail Guard";
const MODEL_USED: &str = "None";
const STORAGE_SIZE: usize = 1024;
const SCALE_BPS: u128 = 10_000;
const BASE_FEE_BPS: u128 = 64;
const MIN_FEE_BPS: u128 = 36;
const MAX_FEE_BPS: u128 = 205;
const RISK_IMBALANCE_WEIGHT: u128 = 145;
const HELP_IMBALANCE_DISCOUNT: u128 = 40;
#[cfg(not(feature = "no-entrypoint"))]
entrypoint!(process_instruction);
pub fn process_instruction(
_program_id: &Pubkey,
_accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
if instruction_data.is_empty() {
return Ok(());
}
match instruction_data[0] {
0 | 1 => {
let output = compute_swap(instruction_data);
set_return_data_u64(output);
}
2 => {
// Keep this version stateless. The quote function adapts from reserves and side,
// which keeps validation simple and avoids relying on platform-specific storage helpers.
}
3 => set_return_data_bytes(NAME.as_bytes()),
4 => set_return_data_bytes(get_model_used().as_bytes()),
_ => {}
}
Ok(())
}
pub fn get_model_used() -> &'static str {
MODEL_USED
}
pub fn compute_swap(data: &[u8]) -> u64 {
if data.len() < 25 {
return 0;
}
let side = data[0];
let input = read_u64(data, 1) as u128;
let reserve_x = read_u64(data, 9) as u128;
let reserve_y = read_u64(data, 17) as u128;
if input == 0 || reserve_x == 0 || reserve_y == 0 {
return 0;
}
match side {
0 => quote_buy_x(input, reserve_x, reserve_y) as u64,
1 => quote_sell_x(input, reserve_x, reserve_y) as u64,
_ => 0,
}
}
fn quote_buy_x(input_y: u128, reserve_x: u128, reserve_y: u128) -> u128 {
let fee_bps = dynamic_fee_bps(0, reserve_x, reserve_y);
let net_y = input_y.saturating_mul(SCALE_BPS - fee_bps) / SCALE_BPS;
constant_product_out(net_y, reserve_y, reserve_x)
}
fn quote_sell_x(input_x: u128, reserve_x: u128, reserve_y: u128) -> u128 {
let fee_bps = dynamic_fee_bps(1, reserve_x, reserve_y);
let net_x = input_x.saturating_mul(SCALE_BPS - fee_bps) / SCALE_BPS;
constant_product_out(net_x, reserve_x, reserve_y)
}
fn constant_product_out(net_input: u128, reserve_in: u128, reserve_out: u128) -> u128 {
if net_input == 0 || reserve_in == 0 || reserve_out == 0 {
return 0;
}
let k = reserve_in.saturating_mul(reserve_out);
let new_reserve_in = reserve_in.saturating_add(net_input);
reserve_out.saturating_sub(div_ceil(k, new_reserve_in))
}
fn dynamic_fee_bps(side: u8, reserve_x: u128, reserve_y: u128) -> u128 {
let imbalance_bps = reserve_imbalance_bps(reserve_x, reserve_y);
let mut fee = BASE_FEE_BPS;
if trade_worsens_inventory(side, reserve_x, reserve_y) {
fee = fee.saturating_add(imbalance_bps.saturating_mul(RISK_IMBALANCE_WEIGHT) / SCALE_BPS);
} else {
fee = fee.saturating_sub(imbalance_bps.saturating_mul(HELP_IMBALANCE_DISCOUNT) / SCALE_BPS);
}
clamp(fee, MIN_FEE_BPS, MAX_FEE_BPS)
}
fn trade_worsens_inventory(side: u8, reserve_x: u128, reserve_y: u128) -> bool {
if reserve_x == reserve_y {
return false;
}
match side {
// Trader buys X: reserve X decreases and reserve Y increases.
0 => reserve_x < reserve_y,
// Trader sells X: reserve X increases and reserve Y decreases.
1 => reserve_x > reserve_y,
_ => true,
}
}
fn reserve_imbalance_bps(reserve_x: u128, reserve_y: u128) -> u128 {
let total = reserve_x.saturating_add(reserve_y);
if total == 0 {
return 0;
}
let diff = if reserve_x > reserve_y {
reserve_x - reserve_y
} else {
reserve_y - reserve_x
};
let imbalance = diff.saturating_mul(SCALE_BPS) / total;
if imbalance > SCALE_BPS {
SCALE_BPS
} else {
imbalance
}
}
fn div_ceil(numerator: u128, denominator: u128) -> u128 {
if denominator == 0 {
return 0;
}
numerator.saturating_add(denominator - 1) / denominator
}
fn clamp(value: u128, min: u128, max: u128) -> u128 {
if value < min {
min
} else if value > max {
max
} else {
value
}
}
fn read_u64(data: &[u8], offset: usize) -> u64 {
let mut bytes = [0u8; 8];
bytes.copy_from_slice(&data[offset..offset + 8]);
u64::from_le_bytes(bytes)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment