From d3ca908d693c6dfb3dd721635b176366b31bf378 Mon Sep 17 00:00:00 2001 From: Sofio Date: Tue, 16 Dec 2025 07:35:35 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20LP=20=E6=B5=81?= =?UTF-8?q?=E5=8A=A8=E6=80=A7=E6=B1=A0=E8=BE=B9=E7=95=8C=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 LP 边界测试功能: - 添加流动性边界测试: - 添加金额为0 (InvalidAmount) - 添加超过代币余额 (InsufficientBalance) - 移除流动性边界测试: - 移除金额为0 (InvalidAmount) - 移除超过ytLP余额 (InsufficientBalance) - 移除时minOut过高 (InsufficientOutput) - 代币互换边界测试: - 互换金额为0 (InvalidAmount) - 相同代币互换 (SameToken) - 互换超过余额 (InsufficientBalance) UI功能: - 可折叠的边界测试区域 - 显示冷却时间和ytLP余额状态 - 中英文翻译支持 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- frontend/src/components/LPPanel.tsx | 199 ++++++++++++++++++++++++++++ frontend/src/i18n/locales/en.json | 19 ++- frontend/src/i18n/locales/zh.json | 19 ++- 3 files changed, 235 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/LPPanel.tsx b/frontend/src/components/LPPanel.tsx index e63f39a..b66277f 100644 --- a/frontend/src/components/LPPanel.tsx +++ b/frontend/src/components/LPPanel.tsx @@ -60,6 +60,7 @@ export function LPPanel() { slippage: '0.5', }) const [activeTab, setActiveTab] = useState<'add' | 'remove' | 'swap'>('add') + const [showBoundaryTest, setShowBoundaryTest] = useState(false) // Read pool data const { data: ytLPBalance, refetch: refetchBalance } = useReadContract({ @@ -295,6 +296,88 @@ export function LPPanel() { return token?.symbol || 'Unknown' } + // Boundary test function + const runBoundaryTest = (testType: string) => { + if (!address) return + recordTx('test', undefined, 'LP') + + switch (testType) { + case 'add_zero': + // 添加流动性金额为0 + writeContract({ + address: CONTRACTS.YT_REWARD_ROUTER, + abi: YT_REWARD_ROUTER_ABI, + functionName: 'addLiquidity', + args: [CONTRACTS.VAULTS.YT_A, BigInt(0), BigInt(0), BigInt(0)], + }) + break + case 'add_exceed_balance': + // 添加超过余额 + writeContract({ + address: CONTRACTS.YT_REWARD_ROUTER, + abi: YT_REWARD_ROUTER_ABI, + functionName: 'addLiquidity', + args: [CONTRACTS.VAULTS.YT_A, parseUnits('999999999', 18), BigInt(0), BigInt(0)], + }) + break + case 'remove_zero': + // 移除流动性金额为0 + writeContract({ + address: CONTRACTS.YT_REWARD_ROUTER, + abi: YT_REWARD_ROUTER_ABI, + functionName: 'removeLiquidity', + args: [CONTRACTS.VAULTS.YT_A, BigInt(0), BigInt(0), address], + }) + break + case 'remove_exceed_balance': + // 移除超过ytLP余额 + const exceedAmount = ytLPBalance ? ytLPBalance + parseUnits('999999', 18) : parseUnits('999999999', 18) + writeContract({ + address: CONTRACTS.YT_REWARD_ROUTER, + abi: YT_REWARD_ROUTER_ABI, + functionName: 'removeLiquidity', + args: [CONTRACTS.VAULTS.YT_A, exceedAmount, BigInt(0), address], + }) + break + case 'remove_high_minout': + // 移除时minOut过高 + writeContract({ + address: CONTRACTS.YT_REWARD_ROUTER, + abi: YT_REWARD_ROUTER_ABI, + functionName: 'removeLiquidity', + args: [CONTRACTS.VAULTS.YT_A, parseUnits('1', 18), parseUnits('999999999', 18), address], + }) + break + case 'swap_zero': + // 互换金额为0 + writeContract({ + address: CONTRACTS.YT_REWARD_ROUTER, + abi: YT_REWARD_ROUTER_ABI, + functionName: 'swapYT', + args: [CONTRACTS.VAULTS.YT_A, CONTRACTS.VAULTS.YT_B, BigInt(0), BigInt(0), address], + }) + break + case 'swap_same_token': + // 相同代币互换 + writeContract({ + address: CONTRACTS.YT_REWARD_ROUTER, + abi: YT_REWARD_ROUTER_ABI, + functionName: 'swapYT', + args: [CONTRACTS.VAULTS.YT_A, CONTRACTS.VAULTS.YT_A, parseUnits('1', 18), BigInt(0), address], + }) + break + case 'swap_exceed_balance': + // 互换超过余额 + writeContract({ + address: CONTRACTS.YT_REWARD_ROUTER, + abi: YT_REWARD_ROUTER_ABI, + functionName: 'swapYT', + args: [CONTRACTS.VAULTS.YT_A, CONTRACTS.VAULTS.YT_B, parseUnits('999999999', 18), BigInt(0), address], + }) + break + } + } + // Calculate cooldown remaining time const getCooldownRemaining = () => { if (!lastAddedAt || !cooldownDuration) return 0 @@ -615,6 +698,122 @@ export function LPPanel() { )} + {/* 边界测试区域 */} +
+
setShowBoundaryTest(!showBoundaryTest)} style={{ cursor: 'pointer' }}> +

{t('test.boundaryTests')} {showBoundaryTest ? '[-]' : '[+]'}

+
+ + {showBoundaryTest && ( + <> +
{t('lp.boundaryHint')}
+ + {/* 冷却时间状态 */} +
+ {t('lp.cooldownRemaining')}: + 0 ? 'text-warning' : 'text-success'}> + {formatCooldown(getCooldownRemaining())} + + {t('lp.yourBalance')}: + {ytLPBalance ? formatUnits(ytLPBalance, 18) : '0'} ytLP +
+ +
+ {/* 添加流动性边界测试 */} +
+
+ {t('lp.testAddZero')} + InvalidAmount +
+

{t('lp.testAddZeroDesc')}

+ +
+ +
+
+ {t('lp.testAddExceed')} + InsufficientBalance +
+

{t('lp.testAddExceedDesc')}

+ +
+ + {/* 移除流动性边界测试 */} +
+
+ {t('lp.testRemoveZero')} + InvalidAmount +
+

{t('lp.testRemoveZeroDesc')}

+ +
+ +
+
+ {t('lp.testRemoveExceed')} + InsufficientBalance +
+

{t('lp.testRemoveExceedDesc')}

+ +
+ +
+
+ {t('lp.testRemoveHighMinout')} + InsufficientOutput +
+

{t('lp.testRemoveHighMinoutDesc')}

+ +
+ + {/* 代币互换边界测试 */} +
+
+ {t('lp.testSwapZero')} + InvalidAmount +
+

{t('lp.testSwapZeroDesc')}

+ +
+ +
+
+ {t('lp.testSwapSame')} + SameToken +
+

{t('lp.testSwapSameDesc')}

+ +
+ +
+
+ {t('lp.testSwapExceed')} + InsufficientBalance +
+

{t('lp.testSwapExceedDesc')}

+ +
+
+ + )} +
+ {/* Transaction History */} diff --git a/frontend/src/i18n/locales/en.json b/frontend/src/i18n/locales/en.json index cad91d9..5730fd9 100644 --- a/frontend/src/i18n/locales/en.json +++ b/frontend/src/i18n/locales/en.json @@ -178,6 +178,23 @@ "swap": "Swap", "cooldownNotPassed": "Cooldown not passed, please try later", "insufficientOutput": "Insufficient output amount", - "cooldownWarning": "Cooldown remaining {{time}}, cannot remove liquidity yet" + "cooldownWarning": "Cooldown remaining {{time}}, cannot remove liquidity yet", + "boundaryHint": "These tests are designed to trigger LP contract errors. Expected errors are shown for each test.", + "testAddZero": "Add Liquidity Zero", + "testAddZeroDesc": "Test addLiquidity(token, 0, 0, 0)", + "testAddExceed": "Add Exceed Balance", + "testAddExceedDesc": "Add liquidity exceeding token balance", + "testRemoveZero": "Remove Liquidity Zero", + "testRemoveZeroDesc": "Test removeLiquidity(token, 0, 0, receiver)", + "testRemoveExceed": "Remove Exceed Balance", + "testRemoveExceedDesc": "Remove liquidity exceeding ytLP balance", + "testRemoveHighMinout": "Remove High MinOut", + "testRemoveHighMinoutDesc": "Set impossible minimum output amount", + "testSwapZero": "Swap Amount Zero", + "testSwapZeroDesc": "Test swapYT(tokenIn, tokenOut, 0, 0, receiver)", + "testSwapSame": "Swap Same Token", + "testSwapSameDesc": "Test swapYT(YT-A, YT-A, amount, 0, receiver)", + "testSwapExceed": "Swap Exceed Balance", + "testSwapExceedDesc": "Swap amount exceeding token balance" } } diff --git a/frontend/src/i18n/locales/zh.json b/frontend/src/i18n/locales/zh.json index 987909a..70e94a4 100644 --- a/frontend/src/i18n/locales/zh.json +++ b/frontend/src/i18n/locales/zh.json @@ -178,6 +178,23 @@ "swap": "交换", "cooldownNotPassed": "冷却期未过,请稍后再试", "insufficientOutput": "输出金额不足", - "cooldownWarning": "冷却期剩余 {{time}},暂时无法移除流动性" + "cooldownWarning": "冷却期剩余 {{time}},暂时无法移除流动性", + "boundaryHint": "这些测试旨在触发LP合约错误。每个测试都显示了预期的错误类型。", + "testAddZero": "添加流动性为0", + "testAddZeroDesc": "测试 addLiquidity(token, 0, 0, 0)", + "testAddExceed": "添加超过余额", + "testAddExceedDesc": "添加流动性金额超过代币余额", + "testRemoveZero": "移除流动性为0", + "testRemoveZeroDesc": "测试 removeLiquidity(token, 0, 0, receiver)", + "testRemoveExceed": "移除超过余额", + "testRemoveExceedDesc": "移除流动性金额超过ytLP余额", + "testRemoveHighMinout": "移除minOut过高", + "testRemoveHighMinoutDesc": "设置不可能达到的最小输出金额", + "testSwapZero": "互换金额为0", + "testSwapZeroDesc": "测试 swapYT(tokenIn, tokenOut, 0, 0, receiver)", + "testSwapSame": "相同代币互换", + "testSwapSameDesc": "测试 swapYT(YT-A, YT-A, amount, 0, receiver)", + "testSwapExceed": "互换超过余额", + "testSwapExceedDesc": "互换金额超过代币余额" } }