Skip to content

Effective Gas Price should influence priority #237

@sekisamu

Description

@sekisamu

Description

When running Uniswap V3 Periphery test suite against a local Revive network, the test NonfungiblePositionManager → #mint → can use eth via multicall fails due to ETH balance assertion errors.

Environment

Steps to Reproduce

  1. Clone test repository:

    git clone https://github.com/papermoonio/v3-periphery-revm.git
    cd v3-periphery-revm
    npm install
  2. Start local Revive network at http://localhost:8545 (chainId: 420420420)

  3. Run the failing test:

    MOCHA_GREP="can use eth via multicall" npx hardhat test --network local test/NonfungiblePositionManager.spec.ts
  4. Observe the failure:

    1) NonfungiblePositionManager
         #mint
           can use eth via multicall:
    
       AssertionError: Expected "9999999986231533778449944922620"
                      to be equal 9999999986232742698599944922620
    

Debug Output

I've added some debug logging that help identifying the issue:

=== Revive Gas Price Compatibility Debug ===
Network Info:
  chainId: 420420420
  block.baseFeePerGas: undefined
  provider.getGasPrice(): 50.0 Gwei

Transaction:
  tx.gasPrice (requested): 100.0 Gwei
  receipt.gasUsed: 24178403

Balance Changes:
  balanceBefore: 9999999986231533778449944922620
  balanceAfter: 9999999986230324858299944922520
  actualCost: 1208920150000000100
  actualCost (ETH): 1.2089201500000001

Expected vs Actual:
  expectedCost (gasUsed × tx.gasPrice + 100): 2417840300000000100
  expectedCost (ETH): 2.4178403000000001
  difference: -1208920150000000000
  difference (ETH): -1.20892015

Revive Effective Gas Price Analysis:
  calculated effectiveGasPrice: 50.0 Gwei
  tx.gasPrice / effectiveGasPrice ratio: 2

Issue:
  Revive caps effective_gas_price = min(tx.gasPrice, base_fee)
  Test assumes effective_gas_price = tx.gasPrice
  This causes balance assertion to fail on Revive network
  Source: substrate/frame/revive/src/evm/api/rpc_types.rs:244
===========================================

Key Evidence:

  • Transaction sent with tx.gasPrice = 100 Gwei
  • Network base_fee = 50 Gwei
  • Actual cost calculated: effectiveGasPrice = 50 Gwei
  • Ratio: tx.gasPrice / effectiveGasPrice = 2 (transaction only paid 50% of requested gas price)
  • Balance difference: -1.20892015 ETH (exactly 50% of expected cost)

Analysis

Root Cause in Revive

File: substrate/frame/revive/src/evm/api/rpc_types.rs
Function: effective_gas_price() (Lines 234-245)

/// The gas price that is actually paid (including priority fee).
pub fn effective_gas_price(&self, base_gas_price: U256) -> Option<U256> {
    let effective_gas_price = if let Some(prio_price) = self.max_priority_fee_per_gas {
        let max_price = self.max_fee_per_gas?;
        Some(max_price.min(base_gas_price.saturating_add(prio_price)))
    } else {
        self.gas_price
    };

    // we do not implement priority fee as it does not map to tip well
    // hence the effective gas price cannot be higher than the base price
    effective_gas_price.map(|e| e.min(base_gas_price))  // ← Line 244: Caps at base_fee
    //                         ^^^^^^^^^^^^^^^^^^^^^^^
}

Ethereum Standard Behavior

On standard Ethereum networks (including Hardhat):

  • Legacy transactions: effective_gas_price = tx.gasPrice
  • EIP-1559 transactions: effective_gas_price = min(maxFeePerGas, baseFee + maxPriorityFeePerGas)
  • Users can set tx.gasPrice above baseFee and pay the requested amount

Revive's Behavior

According to the comment in the code:

"we do not implement priority fee as it does not map to tip well"

Revive enforces:

  • effective_gas_price ≤ base_gas_price always
  • Even for legacy transactions where users explicitly set gasPrice
  • This breaks compatibility with contracts/tests that calculate costs using tx.gasPrice

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions