Skip to content

fix/mantle lack operator fee#8837

Open
jeremytsng wants to merge 2 commits into
mainfrom
fix/mantle-lack-operator-fee
Open

fix/mantle lack operator fee#8837
jeremytsng wants to merge 2 commits into
mainfrom
fix/mantle-lack-operator-fee

Conversation

@jeremytsng
Copy link
Copy Markdown
Contributor

@jeremytsng jeremytsng commented May 18, 2026

Explanation

We observed the confirmation screen showing 0.10 MNT for a transaction that ended up costing 0.12 MNT — the ~0.02 MNT delta is the operator-fee component of Mantle's Arsia gas model, which never reached the displayed total.

Root cause is in OracleLayer1GasFeeFlow.#getOperatorLayer1GasFee: the method skips the operator-fee oracle call whenever transactionMeta.gasUsed is unset. That field is populated by the transaction simulation backend, and Mantle is not in its supported-networks list — getBalanceChanges throws SimulationChainNotSupportedError, the catch returns gasUsed: undefined, and the operator-fee path silently collapses to zero for the entire pre-confirmation lifecycle (initial render, gas-fee poller re-poll, edit-gas). The UI sums layer1GasFee straight into the displayed total in useFeeCalculations.ts, so the dropped operator fee flows directly to the user.

The fix introduces a protected getOperatorFeeGas hook on OracleLayer1GasFeeFlow. The base default returns transactionMeta.gasUsed, so OptimismLayer1GasFeeFlow, ScrollLayer1GasFeeFlow, and any other current or future subclass keep their existing behaviour. MantleLayer1GasFeeFlow overrides the hook to fall back to txParams.gas ?? txParams.gasLimit when gasUsed is unavailable.

The transaction's gas limit is an upper bound on actual gas used (it carries the updateGas buffer when populated by the controller, and is the caller-supplied value otherwise). Mantle's operator-fee oracle is strictly linear in its input gas (verified on-chain at 0x420000000000000000000000000000000000000FgetOperatorFee(21000) = 2.1e14, getOperatorFee(500000) = 5e15, same per-gas rate), so the operator fee returned for a gas-limit input is an upper bound on the realised operator fee. The displayed total will be a hair above the actual on-chain cost rather than under-reporting it. This matches the over-estimate direction already used for the Optimism L1 data fee.

Caller coverage with the override in place:

  • Confirmation screen (addTransaction flow): updateGas populates txParams.gas in #updateGasProperties before updateTransactionLayer1GasFee runs in the same method.
  • GasFeePoller 10s re-poll: reads the same txParams.gas from state.
  • updateEditableParams (user edits gas): uses the new txParams.gas after the edit.
  • Bridge L1-fee path: bridge-controller's appendL1GasFees is allowlisted to Optimism + Base only today, so Mantle quotes don't reach this code. The ?? gasLimit arm future-proofs the bridge getLayer1GasFee call shape if Mantle is added later.

References

Fixes the operator-fee under-reporting flagged by the Mantle team following the Arsia gas model rollout.

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Low Risk
Low risk: adds an overridable hook to choose the gas value for the operator-fee oracle and updates Mantle to fall back to txParams.gas/txParams.gasLimit, with focused unit-test coverage.

Overview
Fixes Mantle L1 fee under-reporting when simulation data is missing. OracleLayer1GasFeeFlow now uses a new protected getOperatorFeeGas hook (defaulting to transactionMeta.gasUsed) to decide whether/what to pass to getOperatorFee.

MantleLayer1GasFeeFlow overrides this hook to fall back to txParams.gas ?? txParams.gasLimit when gasUsed is unavailable, and the Mantle fee-flow tests are expanded to cover the new fallback/skip behavior. The transaction-controller changelog documents the fix.

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

…d` is missing

`OracleLayer1GasFeeFlow` skipped the operator-fee oracle call whenever
`transactionMeta.gasUsed` was unset. Mantle has no value for `gasUsed`
during the pre-confirmation lifecycle, so the operator fee silently
collapsed to zero and the displayed L1 fee under-reported the actual
on-chain cost.

Expose a `protected getOperatorFeeGas` hook on the base flow so
subclasses can supply a fallback value, and override it in
`MantleLayer1GasFeeFlow` to fall back to `txParams.gas` (or
`txParams.gasLimit`) when `gasUsed` is not available. Gas limit is an
upper bound on actual gas used, so the resulting operator fee
over-estimates rather than under-reports.
@jeremytsng jeremytsng force-pushed the fix/mantle-lack-operator-fee branch from d661f99 to 08620b9 Compare May 18, 2026 07:04
@jeremytsng jeremytsng self-assigned this May 18, 2026
@jeremytsng jeremytsng marked this pull request as ready for review May 18, 2026 07:22
@jeremytsng jeremytsng requested review from a team as code owners May 18, 2026 07:22
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.

1 participant