diff --git a/submissions/pancakeswap-v2/LICENSE b/submissions/pancakeswap-v2/LICENSE new file mode 100644 index 0000000..017d741 --- /dev/null +++ b/submissions/pancakeswap-v2/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 skylavis-sky + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/submissions/pancakeswap-v2/plugin.yaml b/submissions/pancakeswap-v2/plugin.yaml new file mode 100644 index 0000000..67bf055 --- /dev/null +++ b/submissions/pancakeswap-v2/plugin.yaml @@ -0,0 +1,35 @@ +schema_version: 1 +name: pancakeswap-v2 +version: "0.2.0" +description: "Swap tokens and provide full-range liquidity on PancakeSwap V2 — the xyk AMM on BSC and Base" +author: + name: skylavis-sky + github: skylavis-sky +category: defi-protocol +tags: + - dex + - swap + - liquidity + - amm + - pancakeswap + - bsc + - v2 + - xyk + - lp +license: MIT + +components: + skill: + dir: skills/pancakeswap-v2 + +build: + lang: rust + binary_name: pancakeswap-v2 + source_repo: skylavis-sky/onchainos-plugins + source_commit: "83b306e1e3ccf4b14fc11a76bd5b906297340ef4" + source_dir: pancakeswap-v2 + +api_calls: + - "https://bsc-rpc.publicnode.com" + - "https://base-rpc.publicnode.com" + - "https://api.pancakeswap.info/api/v2/tokens" diff --git a/submissions/pancakeswap-v2/skills/pancakeswap-v2/SKILL.md b/submissions/pancakeswap-v2/skills/pancakeswap-v2/SKILL.md new file mode 100644 index 0000000..c136ac9 --- /dev/null +++ b/submissions/pancakeswap-v2/skills/pancakeswap-v2/SKILL.md @@ -0,0 +1,268 @@ +--- +name: pancakeswap-v2 +description: "Swap tokens and provide full-range liquidity on PancakeSwap V2 — the xyk AMM on BSC and Base. Trigger phrases: swap on pancakeswap v2, pancake swap, pcs v2 swap, add liquidity pancakeswap, remove liquidity pancake, pancake amm, pancakeswap v2 quote, check pancake pair. Chinese: 在PancakeSwap V2兑换代币, PancakeSwap添加流动性, PancakeSwap移除流动性, 查询Pancake报价" +license: MIT +metadata: + author: skylavis-sky + version: "0.2.0" +--- + +## Changelog + +### v0.2.0 (2026-04-11) + +**Bug fixes in `remove-liquidity`:** + +1. **`lpBalance` showed zero-address balance in dry-run** — When `--dry-run` was used without `--from`, the wallet was set to `0x0000…0000` for all reads, so `lpBalance` returned whatever LP tokens the zero address holds (typically the locked MINIMUM_LIQUIDITY) instead of the user's real balance. Fixed: dry-run now uses `--from` (if provided) or `onchainos::resolve_wallet` for reads; zero address is only the final fallback when no wallet is available. + +2. **`expectedTokenA / expectedTokenB` overflow for large pools** — The formula `reserve * lp_burned / total_supply` used raw `u128` multiplication. For high-liquidity pools (e.g. the BSC BNB/USDT pool with reserves > 10²² raw units), `reserve × lp_burned` overflows u128 (max ~3.4×10³⁸), producing garbage values. Fixed: `safe_mul_div` tries `checked_mul` first and falls back to `f64` arithmetic on overflow, matching the approach already used in `lp-balance`. + +Both bugs confirmed fixed via full live-transaction regression test suite (12 tests, BSC + Base, 2026-04-11). + +--- + +## Architecture + +- Read ops (quote, get-pair, get-reserves, lp-balance) → direct `eth_call` via public RPC; no confirmation needed +- Write ops (swap, add-liquidity, remove-liquidity) → after user confirmation, submits via `onchainos wallet contract-call --force` +- ERC-20 approvals → manually encoded `approve()` calldata, submitted via `onchainos wallet contract-call --force` +- Supports BSC (chain 56, default) and Base (chain 8453) +- V2 uses constant-product xyk formula; LP tokens are standard ERC-20 (not NFTs); fixed 0.25% swap fee + +## Execution Flow for Write Operations + +1. Run with `--dry-run` first to preview calldata and estimated amounts +2. **Ask user to confirm** the transaction details before proceeding +3. Execute only after explicit user approval +4. Report transaction hash and block explorer link + +--- + +## Command Routing + +| User intent | Command | +|-------------|---------| +| "How much CAKE for 100 USDT?" | `pancakeswap-v2 quote` | +| "Swap 100 USDT for CAKE on PancakeSwap V2" | `pancakeswap-v2 swap` | +| "Add liquidity CAKE/BNB on PancakeSwap" | `pancakeswap-v2 add-liquidity` | +| "Remove my CAKE/USDT liquidity on Pancake" | `pancakeswap-v2 remove-liquidity` | +| "What is the CAKE/BNB pair address on PancakeSwap V2?" | `pancakeswap-v2 get-pair` | +| "What are the reserves in the CAKE/BNB pool?" | `pancakeswap-v2 get-reserves` | +| "How much LP do I have for CAKE/BNB?" | `pancakeswap-v2 lp-balance` | + +--- + +## quote — Get Expected Swap Output + +**Trigger phrases:** quote pancakeswap, how much would I get, pancake v2 price, estimate swap + +**Usage:** +``` +pancakeswap-v2 --chain 56 quote --token-in USDT --token-out CAKE --amount-in 100000000000000000000 +``` + +**Parameters:** +| Name | Flag | Description | +|------|------|-------------| +| tokenIn | `--token-in` | Input token: symbol (USDT, CAKE, WBNB) or hex address | +| tokenOut | `--token-out` | Output token: symbol or hex address | +| amountIn | `--amount-in` | Input amount in minimal units (e.g. 100e18 = 100 tokens for 18-decimal token) | +| chain | `--chain` | Chain ID: 56 (BSC, default) or 8453 (Base) | + +**Example output:** +```json +{ + "ok": true, + "data": { + "tokenIn": "0x55d398326f99059fF775485246999027B3197955", + "tokenOut": "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82", + "symbolIn": "USDT", + "symbolOut": "CAKE", + "amountIn": "100000000000000000000", + "amountOut": "23500000000000000000", + "amountOutHuman": "23.500000", + "path": ["0x55d3...", "0x0E09..."], + "fee": "0.25%", + "chain": 56 + } +} +``` + +Read-only operation — no confirmation required. + +--- + +## swap — Swap Tokens + +**Trigger phrases:** swap on pancakeswap v2, pancake swap, exchange tokens on pcs, trade on pancakeswap + +**Usage:** +``` +pancakeswap-v2 --chain 56 swap --token-in USDT --token-out CAKE --amount-in 100000000000000000000 +``` + +**Parameters:** +| Name | Flag | Description | +|------|------|-------------| +| tokenIn | `--token-in` | Input token: symbol or address. Use BNB/ETH for native | +| tokenOut | `--token-out` | Output token: symbol or address | +| amountIn | `--amount-in` | Input amount in minimal units | +| slippageBps | `--slippage-bps` | Slippage in basis points (default 50 = 0.5%) | +| deadlineSecs | `--deadline-secs` | Seconds until deadline (default 300) | +| dryRun | `--dry-run` | Preview calldata only, no broadcast | + +**Execution flow:** +1. Run `--dry-run` to preview the swap calldata and expected output +2. **Ask user to confirm** the swap details (tokenIn, tokenOut, amountIn, amountOutMin, slippage) +3. If tokenIn is an ERC-20 and allowance is insufficient, first submit an approve tx via `onchainos wallet contract-call --force`; **ask user to confirm** the approval +4. Submit swap via `onchainos wallet contract-call --force` +5. Report txHash and BscScan/BaseScan link + +**Supported swap variants:** +- Token → Token (`swapExactTokensForTokens`) +- BNB/ETH → Token (`swapExactETHForTokens`, pass `--token-in BNB`) +- Token → BNB/ETH (`swapExactTokensForETH`, pass `--token-out BNB`) + +**Example output:** +```json +{ + "ok": true, + "steps": [ + {"step": "approve", "txHash": "0xabc..."}, + {"step": "swapExactTokensForTokens", "txHash": "0xdef...", "explorer": "bscscan.com/tx/0xdef..."} + ] +} +``` + +--- + +## add-liquidity — Add Liquidity + +**Trigger phrases:** add liquidity on pancakeswap, provide liquidity pancake v2, become LP on pancakeswap, join pancake pool + +**Usage:** +``` +# Token + Token +pancakeswap-v2 --chain 56 add-liquidity --token-a CAKE --token-b USDT --amount-a 10000000000000000000 --amount-b 50000000000000000000 + +# Token + native BNB +pancakeswap-v2 --chain 56 add-liquidity --token-a CAKE --token-b BNB --amount-a 10000000000000000000 --amount-b 50000000000000000 +``` + +**Parameters:** +| Name | Flag | Description | +|------|------|-------------| +| tokenA | `--token-a` | First token: symbol or address. Use BNB/ETH for native | +| tokenB | `--token-b` | Second token. Use BNB/ETH for native | +| amountA | `--amount-a` | Desired amount of tokenA in minimal units | +| amountB | `--amount-b` | Desired amount of tokenB (or native BNB/ETH) in minimal units | +| slippageBps | `--slippage-bps` | Slippage tolerance (default 50 = 0.5%) | +| dryRun | `--dry-run` | Preview calldata only | + +**Execution flow:** +1. Check current pair reserves and ratio +2. Run `--dry-run` to preview the transaction +3. **Ask user to confirm** the amounts and LP token receipt before proceeding +4. Approve Router02 to spend tokenA/tokenB via `onchainos wallet contract-call --force` (if needed); **ask user to confirm** each approval +5. Submit `addLiquidity` or `addLiquidityETH` via `onchainos wallet contract-call --force` +6. Report txHash and LP tokens received + +--- + +## remove-liquidity — Remove Liquidity + +**Trigger phrases:** remove liquidity pancakeswap, withdraw liquidity from pancake, exit pancakeswap pool, burn LP tokens pancake + +**Usage:** +``` +# Remove all LP +pancakeswap-v2 --chain 56 remove-liquidity --token-a CAKE --token-b USDT + +# Remove specific amount +pancakeswap-v2 --chain 56 remove-liquidity --token-a CAKE --token-b USDT --liquidity 1000000000000000000 +``` + +**Parameters:** +| Name | Flag | Description | +|------|------|-------------| +| tokenA | `--token-a` | First token | +| tokenB | `--token-b` | Second token. Use BNB/ETH to receive native | +| liquidity | `--liquidity` | LP tokens to burn (minimal units). Omit to remove all | +| slippageBps | `--slippage-bps` | Slippage tolerance (default 50 = 0.5%) | +| dryRun | `--dry-run` | Preview only | + +**Execution flow:** +1. Fetch LP balance and compute expected token withdrawals +2. Display summary: LP amount, expected tokenA and tokenB out +3. Run `--dry-run` to preview calldata +4. **Ask user to confirm** the removal details before proceeding +5. Approve LP tokens to Router02 via `onchainos wallet contract-call --force`; **ask user to confirm** +6. Submit `removeLiquidity` or `removeLiquidityETH` via `onchainos wallet contract-call --force` +7. Report txHash + +--- + +## get-pair — Look Up Pair Address + +**Trigger phrases:** find pancakeswap pair, what is the pancake pair address, does pancake v2 have a pool for + +**Usage:** +``` +pancakeswap-v2 --chain 56 get-pair --token-a CAKE --token-b BNB +``` + +Read-only — no confirmation required. + +--- + +## get-reserves — Get Pool Reserves + +**Trigger phrases:** pancakeswap pool reserves, pancake pool price, what is the price in pancake v2, check pancake liquidity + +**Usage:** +``` +pancakeswap-v2 --chain 56 get-reserves --token-a CAKE --token-b BNB +``` + +Read-only — no confirmation required. + +--- + +## lp-balance — Check LP Token Balance + +**Trigger phrases:** how much LP do I have in pancake, check my pancakeswap position, my pancake v2 liquidity + +**Usage:** +``` +pancakeswap-v2 --chain 56 lp-balance --token-a CAKE --token-b BNB +pancakeswap-v2 --chain 56 lp-balance --token-a CAKE --token-b BNB --wallet 0xYourAddress +``` + +Read-only — no confirmation required. + +--- + +## Token Symbols (BSC) + +| Symbol | Address | +|--------|---------| +| WBNB / BNB | `0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c` | +| CAKE | `0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82` | +| USDT | `0x55d398326f99059fF775485246999027B3197955` | +| USDC | `0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d` | +| BUSD | `0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56` | + +For Base (8453): WETH `0x4200000000000000000000000000000000000006`, USDC `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`. + +--- + +## Troubleshooting + +| Error | Likely cause | Fix | +|-------|-------------|-----| +| "No V2 liquidity path found" | No direct or WBNB-routed pair exists | Use a different token pair or check on BscScan | +| "You have no LP tokens for this pair" | Wallet has 0 LP balance | Verify correct wallet address and chain | +| txHash is "pending", never broadcasts | Missing `--force` flag | Plugin always adds `--force`; check onchainos version | +| Swap reverts on-chain | Slippage too tight or stale price | Increase `--slippage-bps` (e.g. 100 for 1%) | +| "Cannot resolve wallet address" | onchainos not logged in | Run `onchainos wallet login` or pass `--from
` | +| "Unsupported chain ID" | Chain not 56 or 8453 | Use `--chain 56` (BSC) or `--chain 8453` (Base) | diff --git a/submissions/pancakeswap-v2/skills/pancakeswap-v2/pancakeswap-v2 b/submissions/pancakeswap-v2/skills/pancakeswap-v2/pancakeswap-v2 new file mode 100755 index 0000000..20651ab Binary files /dev/null and b/submissions/pancakeswap-v2/skills/pancakeswap-v2/pancakeswap-v2 differ diff --git a/submissions/pancakeswap-v2/tests/test_results.md b/submissions/pancakeswap-v2/tests/test_results.md new file mode 100644 index 0000000..049a028 --- /dev/null +++ b/submissions/pancakeswap-v2/tests/test_results.md @@ -0,0 +1,277 @@ +# Test Results Report — PancakeSwap V2 + +- **Date:** 2026-04-05 +- **Tester:** Phase 3 Tester Agent +- **Plugin:** pancakeswap-v2 v0.1.0 +- **Test chains:** BSC (56), Base (8453) +- **Compile:** ✅ +- **Lint:** ✅ + +--- + +## Summary + +| Total | L1 Compile | L2 Read | L3 Simulate | L4 On-chain | Failed | Blocked | +|-------|-----------|---------|------------|------------|--------|---------| +| 17 | 2 ✅ | 8 ✅ | 3 ✅ | 2 ✅ (Base) + 2 ⛔ BLOCKED (BSC) | 0 | 2 | + +--- + +## Detailed Results + +| # | Scenario (user view) | Level | Command | Result | TxHash / Calldata | Notes | +|---|---------------------|-------|---------|--------|------------------|-------| +| 1 | Build plugin binary | L1 | `cargo build --release` | ✅ PASS | — | 1 dead_code warning (validate_router, harmless) | +| 2 | Plugin lint check | L1 | `cargo clean && plugin-store lint .` | ✅ PASS | — | 0 errors, all checks passed | +| 3 | "How much USDT for 1 WBNB on PancakeSwap V2?" | L2 | `--chain 56 quote --token-in WBNB --token-out USDT --amount-in 1000000000000000000` | ✅ PASS | — | amountOut=592327660679599984516 (~592 USDT), direct path WBNB→USDT | +| 4 | "Quote WETH→USDC on Base PancakeSwap V2" | L2 | `--chain 8453 quote --token-in WETH --token-out USDC --amount-in 1000000000000000` | ✅ PASS | — | amountOut=2049543 (~2.05 USDC), direct path WETH→USDC | +| 5 | "What is the WBNB/USDT pair address on BSC?" | L2 | `--chain 56 get-pair --token-a WBNB --token-b USDT` | ✅ PASS | — | pair=0x16b9a82891338f9ba80e2d6970fdda79d1eb0dae, exists=true | +| 6 | "What is the WETH/USDC pair address on Base?" | L2 | `--chain 8453 get-pair --token-a WETH --token-b USDC` | ✅ PASS | — | pair=0x79474223aedd0339780bacce75abda0be84dcbf9, exists=true | +| 7 | "What are the reserves in the WBNB/USDT pool on BSC?" | L2 | `--chain 56 get-reserves --token-a WBNB --token-b USDT` | ✅ PASS | — | reserveA=28680 WBNB, reserveB=17.0M USDT, price=593.84 USDT/WBNB | +| 8 | "What are the reserves in the WETH/USDC pool on Base?" | L2 | `--chain 8453 get-reserves --token-a WETH --token-b USDC` | ✅ PASS | — | reserveA=0.174 WETH, reserveB=360 USDC, price=2066 USDC/WETH | +| 9 | "How much LP do I have in WBNB/USDT on BSC?" | L2 | `--chain 56 lp-balance --token-a WBNB --token-b USDT --wallet 0xee385ac7...` | ✅ PASS | — | lpBalance=0 (wallet not LP), totalSupply=272379606984276614941852 | +| 10 | "How much LP do I have in WETH/USDC on Base?" | L2 | `--chain 8453 lp-balance --token-a WETH --token-b USDC --wallet 0xee385ac7...` | ✅ PASS | — | lpBalance=0, totalSupply=5757069332383 | +| 11 | "Simulate swapping WBNB→USDT on PancakeSwap V2" | L3 | `--chain 56 --dry-run swap --token-in WBNB --token-out USDT --amount-in 1000000000000000000` | ✅ PASS | calldata selector: `0x38ed1739` (swapExactTokensForTokens) | dry_run=true, no broadcast, correct selector verified in source | +| 12 | "Preview adding WBNB/USDT liquidity on BSC" | L3 | `--chain 56 --dry-run add-liquidity --token-a WBNB --token-b USDT --amount-a 1000000000000000 --amount-b 500000000000000000` | ✅ PASS | calldata selector: `0xe8e33700` (addLiquidity) | dry_run=true, steps include approve_tokenA, approve_tokenB, addLiquidity | +| 13 | "Preview removing WBNB/USDT liquidity on BSC" | L3 | `--chain 56 --dry-run remove-liquidity --token-a WBNB --token-b USDT --liquidity 1000000000000000` | ✅ PASS | calldata selector: `0xbaa2abde` (removeLiquidity) | dry_run=true, steps include approve_lp, removeLiquidity | +| 14 | "Swap WBNB→USDT with minimum amount on BSC" | L4 | `--chain 56 swap --token-in WBNB --token-out USDT --amount-in