From c41dd1ac5c681b5401989b19d999bf8095bce05d Mon Sep 17 00:00:00 2001 From: cliqueengagements <83251815+cliqueengagements@users.noreply.github.com> Date: Sat, 29 Aug 2026 13:29:51 +0000 Subject: [PATCH] fix(stacks-alpha-engine): a one sided HODLMM holding is not "deploy now" A wallet holding one side of a HODLMM pair is tiered `deploy_now` and given the pool's full APY with a daily dollar figure. It should be `swap_first`, and that figure is not achievable. `dlmm-core-v-1-1` holds the X asset only at bins at or above the active bin, and Y only at or below it, so both assets are valid together ONLY at the active bin. A deposit funded from one side lands outside it, which is outside the range where fees accrue, so the reported income is not received. Second issue in the same branch: the size comes from `Math.max(xUsd, yUsd)`, the larger side. A paired deposit can only be as large as the side that runs out first, so it is bounded by the smaller side, doubled. Observed on a wallet holding only STX: four pools offered as ready to deploy, at 604%, 366%, 185% and 4.4% APY, each carrying a daily figure. No behaviour change for a wallet holding both sides, or holding neither. Co-Authored-By: microbasilisk <272877828+microbasilisk@users.noreply.github.com> --- stacks-alpha-engine/stacks-alpha-engine.ts | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/stacks-alpha-engine/stacks-alpha-engine.ts b/stacks-alpha-engine/stacks-alpha-engine.ts index 75277f7d..28436ec4 100644 --- a/stacks-alpha-engine/stacks-alpha-engine.ts +++ b/stacks-alpha-engine/stacks-alpha-engine.ts @@ -805,11 +805,26 @@ async function getYieldOptions( let capUsd: number; let swapNote: string | null = null; - if (hasX || hasY) { + const xUsd = (balances as unknown as Record)[def.tokenX]?.usd ?? 0; + const yUsd = (balances as unknown as Record)[def.tokenY]?.usd ?? 0; + + if (hasX && hasY) { + // Both sides held. Bounded by the SMALLER side, doubled: a paired + // deposit can only be as large as the side that runs out first. tier = "deploy_now"; - const xUsd = (balances as unknown as Record)[def.tokenX]?.usd ?? 0; - const yUsd = (balances as unknown as Record)[def.tokenY]?.usd ?? 0; + capUsd = Math.min(xUsd, yUsd) * 2; + } else if (hasX || hasY) { + // One side only, and this is NOT deploy_now. + // + // dlmm-core-v-1-1 holds the X asset only at bins at or above the active + // bin, and Y only at or below it, so both assets are valid together + // ONLY at the active bin. A deposit funded from one side lands outside + // it, which is outside the range where fees accrue. Reporting the + // pool's APY and a daily figure against that describes income the + // depositor does not receive. + tier = "swap_first"; capUsd = Math.max(xUsd, yUsd); + swapNote = `Swap part of your ${hasX ? tokenXMeta.symbol : tokenYMeta.symbol} into ${hasX ? tokenYMeta.symbol : tokenXMeta.symbol} on Bitflow first`; } else { // Check if user has any token that could be swapped const totalUsd = balances.sbtc.usd + balances.stx.usd + balances.usdcx.usd + balances.usdh.usd + balances.aeusdc.usd;