Skip to content

feat: add LunarBase adapter on Base#1189

Open
NebulaNomadPixel wants to merge 2 commits into
VeloraDEX:masterfrom
NebulaNomadPixel:master
Open

feat: add LunarBase adapter on Base#1189
NebulaNomadPixel wants to merge 2 commits into
VeloraDEX:masterfrom
NebulaNomadPixel:master

Conversation

@NebulaNomadPixel
Copy link
Copy Markdown

@NebulaNomadPixel NebulaNomadPixel commented May 25, 2026

Summary

Add LunarBase as a new Base DEX integration for the ETH/USDC pool.

Changes

  • Add LunarBase adapter and register it in the DEX index
  • Add Base config for pool 0x0000eFC4ec03a7c47D3a38A9Be7Ff1d52dD01b99
  • Add Pool ABI for quote, swap, state, reserves, pause, and fee multiplier reads
  • Add event-based state tracking for pool state, reserves, concentration, block delay, pause state, and blacklist fee multiplier
  • Port PMM exact-input quote math to TypeScript
  • Add calldata tests for ETH -> USDC and USDC -> ETH exact-input swaps

How it works

LunarBase supports SELL exact-input routing on Base. Pricing is computed locally from event-tracked pool state instead of calling the pool quote method on every request.

The pool uses native ETH as address(0), while ParaSwap uses the standard ETH sentinel. The adapter maps those addresses when building calldata.

Because current Velora executor addresses are not whitelisted in the pool, pricing uses the on-chain blacklistFeeMultiplier to avoid overestimating output.

Tests

  • pnpm run build
  • pnpm exec jest src/dex/lunar-base --runInBand
  • Live Base quote parity check against on-chain quoteXToY

Note

Medium Risk
New swap venue with ported on-chain PMM math and block-delay gating; quote or calldata mistakes could misprice routes or fail swaps, but scope is a single pool and SELL-only.

Overview
Adds LunarBase on Base as a new DEX: registered in the DEX index, wired to the ETH/USDC pool 0x0000…01b99, with a pool ABI and Base-specific config.

SELL exact-input routing only. Quotes use local PMM math (quoteXToY / quoteYToX) from event-tracked pool state (anchor price, reserves, fees, pause, blacklistFeeMultiplier, block delay)—not per-request on-chain quote* calls. Pricing applies the on-chain blacklist fee multiplier so non-whitelisted executors are not over-quoted. Native ETH is mapped to the pool’s address(0) when building swapExactInNative vs swapExactIn calldata (pool as spender for ERC-20 legs).

Includes unit tests for PMM math and swap calldata encoding.

Reviewed by Cursor Bugbot for commit 7b3795f. Bugbot is set up for automated code reviews on this repo. Configure here.

@NebulaNomadPixel NebulaNomadPixel marked this pull request as ready for review May 25, 2026 19:59
@NebulaNomadPixel NebulaNomadPixel changed the title feat: add DarkPools adapter on Base feat: add LunarBase adapter on Base May 27, 2026
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 7b3795f. Configure here.

if (state.anchorPrice === 0n) return false;
if (state.reserveX === 0n || state.reserveY === 0n) return false;

return blockNumber < state.latestUpdateBlock + state.blockDelay;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pool state usability check likely inverted for blockDelay

High Severity

The check blockNumber < state.latestUpdateBlock + state.blockDelay returns true during the delay window and false after it. If the on-chain pool uses blockDelay as an anti-front-running mechanism (blocking trades until the delay elapses), this is inverted — the adapter would quote prices exactly when the pool rejects swaps and stop quoting when the pool accepts them. Additionally, when blockDelay is 0 (meaning "no delay"), the check becomes blockNumber < latestUpdateBlock, which is effectively always false, making the pool permanently unusable.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7b3795f. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant