-
Notifications
You must be signed in to change notification settings - Fork 271
fix(rpc): eth_estimateGas returns ~6x inflated gas for calls array format #3178
Description
Summary
eth_estimateGas returns ~305k gas for a TIP-20 transfer when the request uses the calls array format, vs ~50k when using to+data format. Since viem always converts to calls format for Tempo TXs, every gas estimate from the wallet is inflated ~6x.
Repro
# Correct: to+data format → ~53k ✅
curl -s -X POST https://rpc.moderato.tempo.xyz \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_estimateGas","params":[{"type":"0x45","from":"0xa522504eebb35e9e1dbd02ffd37dffdb24afec3b","to":"0x20c0000000000000000000000000000000000002","data":"0xa9059cbb0000000000000000000000003e144273d5e4a115c80d46b84d0c5eedbc361a4a00000000000000000000000000000000000000000000000000000000000f4240","nonce":"0x0","nonceKey":"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","validBefore":"0x69b9b005","feeToken":"0x20c0000000000000000000000000000000000002"}],"id":1}' | jq .
# Inflated: calls format → ~309k ❌
curl -s -X POST https://rpc.moderato.tempo.xyz \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_estimateGas","params":[{"type":"0x45","from":"0xa522504eebb35e9e1dbd02ffd37dffdb24afec3b","calls":[{"to":"0x20c0000000000000000000000000000000000002","data":"0xa9059cbb0000000000000000000000003e144273d5e4a115c80d46b84d0c5eedbc361a4a00000000000000000000000000000000000000000000000000000000000f4240","value":"0x0"}],"nonce":"0x0","nonceKey":"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","validBefore":"0x69b9b005","feeToken":"0x20c0000000000000000000000000000000000002"}],"id":1}' | jq .Root Cause
In crates/revm/src/handler.rs:739:
if !nonce_key.is_zero() && tx.kind().is_create() && caller_account.nonce() == 0 {
evm.initial_gas += cfg.gas_params().get(GasId::new_account_cost()); // +250,000
}When calls format is used, inner.to is None (viem clears to/data and wraps them in a calls array). This makes tx.kind() return Create. Combined with expiring nonce (nonce = 0), this incorrectly triggers +250,000 gas (new_account_cost) even though the actual calls in aa_calls are all CALLs, not contract deployments.
When to+data is sent directly, inner.to is set, so tx.kind() returns Call and the check is correctly skipped.
Impact
- Every Tempo TX gas estimate from viem/wagmi is ~6x too high for TIP-20 transfers
- TIP-1010 targets ~50k gas / $0.001 per transfer, but wallets show ~$0.006
- Affects max-send calculations (users cannot send their full balance)
Suggested Fix
For AA transactions, this check should inspect aa_calls instead of tx.kind() from the inner TxEnv — tx.kind() is meaningless for AA batch transactions since execute_multi_call overrides it per-call anyway.
Workaround
Call eth_estimateGas with to+data format directly, bypassing viem's formatter which converts to calls.