From 7c911a62696dce7ef61bd96ac2a3b6d441b56d98 Mon Sep 17 00:00:00 2001 From: Alice Date: Mon, 12 Oct 2026 19:05:59 +0700 Subject: [PATCH] fix(bundler): make default maxFeePerGas floor chain-aware Fixes #15 prepareUserOperation used a hardcoded 3 gwei maxFeePerGas floor when neither the caller-supplied partialUserOp fields nor a custom estimateFeesPerGas callback provided fees. On L2s where base fees sit well below 1 gwei this inflates the worst-case spend (gasLimit x maxFeePerGas) that Gas Station policies check by 100-500x, rejecting otherwise-trivial UserOperations with a budget of ~0.01 USDC. Add defaultMaxFeePerGasFor(chainId) applying a 0.05 gwei floor on L2 chains where sub-gwei base fees are routine (Base, Base Sepolia, Arbitrum One and Sepolia, Optimism and OP Sepolia, Polygon and Amoy) and keep the conservative L1-tuned 3 gwei default for Ethereum mainnet and unknown chains. The max(estimated x 2) clamp is unchanged, so when the node estimates non-trivial fees they still win. The custom estimateFeesPerGas override path is untouched. --- .../core/apis/bundler/BundlerApiImpl.kt | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/src/main/java/com/circle/modularwallets/core/apis/bundler/BundlerApiImpl.kt b/lib/src/main/java/com/circle/modularwallets/core/apis/bundler/BundlerApiImpl.kt index e84c396..dd4481c 100644 --- a/lib/src/main/java/com/circle/modularwallets/core/apis/bundler/BundlerApiImpl.kt +++ b/lib/src/main/java/com/circle/modularwallets/core/apis/bundler/BundlerApiImpl.kt @@ -197,7 +197,7 @@ internal object BundlerApiImpl : BundlerApi { try { if (partialUserOp.maxFeePerGas == null || partialUserOp.maxPriorityFeePerGas == null) { if (estimateFeesPerGas == null) { - val defaultMaxFeePerGas = parseGwei("3") + val defaultMaxFeePerGas = defaultMaxFeePerGasFor(bundlerClient.chain.chainId) val defaultMaxPriorityFeePerGas = parseGwei("1") val two = BigInteger.valueOf(2) val fees = publicApi.estimateFeesPerGas( @@ -359,6 +359,22 @@ internal fun getUpdatedCalls(calls: Array): Array parseGwei("0.05") + else -> parseGwei("3") +} internal suspend fun startPolling( pollingInterval: Long, retryCount: Int,