Skip to content

feat: impl basefee change from FIP-0115#6702

Open
LesnyRumcajs wants to merge 9 commits intomainfrom
fip-0115-basefee
Open

feat: impl basefee change from FIP-0115#6702
LesnyRumcajs wants to merge 9 commits intomainfrom
fip-0115-basefee

Conversation

@LesnyRumcajs
Copy link
Member

@LesnyRumcajs LesnyRumcajs commented Mar 6, 2026

Summary of changes

Changes introduced in this pull request:

  • simplified some existing code,
  • ported basefee change from FIP-0115 from Lotus to Forest

Reference issue to close (if applicable)

Closes #6686

Other information and links

Don't merge before the reference is merged to Lotus master. There might be some additional changes there.

Change checklist

  • I have performed a self-review of my own code,
  • I have made corresponding changes to the documentation. All new code adheres to the team's documentation standards,
  • I have added tests that prove my fix is effective or that my feature works (if possible),
  • I have made sure the CHANGELOG is up-to-date. All user-facing changes should be reflected in this document.

Outside contributions

  • I have read and agree to the CONTRIBUTING document.
  • I have read and agree to the AI Policy document. I understand that failure to comply with the guidelines will lead to rejection of the pull request.

Summary by CodeRabbit

  • New Features
    • Implements FIP-0115: after the upgrade height, base fee may be driven by transaction premium percentiles (instead of solely by utilization).
  • Behavioral Change
    • Base fee calculation now considers unique senders/messages when determining fees, improving fee responsiveness.
  • Tests / Changelog
    • Expanded tests and changelog entry added to cover the new fee logic.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 6, 2026

Walkthrough

Implements FIP-0115: base fee computation now branches at a specified upgrade epoch to compute next base fee from sender premiums (using a weighted quick-select) instead of utilization; adds premium-based helpers, a weighted_quick_select module, constants, and updates call sites and tests.

Changes

Cohort / File(s) Summary
Core Base Fee Computation
src/chain/store/base_fee.rs
Added PLACEHOLDER_NEXT_UPGRADE_HEIGHT and BLOCK_GAS_TARGET_INDEX. Extended compute_base_fee signature to accept next_upgrade_height and branch between premium-based and utilization-based computation. Added helpers: compute_next_base_fee_from_premiums, compute_next_base_fee_from_premium, compute_next_base_fee_from_utlilization. Updated internal deduplication by (from, sequence) and tests.
Weighted Quick-Select Algorithm
src/chain/store/weighted_quick_select.rs
New module implementing weighted_quick_select(premiums, limits, target_index) to choose gas-weighted percentile premium. Includes unit and property-based tests and RNG usage.
Module Registration
src/chain/store/mod.rs
Registered new private module mod weighted_quick_select;.
Call Site Updates
src/chain_sync/tipset_syncer.rs, src/message_pool/msgpool/provider.rs, src/rpc/methods/miner.rs
Updated compute_base_fee invocations to pass PLACEHOLDER_NEXT_UPGRADE_HEIGHT as the additional argument.
Message Tests
src/message/mod.rs
Added unit tests for effective_gas_premium covering multiple fee scenarios.
Manifest
Cargo.toml, CHANGELOG.md
Cargo manifest lines changed; changelog updated with FIP-0115 entry.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • hanabi1224
  • akaladarshi
  • elmattic
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: impl basefee change from FIP-0115' accurately and concisely describes the main purpose of the PR.
Linked Issues check ✅ Passed The PR implements FIP-0115 base fee changes with new weighted-percentile premium logic, deduplication, and upgrade-height branching, matching requirements from issue #6686 to implement FIP-0115 client-side changes in Forest.
Out of Scope Changes check ✅ Passed All changes are directly related to FIP-0115 implementation: base fee computation logic, weighted selection algorithm, updated call sites, and related tests.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fip-0115-basefee

Comment @coderabbitai help to get the list of available commands and usage tips.

@LesnyRumcajs
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 6, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/chain/store/base_fee.rs`:
- Around line 13-17: The placeholder constant PLACEHOLDER_NEXT_UPGRADE_HEIGHT
(in src/chain/store/base_fee.rs) is disabling the FIP-0115 branch; replace this
compile-time MAX sentinel with a real activation epoch sourced from the network
configuration (e.g., add a field to your network/chain config struct or
ChainConfig and use that value instead of PLACEHOLDER_NEXT_UPGRADE_HEIGHT),
update all callers that currently import PLACEHOLDER_NEXT_UPGRADE_HEIGHT to read
the configured activation epoch (or accept it via function parameters) so the
premium-based branch can activate at runtime, and adjust any tests/fixtures to
inject the desired activation epoch for deterministic behavior.

In `@src/chain/store/weighted_quick_select.rs`:
- Around line 347-363: The property test prop_result_respects_weight_ordering is
vacuous because it sets target = pair.weight_high so the conditional `if target
< pair.weight_high` never runs; change how target is chosen (in the prop or
before calling weighted_quick_select) to produce a value strictly less than
pair.weight_high (for example pick target = pair.weight_low or generate target =
pair.weight_high - 1 ensuring non-negative), then call weighted_quick_select
with that target and assert the result equals
TokenAmount::from_atto(pair.high_premium) when target < pair.weight_high; adjust
logic around OrderedPremiumPair and TokenAmount conversions to match the chosen
target generation.
- Around line 30-31: Replace the panic-prone unwrap() call on
premiums.into_iter().next() with expect(...) that provides context; the
surrounding check uses limits.first().is_some_and(|&limit| limit > target_index)
so change premiums.into_iter().next().unwrap() to
premiums.into_iter().next().expect("expected at least one premium when
limits.first() indicates a valid target index") to document why next() is safe
and give a helpful error if it ever fails.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: c5ed8d65-73fa-4ce4-aebd-af197db579f3

📥 Commits

Reviewing files that changed from the base of the PR and between bbdcde9 and 5ce6520.

📒 Files selected for processing (7)
  • src/chain/store/base_fee.rs
  • src/chain/store/mod.rs
  • src/chain/store/weighted_quick_select.rs
  • src/chain_sync/tipset_syncer.rs
  • src/message/mod.rs
  • src/message_pool/msgpool/provider.rs
  • src/rpc/methods/miner.rs


/// Placeholder for the FIP-0115 activation height.
/// Replace with the actual network upgrade height once finalized.
pub const PLACEHOLDER_NEXT_UPGRADE_HEIGHT: ChainEpoch = ChainEpoch::MAX;
Copy link
Member Author

Choose a reason for hiding this comment

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

Tracking in #6704

@LesnyRumcajs LesnyRumcajs marked this pull request as ready for review March 9, 2026 09:33
@LesnyRumcajs LesnyRumcajs requested a review from a team as a code owner March 9, 2026 09:33
@LesnyRumcajs LesnyRumcajs requested review from akaladarshi and hanabi1224 and removed request for a team March 9, 2026 09:33
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/chain/store/weighted_quick_select.rs (1)

21-25: Assert the premiums/limits 1:1 contract.

zip will silently drop trailing entries if those vectors ever diverge, which would skew the selected premium without failing fast. A small guard here would make the invariant explicit in this consensus path.

♻️ Suggested guard
 pub fn weighted_quick_select(
     mut premiums: Vec<TokenAmount>,
     mut limits: Vec<u64>,
     mut target_index: u64,
 ) -> TokenAmount {
+    debug_assert_eq!(
+        premiums.len(),
+        limits.len(),
+        "premiums and limits must stay 1:1",
+    );
     loop {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/chain/store/weighted_quick_select.rs` around lines 21 - 25, Ensure the
1:1 invariant between premiums and limits in weighted_quick_select by adding an
explicit guard that checks premiums.len() == limits.len() (and fails with a
clear message if not) at the start of the function so zip cannot silently drop
entries; refer to the function weighted_quick_select and the parameters premiums
and limits when adding this assertion.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/chain/store/base_fee.rs`:
- Around line 58-72: The activation check in compute_base_fee is off-by-one:
since compute_base_fee receives the parent tipset (ts), change the condition
that selects compute_next_base_fee_from_premiums so it compares the child epoch
to next_upgrade_height by using ts.epoch() + 1 instead of ts.epoch(); update the
if in compute_base_fee to use ts.epoch() + 1 >= next_upgrade_height so the
premium rule calls compute_next_base_fee_from_premiums at the correct epoch,
otherwise continue to compute_next_base_fee_from_utlilization.

---

Nitpick comments:
In `@src/chain/store/weighted_quick_select.rs`:
- Around line 21-25: Ensure the 1:1 invariant between premiums and limits in
weighted_quick_select by adding an explicit guard that checks premiums.len() ==
limits.len() (and fails with a clear message if not) at the start of the
function so zip cannot silently drop entries; refer to the function
weighted_quick_select and the parameters premiums and limits when adding this
assertion.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 0675fdf2-09e1-46da-ad53-c63fe9e97969

📥 Commits

Reviewing files that changed from the base of the PR and between 5ce6520 and 34fc466.

📒 Files selected for processing (8)
  • CHANGELOG.md
  • src/chain/store/base_fee.rs
  • src/chain/store/mod.rs
  • src/chain/store/weighted_quick_select.rs
  • src/chain_sync/tipset_syncer.rs
  • src/message/mod.rs
  • src/message_pool/msgpool/provider.rs
  • src/rpc/methods/miner.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/rpc/methods/miner.rs
  • src/message/mod.rs
  • src/message_pool/msgpool/provider.rs

@codecov
Copy link

codecov bot commented Mar 9, 2026

Codecov Report

❌ Patch coverage is 92.34973% with 28 lines in your changes missing coverage. Please review.
✅ Project coverage is 63.54%. Comparing base (29a1d0b) to head (34fc466).

Files with missing lines Patch % Lines
src/chain/store/base_fee.rs 80.15% 25 Missing ⚠️
src/chain_sync/tipset_syncer.rs 57.14% 2 Missing and 1 partial ⚠️
Additional details and impacted files
Files with missing lines Coverage Δ
src/chain/store/weighted_quick_select.rs 100.00% <100.00%> (ø)
src/message/mod.rs 90.56% <100.00%> (+3.06%) ⬆️
src/message_pool/msgpool/provider.rs 39.13% <100.00%> (+4.24%) ⬆️
src/rpc/methods/miner.rs 7.91% <ø> (ø)
src/chain_sync/tipset_syncer.rs 63.21% <57.14%> (+0.37%) ⬆️
src/chain/store/base_fee.rs 87.03% <80.15%> (-12.09%) ⬇️

... and 10 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 29a1d0b...34fc466. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

implement FIP-0115

1 participant