Skip to content

feat(arbos60): add multi-gas constraints pricing model#700

Merged
damian-orzechowski merged 83 commits into
mainfrom
daniil/arbos60-multigas-constraints
May 25, 2026
Merged

feat(arbos60): add multi-gas constraints pricing model#700
damian-orzechowski merged 83 commits into
mainfrom
daniil/arbos60-multigas-constraints

Conversation

@AnkushinDaniil

@AnkushinDaniil AnkushinDaniil commented Mar 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

Implements ArbOS 60 multi-gas constraints pricing model with per-resource weights. Includes MultiGas tracking fixes and comparison mode test isolation improvements (merged from #723).

Key Features

Core Pricing Model

  • GasModel enum for routing: Legacy, SingleGasConstraints, MultiGasConstraints
  • Weighted backlog calculation with saturating arithmetic
  • Per-resource exponent calculation with MaxPricingExponentBips cap (85,000)
  • Input validation and bounds checking throughout
  • Production wiring: UpdateGasPool now calls GrowBacklog(computeGas, AccumulatedMultiGas) for ArbOS 60+

MultiGas Tracking (from #723)

  • Register receipt decoder so MultiGas fields persist correctly in storage
  • Track precompile output data as Computation gas
  • Track code deposit gas as StorageGrowth
  • Owner precompiles don't charge multigas (return zero gas)

Comparison Mode (from #723)

  • Reset BlockTree internal state (Head, BestKnownNumber) between tests via IResettableBlockTree
  • Add Genesis null checks to handle reinitialized state gracefully
  • Enable debug logging for troubleshooting

Architecture

Gas Model Selection

flowchart TD
    Start([GetGasModelToUse]) --> V60{ArbOS >= 60?}
    V60 -->|Yes| MC{MultiGasConstraints<br/>Length > 0?}
    MC -->|Yes| MGC[MultiGasConstraints]
    MC -->|No| V50
    V60 -->|No| V50{ArbOS >= 50?}
    V50 -->|Yes| SC{Constraints<br/>Length > 0?}
    SC -->|Yes| SGC[SingleGasConstraints]
    SC -->|No| LEG[Legacy]
    V50 -->|No| LEG

    style MGC fill:#22c55e,stroke:#16a34a,color:#000
    style SGC fill:#3b82f6,stroke:#2563eb,color:#000
    style LEG fill:#a1a1aa,stroke:#71717a,color:#000
Loading

Storage Layout

classDiagram
    class MultiGasConstraint {
        <<12 slots>>
        +ulong Target
        +uint AdjustmentWindow
        +ulong Backlog
        +ulong MaxWeight
        +ulong WeightedResources_8
        +GrowBacklog(MultiGas)
        +ShrinkBacklog(MultiGas)
    }

    class MultiGasFees {
        <<16 slots>>
        +UInt256 NextBlockFees_8
        +UInt256 CurrentBlockFees_8
        +CommitNextToCurrent()
    }

    class GasConstraint {
        <<3 slots - Legacy>>
        +ulong Target
        +ulong AdjustmentWindow
        +ulong Backlog
    }

    class ResourceKind {
        <<enum>>
        Unknown
        Computation
        HistoryGrowth
        StorageAccess
        StorageGrowth
        L1Calldata
        L2Calldata
        WasmComputation
    }

    MultiGasConstraint --> ResourceKind : weights per kind
    MultiGasFees --> ResourceKind : fees per kind
Loading

Pricing Update Flow (Per Block)

sequenceDiagram
    participant Block as Block Producer
    participant L2P as L2PricingState
    participant MGC as MultiGasConstraint
    participant MGF as MultiGasFees
    participant Storage as BaseFeeWei

    Block->>L2P: UpdatePricingModel(timePassed)
    
    Note over L2P: Model = MultiGasConstraints
    
    loop For each constraint
        L2P->>MGC: Get backlog, target
        L2P->>L2P: newBacklog = backlog - timePassed * target
        L2P->>MGC: SetBacklog(newBacklog)
    end
    
    L2P->>L2P: CalcMultiGasConstraintsExponents()
    Note over L2P: exponent = backlog * weight * BIPS / divisor
    
    loop For each ResourceKind
        L2P->>L2P: baseFee = minBaseFee * exp(exponent)
        L2P->>MGF: SetNextBlockFee(kind, baseFee)
    end
    
    L2P->>Storage: Set max of all baseFees
    
    Block->>L2P: CommitMultiGasFees()
    L2P->>MGF: CommitNextToCurrent()
    Note over MGF: nextBlockFees copied to currentBlockFees
Loading

Transaction Gas Tracking

flowchart LR
    subgraph TX [Transaction Execution]
        OP[EVM Opcode] -->|gas + resourceKind| ACC[Accumulate MultiGas]
    end

    subgraph GROW [Post-TX: UpdateGasPool → GrowBacklog]
        ACC -->|TxExecContext.AccumulatedMultiGas| UB[GrowBacklog]
        UB -->|for each constraint| WB[Weighted Update]
        WB -->|add weighted amount| MGC2[MultiGasConstraint]
    end

    subgraph SHRINK [Block End: ShrinkBacklog]
        TIME[timePassed * target] --> SB[ShrinkBacklog]
        SB -->|subtract capacity| MGC3[MultiGasConstraint]
    end

    style TX fill:#60a5fa,stroke:#3b82f6,color:#000
    style GROW fill:#f87171,stroke:#ef4444,color:#000
    style SHRINK fill:#4ade80,stroke:#22c55e,color:#000
Loading

Weighted Backlog Calculation

flowchart TD
    subgraph Input [Input]
        MG[MultiGas<br/>per-resource usage]
        W[Constraint Weights<br/>per-resource multiplier]
    end

    subgraph Calculation [Calculation]
        MG -->|amount| MUL[Multiply]
        W -->|weight| MUL
        MUL -->|saturating| WA[weightedAmount]
        WA -->|saturating add/sub| BL[totalBacklog]
    end

    subgraph Output [Output]
        BL --> SET[constraint.SetBacklog]
    end

    style Input fill:#fbbf24,stroke:#f59e0b,color:#000
    style Calculation fill:#c084fc,stroke:#a855f7,color:#000
    style Output fill:#4ade80,stroke:#22c55e,color:#000
Loading

System Test Validation

New logic has been validated by Nitro comparison system tests. The following 4 multi-gas specific tests were added to the passing list as part of this PR:

Test What it validates
TestSetAndGetGasPricingConstraints Single-gas constraint configuration round-trip
TestSetAndGetMultiGasPricingConstraints Multi-gas constraint configuration round-trip
TestMultiGasRefundForNormalTx Per-resource gas refund accounting for normal transactions
TestMultiGasRefundForRetryableTx Per-resource gas refund accounting for retryable transactions

These tests run in comparison mode against Nitro, validating state root parity at every block.

Total passing comparison tests: 46 (see tools/comparison/passing-tests.txt).


Unit & Integration Tests

  • MultiGasConstraintTests.cs — Storage operations, backlog updates (including Nitro-mirrored weighted accumulation tests)
  • MultiGasFeesTests.cs — Fee commit workflow
  • PricingModelMultiGasTests.cs — Pricing model equivalence tests
  • L2PricingStateTests.cs — Constraint lifecycle, exponent calculation

Dependencies

PR Repository Description
#10765 nethermind Submodule changes: IResettableBlockTree, MultiGas gas tracking in EVM
#723 nethermind-arbitrum MultiGas tracking fixes and comparison mode isolation (merged into this PR)

@AnkushinDaniil AnkushinDaniil force-pushed the daniil/arbos60-multigas-constraints branch 6 times, most recently from c1c7363 to f338aff Compare March 3, 2026 10:58
@codecov

codecov Bot commented Mar 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 65.71429% with 264 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.69%. Comparing base (03b251e) to head (69cba3f).

Files with missing lines Patch % Lines
...rmind.Arbitrum/Core/ResettableArbitrumBlockTree.cs 0.00% 87 Missing ⚠️
src/Nethermind.Arbitrum/Precompiles/ArbOwner.cs 0.00% 42 Missing ⚠️
...Arbitrum/Execution/ArbitrumTransactionProcessor.cs 42.55% 25 Missing and 2 partials ⚠️
src/Nethermind.Arbitrum/ArbitrumPlugin.cs 34.61% 16 Missing and 1 partial ⚠️
....Arbitrum/Rpc/ReceiptForRpcPolymorphicConverter.cs 0.00% 14 Missing ⚠️
...rbitrum/Genesis/ArbitrumGenesisStateInitializer.cs 45.45% 9 Missing and 3 partials ⚠️
src/Nethermind.Arbitrum/Arbos/ArbosState.cs 23.07% 9 Missing and 1 partial ⚠️
...rbitrum/Arbos/Storage/FilteredTransactionsState.cs 0.00% 10 Missing ⚠️
...mind.Arbitrum/Precompiles/Parser/ArbOwnerParser.cs 25.00% 9 Missing ⚠️
.../Nethermind.Arbitrum/Precompiles/ArbRetryableTx.cs 60.00% 4 Missing and 2 partials ⚠️
... and 12 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #700      +/-   ##
==========================================
- Coverage   76.11%   75.69%   -0.43%     
==========================================
  Files         234      241       +7     
  Lines       14150    14724     +574     
  Branches     2137     2223      +86     
==========================================
+ Hits        10770    11145     +375     
- Misses       2626     2806     +180     
- Partials      754      773      +19     
Files with missing lines Coverage Δ
src/Nethermind.Arbitrum/Arbos/ArbosAddresses.cs 100.00% <100.00%> (ø)
src/Nethermind.Arbitrum/Arbos/ArbosSubspaceIDs.cs 100.00% <100.00%> (ø)
src/Nethermind.Arbitrum/Arbos/Precompiles.cs 100.00% <100.00%> (ø)
...thermind.Arbitrum/Arbos/Programs/StylusPrograms.cs 73.31% <100.00%> (ø)
src/Nethermind.Arbitrum/Arbos/Programs/WasmGas.cs 87.69% <100.00%> (ø)
...Nethermind.Arbitrum/Arbos/Storage/GasConstraint.cs 100.00% <100.00%> (ø)
...rmind.Arbitrum/Arbos/Storage/MultiGasConstraint.cs 100.00% <100.00%> (ø)
.../Nethermind.Arbitrum/Arbos/Storage/MultiGasFees.cs 100.00% <100.00%> (ø)
...ethermind.Arbitrum/Arbos/Storage/RetryableState.cs 98.33% <100.00%> (ø)
src/Nethermind.Arbitrum/Config/ArbitrumConfig.cs 91.42% <100.00%> (+0.25%) ⬆️
... and 35 more

... and 2 files with indirect coverage changes

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

@AnkushinDaniil AnkushinDaniil marked this pull request as ready for review March 3, 2026 15:15
Copilot AI review requested due to automatic review settings March 3, 2026 15:15

Copilot AI left a comment

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.

Pull request overview

Implements ArbOS 60 multi-gas constraints pricing with per-resource weighted backlogs and per-resource base fees, and wires it into transaction processing and pricing updates.

Changes:

  • Added storage-backed MultiGasConstraint and MultiGasFees primitives for ArbOS 60+ multi-dimensional pricing.
  • Updated L2PricingState to select a GasModel, update multi-gas backlogs/exponents, and commit per-resource fees.
  • Integrated multi-gas backlog growth in tx processing and added extensive tests across pricing, storage, and precompile-related behaviors.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/Nethermind.Arbitrum/Math/MathExtensions.cs Adds inlining hints for saturating arithmetic helpers used by backlog math.
src/Nethermind.Arbitrum/Execution/ArbitrumTransactionProcessor.cs Routes gas pool/backlog updates by GasModel, wiring multi-gas growth.
src/Nethermind.Arbitrum/Evm/MultiGas.cs Adds CheckResourceKind helper and adjusts docs.
src/Nethermind.Arbitrum/Evm/ArbitrumGasPolicy.cs Tracks code deposit under StorageGrowth for multi-gas accounting.
src/Nethermind.Arbitrum/Arbos/Storage/MultiGasFees.cs New storage struct for next/current per-resource base fees with commit rotation.
src/Nethermind.Arbitrum/Arbos/Storage/MultiGasConstraint.cs New storage struct for weighted multi-resource constraints and weighted backlog updates.
src/Nethermind.Arbitrum/Arbos/Storage/L2PricingState.cs Core pricing/state changes: GasModel, multi-gas exponent calc, fee update/commit, backlog routing.
src/Nethermind.Arbitrum/Arbos/Storage/GasConstraint.cs Cleans up storage clearing via new Clear() methods; makes class sealed.
src/Nethermind.Arbitrum/Arbos/Storage/ArbosStorage.cs Adds Clear() to slot and storage-backed primitives.
src/Nethermind.Arbitrum/Arbos/ArbosVersion.cs Introduces version 60 constants / alias for multi-gas constraints enablement.
src/Nethermind.Arbitrum.Test/Precompiles/PrecompileContextTests.cs Adds tests for multi-gas tracking (some currently don’t exercise production code).
src/Nethermind.Arbitrum.Test/Precompiles/ConstraintsPrecompileTests.cs Adds tests around configuring and using multi-gas constraints.
src/Nethermind.Arbitrum.Test/Infrastructure/ArbosStateTestExtensions.cs Adds test-only helpers for reading/writing multi-gas fees.
src/Nethermind.Arbitrum.Test/Evm/MultiGasTests.cs Adds tests for CheckResourceKind validation behavior.
src/Nethermind.Arbitrum.Test/Arbos/Storage/L2PricingStateTests.cs Expands test coverage for gas model selection, backlog updates, multi-gas pricing, and guards.
src/Nethermind.Arbitrum.Test/Arbos/L2Pricing/PricingModelMultiGasTests.cs Adds equivalence tests across legacy/single/multi-gas models.
src/Nethermind.Arbitrum.Test/Arbos/L2Pricing/MultiGasFeesTests.cs Adds tests for per-resource fees and commit semantics.
src/Nethermind.Arbitrum.Test/Arbos/L2Pricing/MultiGasConstraintTests.cs Adds tests for weighted backlog math and storage behavior.
src/Nethermind.Arbitrum.Test/Arbos/ArbosStorageTests.BackedByType.cs Adds tests for new Clear() methods on storage-backed primitives.
src/Nethermind Updates submodule pointer.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Nethermind.Arbitrum/Execution/ArbitrumTransactionProcessor.cs Outdated
Comment thread src/Nethermind.Arbitrum/Arbos/Storage/L2PricingState.cs
Comment thread src/Nethermind.Arbitrum/Arbos/Storage/L2PricingState.cs
Comment thread src/Nethermind.Arbitrum/Arbos/Storage/L2PricingState.cs
Comment thread src/Nethermind.Arbitrum.Test/Precompiles/PrecompileContextTests.cs Outdated
Comment thread src/Nethermind.Arbitrum.Test/Precompiles/ConstraintsPrecompileTests.cs Outdated
Comment thread src/Nethermind.Arbitrum.Test/Infrastructure/ArbosStateTestExtensions.cs Outdated
wurdum
wurdum previously approved these changes Mar 4, 2026

@wurdum wurdum left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please add integration tests to make sure e2e compatibility with nitro

Comment thread src/Nethermind.Arbitrum/Arbos/Storage/L2PricingState.cs Outdated
Comment thread src/Nethermind.Arbitrum/Execution/ArbitrumTransactionProcessor.cs Outdated
Comment thread src/Nethermind.Arbitrum.Test/Arbos/Storage/L2PricingStateTests.cs Outdated
Comment thread src/Nethermind.Arbitrum.Test/Arbos/Storage/L2PricingStateTests.cs Outdated
Comment thread src/Nethermind.Arbitrum.Test/Precompiles/PrecompileContextTests.cs Outdated
@AnkushinDaniil

Copy link
Copy Markdown
Collaborator Author

Please add integration tests to make sure e2e compatibility with nitro

Added more tests. The next step in my plan is to adopt system tests

@AnkushinDaniil AnkushinDaniil force-pushed the daniil/arbos60-multigas-constraints branch 3 times, most recently from d900d77 to f55414e Compare March 4, 2026 15:26

Copilot AI commented Mar 5, 2026

Copy link
Copy Markdown
Contributor

@AnkushinDaniil I've opened a new pull request, #712, to work on those changes. Once the pull request is ready, I'll request review from you.

@svlachakis

svlachakis commented Mar 5, 2026

Copy link
Copy Markdown
Collaborator

I would wait for system tests inclusion for better stability and assurance. I don't think there is any reason to rush this..my humble opinion.

Add ArbOS 60 multi-gas constraints with per-resource weights:
- MultiGasConstraint: storage-backed constraint with weighted resources
- MultiGasFees: per-resource base fee storage (next-block/current-block)
- L2PricingState: constraint management, exponent calculation, pricing updates
- GasModel enum for routing: Legacy, SingleGasConstraints, MultiGasConstraints
- Input validation and bounds checking throughout
- Add Clear() to storage-backed types (ArbosStorageSlot, ArbosStorageBackedUInt/ULong/UInt256)
- Add MultiGas.CheckResourceKind() validation for defensive programming
- Throw InvalidOperationException on divisor == 0 instead of silent continue
- Move test-only methods to test project via extension methods
- Move weights dictionary inside loop to match reference implementation
In ArbOS 60+ (multi-gas constraints), BacklogUpdateCost returns a
static cost (StorageReadCost + StorageWriteCost) regardless of
constraint count. The C# implementation was missing this early
return and continued with additional overhead calculations.

Added tests to verify the static cost behavior in ArbOS 60 and
the dynamic cost calculation in ArbOS 51.
…ization

Performance improvements for multi-gas constraints implementation:

- Add [AggressiveInlining] to SaturateMul and SaturateSub for consistency
  with SaturateAdd (MathExtensions.cs)
- Seal leaf classes (MultiGasConstraint, GasConstraint, MultiGasFees,
  L2PricingState) to enable JIT devirtualization
- Replace yield iterator in CalcMultiGasConstraintsExponents with direct
  loop to avoid state machine allocation per-call
- Use inline array FeeBuffer instead of heap-allocated UInt256[] in
  MultiDimensionalPriceForRefund to eliminate per-transaction allocation
Add 24 tests to achieve full patch coverage:

- Exception guards: divisor-zero checks in CalcMultiGasConstraintsExponents
  and UpdatePricingModelMultiConstraints
- Migration path: SetMultiGasConstraintsFromSingleGasConstraints conversion,
  uint32 clamping, and clearing existing constraints
- Legacy pricing: GasPoolUpdateCost for ArbOS 49/50, legacy backlog
  grow/shrink, high backlog pricing
- Multi-gas fees: CommitMultiGasFees early return and commit paths,
  L1Calldata/zero fee fallback to baseFeeWei
- MultiGas: CheckResourceKind validation for valid and invalid kinds
- ArbosStorage: Clear methods for UInt, ULong, UInt256 backed storage
Remove ShouldUseGasConstraints() which was a C#-only helper that
didn't exist in Nitro. Use GetGasModelToUse() directly instead,
which matches Nitro's GasModelToUse() function.

Changes:
- Remove ShouldUseGasConstraints() from L2PricingState
- Update tests to use GetGasModelToUse() assertions
- Remove tests that directly tested the removed method
…sPool

UpdateGasPool now routes to GrowBacklog for ArbOS 60+ MultiGasConstraints mode,
matching Nitro's tx_processor behavior. Legacy and SingleGasConstraints modes
continue using AddToGasPool.

Added tests mirroring Nitro's TestMultiGasConstraintBacklogGrowth and
TestMultiGasConstraintBacklogDecay patterns for weighted accumulation.
Remove Arrange/Act/Assert comments from ConstraintsPrecompileTests
and PrecompileContextTests per code style guidelines.
@wurdum

wurdum commented Mar 25, 2026

Copy link
Copy Markdown
Collaborator

Well done. Figuring out where to put all these CommitMultiGasFees is crazy 🤯

…pport

The IJsonTypeInfoResolver approach (da1ebcb) broke polymorphic
serialization — ArbitrumReceiptForRpc properties (GasUsedForL1,
MultiGasUsed) were not serialized in comparison mode responses.
Revert to a custom JsonConverter<ReceiptForRpc> that delegates to
the runtime type, restoring correct receipt comparison.
- Remove unused `spec` variable in ArbitrumBlockProducer
- Replace `var` with explicit types (ReceiptForRpcPolymorphicConverter, TestArbosStorage)
- Introduce DisabledArbOsVersionOverride and make IArbOSVersionOverride required
- Split L2PricingStateTests into partial classes by feature area
@wurdum

wurdum commented May 18, 2026

Copy link
Copy Markdown
Collaborator

FYI: Looks like folks in OffchainLabs changed the list of multi-gas resources
https://github.com/OffchainLabs/go-ethereum/blob/v3.10.x-release/arbitrum/multigas/resources.go#L18

@damian-orzechowski

Copy link
Copy Markdown
Collaborator

FYI: Looks like folks in OffchainLabs changed the list of multi-gas resources https://github.com/OffchainLabs/go-ethereum/blob/v3.10.x-release/arbitrum/multigas/resources.go#L18

Updated with changes from: OffchainLabs/go-ethereum#636

Comment thread src/Nethermind.Arbitrum/Precompiles/ArbRetryableTx.cs Fixed
Comment thread src/Nethermind.Arbitrum/Arbos/Storage/L2PricingState.cs Fixed
Comment thread src/Nethermind.Arbitrum/Arbos/Storage/L2PricingState.cs Fixed
Comment thread src/Nethermind.Arbitrum/Arbos/Storage/MultiGasConstraint.cs Dismissed
Comment thread src/Nethermind.Arbitrum/Precompiles/ArbOwner.cs Fixed
Comment thread src/Nethermind.Arbitrum/Precompiles/ArbOwner.cs Dismissed
Comment thread src/Nethermind.Arbitrum/Precompiles/ArbOwner.cs Fixed
Comment thread src/Nethermind.Arbitrum/Precompiles/ArbOwner.cs Dismissed
Comment thread src/Nethermind.Arbitrum/Precompiles/ArbRetryableTx.cs Outdated
Comment thread src/Nethermind.Arbitrum/Precompiles/ArbRetryableTx.cs Outdated
Comment thread src/Nethermind.Arbitrum/Arbos/Storage/L2PricingState.cs
Comment thread src/Nethermind.Arbitrum/Evm/MultiGas.cs Outdated
@damian-orzechowski damian-orzechowski requested a review from wurdum May 22, 2026 14:15
Comment thread src/Nethermind.Arbitrum/Config/IArbitrumConfig.cs
Comment thread src/Nethermind.Arbitrum/Execution/ArbitrumBlockProcessor.cs
Comment thread src/Nethermind.Arbitrum/Execution/ArbitrumBlockValidationTransactionsExecutor.cs Outdated
@damian-orzechowski damian-orzechowski merged commit 7720aac into main May 25, 2026
14 checks passed
@damian-orzechowski damian-orzechowski deleted the daniil/arbos60-multigas-constraints branch May 25, 2026 12:02
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.

8 participants