Skip to content

feat(lunarbase): support v0.4.1 pools and BSC indexing - #1445

Open
ThomasAqu1nas wants to merge 4 commits into
propeller-heads:mainfrom
Lunarbase-Lab:v0.4.1
Open

ThomasAqu1nas wants to merge 4 commits into
propeller-heads:mainfrom
Lunarbase-Lab:v0.4.1

Conversation

@ThomasAqu1nas

Copy link
Copy Markdown
Contributor

Pool v0.4 applies punishment to the current swap and changes the directional fees used by later quotes. The previous LunarBase integration used the older math and state schema, so updating the ABI alone could leave simulated quotes inconsistent with the pool.

This change updates LunarBase to Pool v0.4.1 and adds BSC indexing:

  • Use lunarbase-pmm-math 0.4.1, the full uint160 anchor, maximum punishment, and indexed caller fee policy.
  • Carry reserves and directional fees through consecutive simulated swaps; refresh oracle age only on operator updates and advance it with blocks.
  • Index the new events and bootstrap complete state from verified Base/BSC parent snapshots. Keep the full runtime ABI while generating bindings for the nine consumed events.
  • Add the BSC manifest, replay fixtures and the necessary test-harness registrations.

Substreams package 0.2.0 changes the state schema. It requires the matching simulator and a fresh replay for the configured quote caller.

Validation at 4e1b7a0bf4e0e18423bb32d999f1937f7a79da8b in the fork:

  • Rust CI: 1,169 unit tests and 141 PostgreSQL tests passed; formatting, strict Clippy, Rustdoc and no-default-features checks passed. The Retry-After timing test that failed locally passed here.
  • Substreams CI: LunarBase native/WASM builds, lint and all 19 tests passed.
  • Cargo machete and PR-title validation passed.
  • Locally, all 34 LunarBase simulation tests passed with all features. The current remote workflow filters do not execute these tests.
  • A trial merge with upstream d58c29d2ab71fb3821f4ce4eff22d3edf0803583 has no conflicts and retains only the 30 changed files.

Draft validation limits:

  • Security Audit fails on RUSTSEC-2026-0285 for rustls 0.23.31, inherited unchanged from the branch base. This commit changes only lunarbase-pmm-math in the root lockfile. Current upstream already uses rustls 0.23.45.
  • Full Substreams/RPC integration has not run. The fork has no archive RPC/Substreams secrets; its integration and EVM/RPC runs were cancelled. Production BSC executor registration is unverified.
  • The existing integration composite action exports PROTOCOL, while Docker Compose reads PROTOCOLS; this also needs to be reconciled for a complete range run. No general workflow changes are included here.

Update punishment math, indexed state, and caller-dependent fees while
preserving oracle freshness across blocks and consecutive swaps. Add
verified Base/BSC bootstrap snapshots and BSC test-harness wiring.
@socket-security

socket-security Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedcargo/​lunarbase-pmm-math@​0.2.4 ⏵ 0.4.110010093100100

View full report

Comment thread protocols/substreams/base-lunarbase/src/modules/1_map_protocol_components.rs Outdated
Comment thread protocols/substreams/base-lunarbase/src/modules/3_map_protocol_changes.rs Outdated
) -> tycho::ProtocolComponent {
tycho::ProtocolComponent::new(&component_id(pool))
.with_tokens(&[token_x, token_y])
.with_attributes(&[("quote_caller", quote_caller)])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What does quote_caller do? Can we just assume the Tycho Router fee is zero?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'd suggest removing quote_caller in the substreams and quote_caller_whitelisted in the simulation. We can just assume the Tycho router is whitelisted. Otherwise, if we ever change the router, we'd have to update the substreams and do a full resync, which is a lot of extra work.

Comment thread crates/tycho-simulation/src/evm/protocol/lunarbase/state.rs
@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@ThomasAqu1nas

Copy link
Copy Markdown
Contributor Author

I have read the PropellerHeads CLA and I hereby sign the CLA

@zach030
zach030 marked this pull request as ready for review October 6, 2026 05:58
Direction::XToY => (q96, anchor),
Direction::YToX => (anchor, q96),
};
let probe = (BigUint::from(reserve_out) * &numerator / &denominator) * numerator / denominator;

@zach030 zach030 Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The empty-input-reserve probe can report zero limits for a tradable direction because these two divisions round down, while quote_limit only reduces the input after a rejected quote.

I reproduced this with a fresh, unpaused pool, zero fees and punishment, reserve_x = 0, reserve_y = 1, and anchor_price_x96 = 3 * Q96 / 4. For X -> Y:

  • This probe evaluates to floor(floor(1 / 0.75) / 0.75) = 1.
  • Quoting input 1 produces zero output, so quote_limit halves the input to zero and returns (0, 0).
  • However, input 3 is valid: the actual quote is floor(floor(3 * 0.75) * 0.75) = 1, and quote_exact_in(3) succeeds.

A temporary regression test confirmed that the direct quote succeeds while get_limits returns (0, 0). Consumers relying on these limits will skip this tradable direction.

Could we derive the probe from the quote's exact rounding rules, or distinguish an input that is too small to produce output from an input that exceeds the available liquidity, rather than halving both cases?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[P2] Reconfirmed on b68828334: this also affects the reverse direction and small nonzero input reserves.

A temporary regression test exercised fresh, unpaused states with zero fees and punishment, output reserve = 1, and these four cases:

Direction Anchor Input reserve quote_exact_in(3) output get_limits
X → Y 3 * Q96 / 4 0 1 (0, 0)
X → Y 3 * Q96 / 4 1 1 (0, 0)
Y → X floor(4 * Q96 / 3) 0 1 (0, 0)
Y → X floor(4 * Q96 / 3) 1 1 (0, 0)

With input reserve 1, the soft_limit branch starts at 2, which is still too small to produce output. Halving after rejection then incorrectly concludes that the direction has no capacity. Consumers using these limits will skip a tradable direction.

Please make the probe/search account for the minimum input needed to produce positive output, distinguishing undersized quotes from quotes exceeding available capacity. Regression coverage should include both directions and both zero and small nonzero input reserves. These are synthetic rounding-boundary cases, not observed mainnet failures; the existing 36 LunarBase tests pass but do not catch them.

…ltiplier

- Removed `quote_caller` from bootstrap states and protocol components.
- Eliminated `blacklist_fee_multiplier` and related events from the ABI and state management.
- Updated JSON bootstrap files to reflect changes in attributes.
- Adjusted integration tests to account for the removal of quote_caller.
- Cleaned up event handling logic to ignore deprecated events.
- Simplified configuration parsing by removing quote_caller requirement.
Comment on lines +11 to +12
# This historical range predates router whitelisting. Execution comparison
# requires a whitelisted router; recapture a later range for on-chain parity.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[P2] Update the Base execution fixture to satisfy the whitelist assumption

The simulator now always uses fee multiplier 1, but this range still ends at block 51297765, where the configured Base router (0xAbA5B53b03eAfaD1C5fc8BD5Fc765fC85Bb3de67) is not whitelisted and pays multiplier 100. Execution comparison remains enabled, and the harness does not override LunarBase's whitelist. Adding this comment does not make the configured test environment satisfy the new assumption.

I read the pool state and quotes at block 51297765, using that router as from, and passed the same state into the current simulator:

Direction / input On-chain quote Current simulator
X → Y / 0.001 ETH 2,390,779 2,511,757
Y → X / 1 USDC 393,595,800,163,007 397,890,571,043,066

Both differences exceed the harness's 0.5% execution tolerance. Passing multiplier 100 into the math library reproduces the on-chain outputs exactly, isolating the caller-policy mismatch. These are block-pinned quote comparisons; I did not run the full range/fork execution test.

Please recapture the parent snapshot and range for an execution router verified to have multiplier-one policy, or explicitly configure and validate a whitelisted fork environment and document that state override. Keep the two-direction execution comparison enabled so this test validates the model it now assumes.

This branch is waiting to be deployed

1 waiting deployment
integration-tests — c8273e9a Waiting Oct 13, 2026 by ThomasAqu1nas via EVM tests (requires RPC) #2479
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

2 participants