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

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions