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": "互换金额超过代币余额" } }