diff --git a/modules/amm/ffi/src/api/liquidity.rs b/modules/amm/ffi/src/api/liquidity.rs index dd66126..61010d0 100644 --- a/modules/amm/ffi/src/api/liquidity.rs +++ b/modules/amm/ffi/src/api/liquidity.rs @@ -12,7 +12,8 @@ //! guest's `assert pool uninitialized`. use amm_core::{ - isqrt_product, mul_div_floor, spot_price_q64_64, PoolDefinition, MINIMUM_LIQUIDITY, + isqrt_product, mul_div_floor, spot_price_q64_64, PoolDefinition, FEE_BPS_DENOMINATOR, + MINIMUM_LIQUIDITY, }; use nssa_core::account::AccountId; use serde_json::{json, Value}; @@ -202,13 +203,14 @@ pub(super) fn create_pool_plan(request: CreatePoolPlanRequest) -> Result Result { let token_a = account_id_from_hex(&request.token_a_id, "token A id")?; let token_b = account_id_from_hex(&request.token_b_id, "token B id")?; @@ -217,6 +219,9 @@ pub(super) fn add_liquidity_quote(request: AddLiquidityQuoteRequest) -> Result= FEE_BPS_DENOMINATOR { + return Err(String::from("invalid_slippage")); + } // Decode the pool; absent / undecodable / empty ⇒ nothing to add to. let pool = hex::decode(&request.pool_data) @@ -258,6 +263,14 @@ pub(super) fn add_liquidity_quote(request: AddLiquidityQuoteRequest) -> Result Result() on a number_float THROWS, terminating the module), while a string / + // bool would otherwise fall through to a silent 0. A missing field defaults to 0 (no + // slippage). A negative or >= 100% value is likewise invalid_slippage. + const json slippage_val = request.value("slippageBps", json(0)); + if (!slippage_val.is_number_integer()) + return error("invalid_slippage"); + const int64_t slippage_bps = slippage_val.get(); + if (slippage_bps < 0 || slippage_bps >= 10000) + return error("invalid_slippage"); + const FfiResult quoteResult = call(amm_add_liquidity_quote, json{ {"tokenAId", token_a}, {"tokenBId", token_b}, {"maxAmountARaw", max_a_decimal}, {"maxAmountBRaw", max_b_decimal}, + {"slippageBps", slippage_bps}, {"poolData", pool_data}, }); if (!quoteResult.ok) return error(quoteResult.error.empty() ? "backend_error" : quoteResult.error); - // Success: wrap { amountARaw, amountBRaw, expectedLpRaw, priceRaw } in the envelope. + // Success: wrap { amountARaw, amountBRaw, expectedLpRaw, minimumLpRaw, priceRaw }. LogosMap out = quoteResult.value; out["status"] = "ok"; out["error"] = "";