Moonbeam RPC Significant Gas Underestimation in UniswapInterfaceMulticall Static Calls
Problem Description
When using UniswapInterfaceMulticall.callStatic.multicall() for gas estimation on Moonbeam mainnet, RPC nodes consistently underestimate the actual gas requirements, causing transactions to fail with out-of-gas errors.
Technical Details
Chain Affected: Moonbeam Mainnet (Chain ID: 1284)
Root Cause:
callStatic.multicall()returnsgasUsedvalues that are lower than actual execution requirements- The internal gas accounting in
UniswapInterfaceMulticallappears to be simulated incorrectly by Moonbeam RPC nodes - Other EVM chains simulate this correctly
Reproduction Steps
Method 1: Direct Contract Interaction
- Deploy or use existing UniswapInterfaceMulticall contract on Moonbeam
- Create multiple (permissionless/open) calls that consume significant gas (e.g., complex DeFi operations, state changes)
- Use
callStatic.multicall(calls)to get gas estimates - Execute actual
multicall(calls)transaction using the estimated gas - Observe transaction failure due to insufficient gas
Method 2: Synthetic Test Case
// Deploy a gas-consuming test contract
contract GasConsumer {
mapping(uint256 => uint256) public data;
function consumeGas(uint256 iterations) external {
for(uint256 i = 0; i < iterations; i++) {
data[i] = i * 2;
}
}
}
Then test with multicall:
// assuming the actual gas limit is guaranteed to be < 500000 we allocate at most that for each call
const calls = [
{ target: gasConsumer.address, gasLimit: 500000, callData: gasConsumer.interface.encodeFunctionData('consumeGas', [100]) },
{ target: gasConsumer.address, gasLimit: 500000, callData: gasConsumer.interface.encodeFunctionData('consumeGas', [150]) }
];
// This will underestimate
const staticResult = await multicall.callStatic.multicall(calls);
console.log('Estimated gas:', staticResult.returnData.map(r => r.gasUsed));
// This may fail
const tx = await multicall.multicall(calls);
Error Pattern
Transaction Status: 0 (reverted) Gas Used: [Full gas limit] (indicating out-of-gas) Error: CALL_EXCEPTION
Impact
- Applications relying on accurate gas estimation face transaction failures
- Gas fees are wasted on failed transactions
- Automated systems (keepers, bots) cannot operate reliably
Current Workarounds
- Disable gas estimation and use static gas limits
- Apply significant gas buffers (50%+ markup)
- Use alternative gas estimation methods
Chain Comparison
- Working chains: Ethereum, Polygon, Arbitrum, Base, and many other EVM chains
- Problematic: Moonbeam mainnet specifically
- Note: This issue is unique to Moonbeam's RPC gas simulation, the issue is on a few Moonbeam RPCs such as https://1rpc.io/glmr and https://moonbeam.unitedbloc.com
UniswapInterfaceMulticall Contract
The issue occurs in the internal gas accounting:
uint256 gasLeftBefore = gasleft();
(bool success, bytes memory ret) = target.call{gas: gasLimit}(callData);
uint256 gasUsed = gasLeftBefore - gasleft();
Can you try using eth_estimateGas RPC?
Moonbeam has 3 gas factors, the standard gasmeter, the PoV gas and Storage growth gas. This is most likely happens only when PoV gas or Storage growth gas are the winning factors. We will try to have a look into this, and possibly improve it for future releases.
For now, you should use eth_estimateGas RPC, it is the standard way for estimating gas.
@RomarQ eth_estimateGas would only return the gas estimation for the entire tx, I would like to get an estimate for each call within the multicall() which requires eth_call(as this returns the multicall result).