Kumbaya v3 routing: accept ETH + USDM + CL8Y (pool config + local/testnet testing) #41

Closed
opened 2026-04-22 03:01:42 +00:00 by PlasticDigits · 7 comments
PlasticDigits commented 2026-04-22 03:01:42 +00:00 (Migrated from gitlab.com)

Summary

Enable multi-asset entry for TimeCurve participation by routing ETH and USDM into the sale’s accepted asset (CL8Y) via Kumbaya v3 liquidity, using the natural hop paths:

  • ETH → CL8Y through the CL8Y/ETH (or ETH/CL8Y) v3 pool
  • USDM → CL8Y through USDM/ETH then ETH/CL8Y (or a direct pool if one exists on Kumbaya — product decision)

CL8Y remains a direct path (existing ERC-20 approve + buy flow).

Frontend: encode canonical Kumbaya v3 pair/pool (and fee tier) addresses per chain in the app (not user-configurable at runtime). Optional build-time overrides (VITE_*) can point local/test deployments at mock or forked pools without forking the whole routing table into env for production.

Testing: we must be able to exercise swaps + TimeCurve buy end-to-end on Anvil (31337) and target testnets without relying on mainnet-only liquidity.


Background (repo today)


Scope (proposal)

Product / UX

  • User selects pay with: CL8Y | ETH | USDM (wording TBD vs wrapped ETH if we standardize on WETH under the hood).
  • Quote shows expected CL8Y out (and implied CHARM band / gross spend) before sign; slippage + price impact surfaced.
  • Single transaction where possible (multicall / swap + buy), or explicit two-step if router integration requires approve + swap + buy — document tradeoffs.
  • Clear fallback when no route or insufficient liquidity on Kumbaya for the chain.

Technical — routing

  • Integrate Kumbaya v3 swap interface (exact ABI / router contract TBD with protocol team): pool keys, exactInput / exactOutput paths, fee tiers.
  • Hardcoded routing graph in frontend (or shared TS package): for each supported chainId, list:
    • CL8Y/ETH pool id + fee
    • ETH/USDM pool id + fee (if used)
    • Any official quoter addresses
  • Chain separation: production mainnet/testnet IDs use published Kumbaya addresses; 31337 uses a fixture table (see Testing).

Testing — localnet (Anvil)

  • Option A (preferred for CI): Forge script or DeployDev extension deploys minimal Uniswap v3–compatible (or Kumbaya fork) pair contracts + seed liquidity CL8Y/WETH and WETH/USDM (mock tokens already mintable in dev).
  • Option B: Document fork of a testnet/mainnet RPC where Kumbaya pools exist; anvil --fork-url … for manual QA.
  • E2E or integration test: fund wallet → swap ETH → CL8Y (or USDM path) → TimeCurve buy on 31337.
  • frontend/.env.local / VITE_* override for pool addresses on 31337 so hardcoded “prod” table does not block local dev.

Testing — public testnet

  • Registry JSON (pattern: contracts/deployments/stage2-anvil-registry.json) or equivalent listing Kumbaya pool addresses on the target testnet.
  • Smoke script or doc: acquire test ETH/USDM/CL8Y → run swap + buy against deployed TimeCurve.
  • Align with MegaETH / CL8Y testnet faucet flows if applicable.

Open questions

  1. Kumbaya v3 public ABIs and canonical router address per environment (who owns the list of pools + fee tiers?).
  2. USDM on each chain: same bridge address as production or test-only mint?
  3. exactOutput vs exactInput for TimeCurve: do we target a fixed CL8Y gross (for CHARM band) and solve input ETH/USDM, or fix input and accept CL8Y drift?
  4. Should WETH be the only ETH representation in calldata, with wrap/unwrap handled in the router bundle?
  5. Regulatory / copy: multi-asset entry may need disclaimer on third-party DEX routing (Kumbaya).

Deliverables

  1. Design note: user flows + error states (no liquidity, high slippage, wrong chain).
  2. kumbayaRoutes.ts (or similar): chainId → { pools, quoter, router } with tests.
  3. Deploy / seed tooling for Anvil pools + liquidity.
  4. Docs: docs/… section for “local swap testing” and testnet registry update process.
  5. Optional follow-up issue: indexer events if we need to attribute “buy paid with ETH” vs CL8Y for analytics.

Acceptance criteria (high level)

  • ETH and USDM can be converted to CL8Y through documented Kumbaya v3 paths and used to fund a TimeCurve buy on at least one test environment.
  • Production-bound frontend ships with hardcoded canonical pool config; local/test overrides are documented and used in CI or manual runbook.
  • No silent fallback to wrong pool: invalid chainId or missing config fails closed with user-visible error.
## Summary Enable **multi-asset entry** for TimeCurve participation by routing **ETH** and **USDM** into the sale’s accepted asset (**CL8Y**) via **Kumbaya v3** liquidity, using the natural hop paths: - **ETH → CL8Y** through the **CL8Y/ETH** (or **ETH/CL8Y**) v3 pool - **USDM → CL8Y** through **USDM/ETH** then **ETH/CL8Y** (or a direct pool if one exists on Kumbaya — product decision) **CL8Y** remains a **direct** path (existing ERC-20 approve + `buy` flow). **Frontend:** encode **canonical Kumbaya v3 pair/pool (and fee tier) addresses per chain** in the app (not user-configurable at runtime). Optional **build-time overrides** (`VITE_*`) can point local/test deployments at mock or forked pools without forking the whole routing table into env for production. **Testing:** we must be able to exercise swaps + TimeCurve `buy` end-to-end on **Anvil (31337)** and **target testnets** without relying on mainnet-only liquidity. --- ## Background (repo today) - TimeCurve **`buy`** expects the **accepted asset** (launch default **CL8Y**) — see [`contracts/src/TimeCurve.sol`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/contracts/src/TimeCurve.sol) and [`docs/onchain/fee-routing-and-governance.md`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/docs/onchain/fee-routing-and-governance.md). - The frontend today wires **CL8Y-only** spend on [`frontend/src/pages/TimeCurvePage.tsx`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/frontend/src/pages/TimeCurvePage.tsx); [`frontend/src/lib/addresses.ts`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/frontend/src/lib/addresses.ts) has no pool/router config — [`KumbayaPage`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/frontend/src/pages/KumbayaPage.tsx) is third-party link + placeholder via `VITE_KUMBAYA_DEX_URL`. - Dev deploy uses mock **CL8Y** when `RESERVE_ASSET_ADDRESS` / `USDM_ADDRESS` unset — [`contracts/script/DeployDev.s.sol`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/contracts/script/DeployDev.s.sol), [`contracts/README.md`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/contracts/README.md). --- ## Scope (proposal) ### Product / UX - [ ] User selects **pay with**: CL8Y | ETH | USDM (wording TBD vs wrapped ETH if we standardize on WETH under the hood). - [ ] Quote shows **expected CL8Y out** (and implied CHARM band / gross spend) before sign; slippage + price impact surfaced. - [ ] Single transaction where possible (multicall / swap + buy), or explicit two-step if router integration requires approve + swap + buy — document tradeoffs. - [ ] Clear fallback when **no route** or **insufficient liquidity** on Kumbaya for the chain. ### Technical — routing - [ ] Integrate **Kumbaya v3** swap interface (exact ABI / router contract TBD with protocol team): pool keys, `exactInput` / `exactOutput` paths, fee tiers. - [ ] **Hardcoded routing graph** in frontend (or shared TS package): for each supported `chainId`, list: - CL8Y/ETH pool id + fee - ETH/USDM pool id + fee (if used) - Any official **quoter** addresses - [ ] **Chain separation:** production mainnet/testnet IDs use published Kumbaya addresses; **31337** uses a **fixture table** (see Testing). ### Testing — localnet (Anvil) - [ ] **Option A (preferred for CI):** Forge script or `DeployDev` extension deploys **minimal Uniswap v3–compatible** (or Kumbaya fork) **pair contracts** + seed liquidity **CL8Y/WETH** and **WETH/USDM** (mock tokens already mintable in dev). - [ ] **Option B:** Document **fork** of a testnet/mainnet RPC where Kumbaya pools exist; `anvil --fork-url …` for manual QA. - [ ] E2E or integration test: fund wallet → **swap ETH → CL8Y** (or USDM path) → **TimeCurve buy** on 31337. - [ ] `frontend/.env.local` / `VITE_*` **override** for pool addresses on 31337 so hardcoded “prod” table does not block local dev. ### Testing — public testnet - [ ] Registry JSON (pattern: [`contracts/deployments/stage2-anvil-registry.json`](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/contracts/deployments/stage2-anvil-registry.json)) or equivalent listing **Kumbaya pool addresses** on the target testnet. - [ ] Smoke script or doc: acquire test ETH/USDM/CL8Y → run swap + buy against deployed TimeCurve. - [ ] Align with MegaETH / CL8Y testnet faucet flows if applicable. --- ## Open questions 1. **Kumbaya v3** public ABIs and **canonical router** address per environment (who owns the list of pools + fee tiers?). 2. **USDM** on each chain: same bridge address as production or test-only mint? 3. **exactOutput** vs **exactInput** for TimeCurve: do we target a fixed CL8Y gross (for CHARM band) and solve input ETH/USDM, or fix input and accept CL8Y drift? 4. Should **WETH** be the only ETH representation in calldata, with wrap/unwrap handled in the router bundle? 5. **Regulatory / copy:** multi-asset entry may need disclaimer on third-party DEX routing (Kumbaya). --- ## Deliverables 1. Design note: user flows + error states (no liquidity, high slippage, wrong chain). 2. **`kumbayaRoutes.ts`** (or similar): `chainId → { pools, quoter, router }` with tests. 3. **Deploy / seed** tooling for Anvil pools + liquidity. 4. **Docs:** `docs/…` section for “local swap testing” and testnet registry update process. 5. Optional follow-up issue: indexer events if we need to attribute “buy paid with ETH” vs CL8Y for analytics. --- ## Acceptance criteria (high level) - [ ] ETH and USDM can be converted to CL8Y through **documented** Kumbaya v3 paths and used to fund a TimeCurve buy on **at least one** test environment. - [ ] Production-bound frontend ships with **hardcoded** canonical pool config; local/test overrides are **documented** and **used in CI or manual runbook**. - [ ] No silent fallback to wrong pool: invalid `chainId` or missing config **fails closed** with user-visible error.
PlasticDigits commented 2026-04-22 13:57:47 +00:00 (Migrated from gitlab.com)

mentioned in commit f49960f029

mentioned in commit f49960f029969d4fd1bb36a168ee1f1c8103759e
PlasticDigits commented 2026-04-22 13:58:08 +00:00 (Migrated from gitlab.com)

Implemented GitLab #41 (merged to main @ 92c5a9f).

What shipped

  • frontend/src/lib/kumbayaRoutes.ts: chain table for 31337 + 6343, VITE_KUMBAYA_* overrides, fail-closed routing, v3-style exactOutput path encoding; Vitest coverage.
  • useTimeCurveSaleSession: pay with CL8Y | ETH | USDM; quoteExactOutput → WETH deposit + exactOutput (or USDM approve) → existing TimeCurve approve + buy.
  • TimeCurveSimplePage: pay-with radios, slippage (bps), quote line, Kumbaya disclaimer, routing/quote errors.
  • Contracts: AnvilKumbayaRouter + DeployKumbayaAnvilFixtures.s.sol (Anvil-only constant-product fixture, same address for router + quoter). anvil_deploy_dev.sh runs it and e2e-anvil.sh exports VITE_KUMBAYA_*.
  • E2E: serial wallet tests; new ETH route test; Arena protocol spec + deadline assertion (seconds-remaining needs indexer).
  • Docs: docs/testing/local-swap-testing.md, e2e-anvil.md table, frontend/.env.example, contracts/deployments/kumbaya-anvil-registry.example.json.

Verification for @brouie

  1. bash scripts/e2e-anvil.sh — expect 4 Playwright tests green (includes ETH swap + buy).
  2. On Anvil build, confirm env has VITE_KUMBAYA_WETH, USDM, SWAP_ROUTER, QUOTER (quoter = router for fixture).
  3. Manual: open /timecurve, select ETH, wait for Quote: spend, run Buy CHARM — wallet should sign wrap, approvals, swap, approve CL8Y, buy.
  4. Repeat with USDM (deployer/mock wallet should hold USDM on default Anvil account).
  5. Switch to a chain without VITE_KUMBAYA_* / table support — non-CL8Y modes should show a clear error (fail closed).
  6. Production: replace fixture addresses with real Kumbaya router/quoter/pool config when published; update kumbayaRoutes.ts or CI env.

EOF

Implemented GitLab #41 (merged to `main` @ 92c5a9f). ### What shipped - **`frontend/src/lib/kumbayaRoutes.ts`**: chain table for `31337` + `6343`, `VITE_KUMBAYA_*` overrides, fail-closed routing, v3-style `exactOutput` path encoding; Vitest coverage. - **`useTimeCurveSaleSession`**: pay with CL8Y | ETH | USDM; `quoteExactOutput` → WETH `deposit` + `exactOutput` (or USDM approve) → existing TimeCurve approve + `buy`. - **`TimeCurveSimplePage`**: pay-with radios, slippage (bps), quote line, Kumbaya disclaimer, routing/quote errors. - **Contracts**: `AnvilKumbayaRouter` + `DeployKumbayaAnvilFixtures.s.sol` (Anvil-only constant-product fixture, same address for router + quoter). `anvil_deploy_dev.sh` runs it and `e2e-anvil.sh` exports `VITE_KUMBAYA_*`. - **E2E**: serial wallet tests; new ETH route test; Arena protocol spec + deadline assertion (seconds-remaining needs indexer). - **Docs**: `docs/testing/local-swap-testing.md`, `e2e-anvil.md` table, `frontend/.env.example`, `contracts/deployments/kumbaya-anvil-registry.example.json`. ### Verification for @brouie 1. `bash scripts/e2e-anvil.sh` — expect 4 Playwright tests green (includes ETH swap + buy). 2. On Anvil build, confirm env has `VITE_KUMBAYA_WETH`, `USDM`, `SWAP_ROUTER`, `QUOTER` (quoter = router for fixture). 3. Manual: open `/timecurve`, select **ETH**, wait for **Quote: spend**, run **Buy CHARM** — wallet should sign wrap, approvals, swap, approve CL8Y, buy. 4. Repeat with **USDM** (deployer/mock wallet should hold USDM on default Anvil account). 5. Switch to a chain **without** `VITE_KUMBAYA_*` / table support — non-CL8Y modes should show a **clear error** (fail closed). 6. Production: replace fixture addresses with real Kumbaya router/quoter/pool config when published; update `kumbayaRoutes.ts` or CI env. EOF
PlasticDigits commented 2026-04-23 05:34:06 +00:00 (Migrated from gitlab.com)

Update: needs compliance with #46 As kumbaya has provided their integration kit with testnet/mainnet connectors and contracts which should be utilized where possible instead of custom solutions. https://github.com/Kumbaya-xyz/integrator-kit

Update: needs compliance with #46 As kumbaya has provided their integration kit with testnet/mainnet connectors and contracts which should be utilized where possible instead of custom solutions. https://github.com/Kumbaya-xyz/integrator-kit
Brouie commented 2026-04-23 05:50:49 +00:00 (Migrated from gitlab.com)

mentioned in issue #52

mentioned in issue #52
Brouie commented 2026-04-23 05:51:24 +00:00 (Migrated from gitlab.com)

@PlasticDigits #41 verified.

Backend verification (earlier this morning)

  • kumbayaRoutes.test.ts: 9/9 Vitest passing (path packing, fail-closed chain/router/quoter/weth, pay-asset routing, slippage BPS)
  • forge test: 177/177 including AnvilKumbayaRouter + AnvilKumbayaFixture
  • Live Anvil deploy + quoteExactOutput on-chain:
    • Single-hop CL8Y ← WETH (1000 CL8Y out): 1.003 WETH — matches constant-product 0.3% fee math
    • Two-hop CL8Y ← WETH ← USDM (1000 CL8Y out): 1166.9 USDM — matches compounded-fee + shallow-pool slippage
  • Router ownership transferred to address(0) post-seed (fixture frozen, correct)

Frontend E2E (this afternoon via scripts/e2e-anvil.sh)

  • 3/4 Playwright Anvil tests pass
  • 1 failure: TimeCurve ETH route: quote, swap, and buy — test races against re-quote after slider change, NOT a feature bug. Filed as #52.

Code review highlights (kumbayaRoutes.ts)

  • Fail-closed on unknown chain, zero router/quoter/weth, out-of-range fee tier, out-of-range slippage BPS
  • Standard Uniswap v3 exactOutput path packing (20 + 3 + 20 bytes per hop, output-first token order)
  • CL8Y direct (empty path), ETH single-hop, USDM two-hop
  • Mainnet chain defaults deliberately empty pending protocol deploy — only 31337 + 6343 (dev) pre-configured

Closing as verified.

@PlasticDigits #41 verified. ## Backend verification (earlier this morning) - `kumbayaRoutes.test.ts`: 9/9 Vitest passing (path packing, fail-closed chain/router/quoter/weth, pay-asset routing, slippage BPS) - `forge test`: 177/177 including `AnvilKumbayaRouter` + `AnvilKumbayaFixture` - Live Anvil deploy + `quoteExactOutput` on-chain: - Single-hop CL8Y ← WETH (1000 CL8Y out): 1.003 WETH — matches constant-product 0.3% fee math - Two-hop CL8Y ← WETH ← USDM (1000 CL8Y out): 1166.9 USDM — matches compounded-fee + shallow-pool slippage - Router ownership transferred to `address(0)` post-seed (fixture frozen, correct) ## Frontend E2E (this afternoon via scripts/e2e-anvil.sh) - 3/4 Playwright Anvil tests pass - 1 failure: `TimeCurve ETH route: quote, swap, and buy` — test races against re-quote after slider change, NOT a feature bug. Filed as #52. ## Code review highlights (kumbayaRoutes.ts) - Fail-closed on unknown chain, zero router/quoter/weth, out-of-range fee tier, out-of-range slippage BPS - Standard Uniswap v3 `exactOutput` path packing (20 + 3 + 20 bytes per hop, output-first token order) - CL8Y direct (empty path), ETH single-hop, USDM two-hop - Mainnet chain defaults deliberately empty pending protocol deploy — only 31337 + 6343 (dev) pre-configured Closing as verified.
Brouie (Migrated from gitlab.com) closed this issue 2026-04-23 05:51:25 +00:00
Brouie commented 2026-04-23 06:24:52 +00:00 (Migrated from gitlab.com)

mentioned in issue #42

mentioned in issue #42
PlasticDigits commented 2026-05-04 13:48:08 +00:00 (Migrated from gitlab.com)

mentioned in issue #123

mentioned in issue #123
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
code/yieldomega#41
No description provided.