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
-
Clone test repository:
git clone https://github.com/papermoonio/v3-periphery-revm.git
cd v3-periphery-revm
npm install
-
Start local Revive network at http://localhost:8545 (chainId: 420420420)
-
Run the failing test:
MOCHA_GREP="can use eth via multicall" npx hardhat test --network local test/NonfungiblePositionManager.spec.ts
-
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
Description
When running Uniswap V3 Periphery test suite against a local Revive network, the test
NonfungiblePositionManager → #mint → can use eth via multicallfails due to ETH balance assertion errors.Environment
Steps to Reproduce
Clone test repository:
git clone https://github.com/papermoonio/v3-periphery-revm.git cd v3-periphery-revm npm installStart local Revive network at
http://localhost:8545(chainId: 420420420)Run the failing test:
Observe the failure:
Debug Output
I've added some debug logging that help identifying the issue:
Key Evidence:
tx.gasPrice = 100 Gweibase_fee = 50 GweieffectiveGasPrice = 50 Gweitx.gasPrice / effectiveGasPrice = 2(transaction only paid 50% of requested gas price)-1.20892015 ETH(exactly 50% of expected cost)Analysis
Root Cause in Revive
File:
substrate/frame/revive/src/evm/api/rpc_types.rsFunction:
effective_gas_price()(Lines 234-245)Ethereum Standard Behavior
On standard Ethereum networks (including Hardhat):
effective_gas_price = tx.gasPriceeffective_gas_price = min(maxFeePerGas, baseFee + maxPriorityFeePerGas)tx.gasPriceabovebaseFeeand pay the requested amountRevive's Behavior
According to the comment in the code:
Revive enforces:
effective_gas_price ≤ base_gas_pricealwaysgasPricetx.gasPrice