From b087b8cfa684da91a422db841f4a1929e38bda41 Mon Sep 17 00:00:00 2001
From: mouseless <97399882+mouseless-eth@users.noreply.github.com>
Date: Fri, 24 Jan 2025 02:22:05 +0000
Subject: [PATCH 1/4] add resubmit timeout flag

---
 src/cli/alto.ts                 |   3 +
 src/cli/config/bundler.ts       |  86 +++++++++--------
 src/cli/config/options.ts       | 159 +++++++++++++++++---------------
 src/executor/executor.ts        |   8 +-
 src/executor/executorManager.ts |   5 +-
 5 files changed, 143 insertions(+), 118 deletions(-)

diff --git a/src/cli/alto.ts b/src/cli/alto.ts
index 7c01c932..ff000bf0 100644
--- a/src/cli/alto.ts
+++ b/src/cli/alto.ts
@@ -7,6 +7,7 @@ import {
     bundlerOptions,
     compatibilityOptions,
     debugOptions,
+    executorOptions,
     gasEstimationOptions,
     logOptions,
     rpcOptions,
@@ -71,6 +72,8 @@ export function getAltoCli(): yargs.Argv {
         .group(Object.keys(compatibilityOptions), "Compatibility Options:")
         .options(serverOptions)
         .group(Object.keys(serverOptions), "Server Options:")
+        .options(executorOptions)
+        .group(Object.keys(executorOptions), "Executor Options:")
         .options(rpcOptions)
         .group(Object.keys(rpcOptions), "RPC Options:")
         .options(logOptions)
diff --git a/src/cli/config/bundler.ts b/src/cli/config/bundler.ts
index e45316ab..17a04e13 100644
--- a/src/cli/config/bundler.ts
+++ b/src/cli/config/bundler.ts
@@ -27,43 +27,7 @@ export const bundlerArgsSchema = z.object({
             return validatedAddresses
         }),
     "deterministic-deployer-address": addressSchema,
-    "entrypoint-simulation-contract": z.preprocess(
-        (v) => (v === "" ? undefined : v),
-        addressSchema.optional()
-    ),
-    "refill-helper-contract": addressSchema.optional(),
-    "no-profit-bundling": z.boolean(),
     "safe-mode": z.boolean(),
-    "utility-private-key": hexData32Schema
-        .transform((val) => privateKeyToAccount(val) satisfies Account)
-        .optional(),
-    "utility-wallet-monitor": z.boolean(),
-    "utility-wallet-monitor-interval": z.number(),
-    "executor-private-keys": z.union([
-        z
-            .array(hexData32Schema)
-            .transform((vals) =>
-                vals.map((val) => privateKeyToAccount(val) satisfies Account)
-            ),
-        z
-            .string()
-            .regex(/^0x(?:[0-9a-f]{2}){32}(?:,0x(?:[0-9a-f]{2}){32})*$/)
-            .transform((val) =>
-                val
-                    .split(",")
-                    .map(
-                        (val) =>
-                            privateKeyToAccount(val as Hex) satisfies Account
-                    )
-            )
-    ]),
-    "max-executors": z.number().int().min(0).optional(),
-    "min-executor-balance": z
-        .string()
-        .transform((val) => BigInt(val))
-        .optional(),
-    "executor-refill-interval": z.number().int().min(0),
-    "executor-gas-multiplier": z.string().transform((val) => BigInt(val)),
 
     "min-entity-stake": z.number().int().min(0),
     "min-entity-unstake-delay": z.number().int().min(0),
@@ -119,12 +83,48 @@ export const bundlerArgsSchema = z.object({
                 ","
             )}`
         ),
-    "refilling-wallets": z.boolean().default(true),
-    "aa95-gas-multiplier": z.string().transform((val) => BigInt(val)),
     "enable-instant-bundling-endpoint": z.boolean(),
     "enable-experimental-7702-endpoints": z.boolean()
 })
 
+export const executorArgsSchema = z.object({
+    "resubmit-timeout": z.number().int().min(0).default(15_000),
+    "refilling-wallets": z.boolean().default(true),
+    "aa95-gas-multiplier": z.string().transform((val) => BigInt(val)),
+    "refill-helper-contract": addressSchema.optional(),
+    "no-profit-bundling": z.boolean(),
+    "utility-private-key": hexData32Schema
+        .transform((val) => privateKeyToAccount(val) satisfies Account)
+        .optional(),
+    "utility-wallet-monitor": z.boolean(),
+    "utility-wallet-monitor-interval": z.number(),
+    "executor-private-keys": z.union([
+        z
+            .array(hexData32Schema)
+            .transform((vals) =>
+                vals.map((val) => privateKeyToAccount(val) satisfies Account)
+            ),
+        z
+            .string()
+            .regex(/^0x(?:[0-9a-f]{2}){32}(?:,0x(?:[0-9a-f]{2}){32})*$/)
+            .transform((val) =>
+                val
+                    .split(",")
+                    .map(
+                        (val) =>
+                            privateKeyToAccount(val as Hex) satisfies Account
+                    )
+            )
+    ]),
+    "max-executors": z.number().int().min(0).optional(),
+    "min-executor-balance": z
+        .string()
+        .transform((val) => BigInt(val))
+        .optional(),
+    "executor-refill-interval": z.number().int().min(0),
+    "executor-gas-multiplier": z.string().transform((val) => BigInt(val))
+})
+
 export const compatibilityArgsSchema = z.object({
     "chain-type": z.enum([
         "default",
@@ -199,6 +199,10 @@ export const debugArgsSchema = z.object({
 })
 
 export const gasEstimationArgsSchema = z.object({
+    "entrypoint-simulation-contract": z.preprocess(
+        (v) => (v === "" ? undefined : v),
+        addressSchema.optional()
+    ),
     "binary-search-tolerance-delta": z
         .string()
         .transform((val) => BigInt(val))
@@ -234,6 +238,9 @@ export type IBundlerArgsInput = z.input<typeof bundlerArgsSchema>
 export type ICompatibilityArgs = z.infer<typeof compatibilityArgsSchema>
 export type ICompatibilityArgsInput = z.input<typeof compatibilityArgsSchema>
 
+export type IExecutorArgs = z.infer<typeof executorArgsSchema>
+export type IExecutorArgsInput = z.input<typeof executorArgsSchema>
+
 export type IServerArgs = z.infer<typeof serverArgsSchema>
 export type IServerArgsInput = z.input<typeof serverArgsSchema>
 
@@ -256,7 +263,8 @@ export const optionArgsSchema = z.object({
     ...serverArgsSchema.shape,
     ...rpcArgsSchema.shape,
     ...debugArgsSchema.shape,
-    ...gasEstimationArgsSchema.shape
+    ...gasEstimationArgsSchema.shape,
+    ...executorArgsSchema.shape
 })
 
 export type IOptions = z.infer<typeof optionArgsSchema>
diff --git a/src/cli/config/options.ts b/src/cli/config/options.ts
index 493f0b39..65743efe 100644
--- a/src/cli/config/options.ts
+++ b/src/cli/config/options.ts
@@ -4,6 +4,7 @@ import type {
     IBundlerArgsInput,
     ICompatibilityArgsInput,
     IDebugArgsInput,
+    IExecutorArgsInput,
     IGasEstimationArgsInput,
     ILogArgsInput,
     IOptionsInput,
@@ -25,56 +26,6 @@ export const bundlerOptions: CliCommandOptions<IBundlerArgsInput> = {
         require: false,
         default: "0x4e59b44847b379578588920ca78fbf26c0b4956c"
     },
-    "entrypoint-simulation-contract": {
-        description: "Address of the EntryPoint simulations contract",
-        type: "string",
-        alias: "c",
-        require: false
-    },
-    "refill-helper-contract": {
-        description: "Address of the Executor refill helper contract",
-        type: "string",
-        require: false
-    },
-    "executor-private-keys": {
-        description: "Private keys of the executor accounts split by commas",
-        type: "string",
-        alias: "x",
-        require: true
-    },
-    "utility-private-key": {
-        description: "Private key of the utility account",
-        type: "string",
-        alias: "u",
-        require: false
-    },
-    "utility-wallet-monitor": {
-        description: "Either to enable utility wallet monitor or not",
-        type: "boolean",
-        default: true
-    },
-    "utility-wallet-monitor-interval": {
-        description: "Interval for checking utility wallet balance",
-        type: "number",
-        default: 15 * 1000 // 15 seconds
-    },
-    "max-executors": {
-        description:
-            "Maximum number of executor accounts to use from the list of executor private keys",
-        type: "number",
-        require: false
-    },
-    "min-executor-balance": {
-        description:
-            "Minimum balance required for each executor account (below which the utility account will refill)",
-        type: "string"
-    },
-    "executor-refill-interval": {
-        description: "Interval to refill the signer balance (seconds)",
-        type: "number",
-        require: true,
-        default: 60 * 20
-    },
     "min-entity-stake": {
         description: "Minimum stake required for a relay (in 10e18)",
         type: "number",
@@ -112,12 +63,6 @@ export const bundlerOptions: CliCommandOptions<IBundlerArgsInput> = {
         require: false,
         default: "100"
     },
-    "no-profit-bundling": {
-        description:
-            "Bundle tx such that all beneficiary fees are spent on gas fees",
-        type: "boolean",
-        default: false
-    },
     "gas-price-floor-percent": {
         description:
             "The minimum percentage of incoming user operation gas prices compared to the gas price used by the bundler to submit bundles",
@@ -179,19 +124,6 @@ export const bundlerOptions: CliCommandOptions<IBundlerArgsInput> = {
         require: false,
         default: null
     },
-    "refilling-wallets": {
-        description: "Enable refilling wallets",
-        type: "boolean",
-        require: false,
-        default: true
-    },
-    "aa95-gas-multiplier": {
-        description:
-            "Amount to multiply the current gas limit by if the bundling tx fails due to AA95",
-        type: "string",
-        require: false,
-        default: "125"
-    },
     "enable-instant-bundling-endpoint": {
         description:
             "Should the bundler enable the pimlico_sendUserOperationNow endpoint",
@@ -203,16 +135,17 @@ export const bundlerOptions: CliCommandOptions<IBundlerArgsInput> = {
             "Should the bundler enable the pimlico_experimental_sendUserOperation7702 and pimlico_experimental_estimateUserOperationGas7702 endpoint",
         type: "boolean",
         default: false
-    },
-    "executor-gas-multiplier": {
-        description: "Amount to scale the gas estimations used for bundling",
-        type: "string",
-        default: "100"
     }
 }
 
 export const gasEstimationOptions: CliCommandOptions<IGasEstimationArgsInput> =
     {
+        "entrypoint-simulation-contract": {
+            description: "Address of the EntryPoint simulations contract",
+            type: "string",
+            alias: "c",
+            require: false
+        },
         "binary-search-tolerance-delta": {
             description:
                 "Defines the threshold for when to stop the gas estimation binary search",
@@ -292,6 +225,84 @@ export const gasEstimationOptions: CliCommandOptions<IGasEstimationArgsInput> =
         }
     }
 
+export const executorOptions: CliCommandOptions<IExecutorArgsInput> = {
+    "resubmit-timeout": {
+        description:
+            "Amount of time before retrying a failed userOperation (in ms)",
+        type: "number",
+        require: true,
+        default: 15_000
+    },
+    "aa95-gas-multiplier": {
+        description:
+            "Amount to multiply the current gas limit by if the bundling tx fails due to AA95",
+        type: "string",
+        require: false,
+        default: "125"
+    },
+    "refilling-wallets": {
+        description: "Enable refilling wallets",
+        type: "boolean",
+        require: false,
+        default: true
+    },
+    "executor-gas-multiplier": {
+        description: "Amount to scale the gas estimations used for bundling",
+        type: "string",
+        default: "100"
+    },
+    "no-profit-bundling": {
+        description:
+            "Bundle tx such that all beneficiary fees are spent on gas fees",
+        type: "boolean",
+        default: false
+    },
+    "refill-helper-contract": {
+        description: "Address of the Executor refill helper contract",
+        type: "string",
+        require: false
+    },
+    "executor-private-keys": {
+        description: "Private keys of the executor accounts split by commas",
+        type: "string",
+        alias: "x",
+        require: true
+    },
+    "utility-private-key": {
+        description: "Private key of the utility account",
+        type: "string",
+        alias: "u",
+        require: false
+    },
+    "utility-wallet-monitor": {
+        description: "Either to enable utility wallet monitor or not",
+        type: "boolean",
+        default: true
+    },
+    "utility-wallet-monitor-interval": {
+        description: "Interval for checking utility wallet balance",
+        type: "number",
+        default: 15 * 1000 // 15 seconds
+    },
+    "max-executors": {
+        description:
+            "Maximum number of executor accounts to use from the list of executor private keys",
+        type: "number",
+        require: false
+    },
+    "min-executor-balance": {
+        description:
+            "Minimum balance required for each executor account (below which the utility account will refill)",
+        type: "string"
+    },
+    "executor-refill-interval": {
+        description: "Interval to refill the signer balance (seconds)",
+        type: "number",
+        require: true,
+        default: 60 * 20
+    }
+}
+
 export const compatibilityOptions: CliCommandOptions<ICompatibilityArgsInput> =
     {
         "chain-type": {
diff --git a/src/executor/executor.ts b/src/executor/executor.ts
index a415e874..614ae4f7 100644
--- a/src/executor/executor.ts
+++ b/src/executor/executor.ts
@@ -145,14 +145,14 @@ export class Executor {
             return { status: "failed" }
         }
 
-        newRequest.maxFeePerGas = maxBigInt(
+        newRequest.maxFeePerGas = scaleBigIntByPercent(
             gasPriceParameters.maxFeePerGas,
-            (newRequest.maxFeePerGas * 11n + 9n) / 10n
+            115n
         )
 
-        newRequest.maxPriorityFeePerGas = maxBigInt(
+        newRequest.maxPriorityFeePerGas = scaleBigIntByPercent(
             gasPriceParameters.maxPriorityFeePerGas,
-            (newRequest.maxPriorityFeePerGas * 11n + 9n) / 10n
+            115n
         )
         newRequest.account = transactionInfo.executor
 
diff --git a/src/executor/executorManager.ts b/src/executor/executorManager.ts
index 4a0df0af..42137e21 100644
--- a/src/executor/executorManager.ts
+++ b/src/executor/executorManager.ts
@@ -822,7 +822,10 @@ export class ExecutorManager {
         )
         await Promise.all(
             transactionInfos2.map(async (txInfo) => {
-                if (Date.now() - txInfo.lastReplaced < 5 * 60 * 1000) {
+                if (
+                    Date.now() - txInfo.lastReplaced <
+                    this.config.resubmitTimeout
+                ) {
                     return
                 }
 

From 5160b4737985d299864c4152201d3fe36ebf9f9e Mon Sep 17 00:00:00 2001
From: mouseless <97399882+mouseless-eth@users.noreply.github.com>
Date: Fri, 24 Jan 2025 02:24:00 +0000
Subject: [PATCH 2/4] rename env var

---
 src/cli/config/bundler.ts       | 2 +-
 src/cli/config/options.ts       | 2 +-
 src/executor/executorManager.ts | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/cli/config/bundler.ts b/src/cli/config/bundler.ts
index 17a04e13..806fbe7a 100644
--- a/src/cli/config/bundler.ts
+++ b/src/cli/config/bundler.ts
@@ -88,7 +88,7 @@ export const bundlerArgsSchema = z.object({
 })
 
 export const executorArgsSchema = z.object({
-    "resubmit-timeout": z.number().int().min(0).default(15_000),
+    "resubmit-stuck-timeout": z.number().int().min(0).default(15_000),
     "refilling-wallets": z.boolean().default(true),
     "aa95-gas-multiplier": z.string().transform((val) => BigInt(val)),
     "refill-helper-contract": addressSchema.optional(),
diff --git a/src/cli/config/options.ts b/src/cli/config/options.ts
index 65743efe..2da12842 100644
--- a/src/cli/config/options.ts
+++ b/src/cli/config/options.ts
@@ -226,7 +226,7 @@ export const gasEstimationOptions: CliCommandOptions<IGasEstimationArgsInput> =
     }
 
 export const executorOptions: CliCommandOptions<IExecutorArgsInput> = {
-    "resubmit-timeout": {
+    "resubmit-stuck-timeout": {
         description:
             "Amount of time before retrying a failed userOperation (in ms)",
         type: "number",
diff --git a/src/executor/executorManager.ts b/src/executor/executorManager.ts
index 42137e21..09fdb265 100644
--- a/src/executor/executorManager.ts
+++ b/src/executor/executorManager.ts
@@ -824,7 +824,7 @@ export class ExecutorManager {
             transactionInfos2.map(async (txInfo) => {
                 if (
                     Date.now() - txInfo.lastReplaced <
-                    this.config.resubmitTimeout
+                    this.config.resubmitStuckTimeout
                 ) {
                     return
                 }

From 09a0ec1ed6c1140a1503482c8fcc50292ad02458 Mon Sep 17 00:00:00 2001
From: mouseless <97399882+mouseless-eth@users.noreply.github.com>
Date: Fri, 24 Jan 2025 02:26:35 +0000
Subject: [PATCH 3/4] fix build

---
 src/cli/config/options.ts | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/src/cli/config/options.ts b/src/cli/config/options.ts
index 6437f851..dc79cdb8 100644
--- a/src/cli/config/options.ts
+++ b/src/cli/config/options.ts
@@ -135,12 +135,7 @@ export const bundlerOptions: CliCommandOptions<IBundlerArgsInput> = {
             "Should the bundler enable the pimlico_experimental_sendUserOperation7702 and pimlico_experimental_estimateUserOperationGas7702 endpoint",
         type: "boolean",
         default: false
-    },
-    "executor-gas-multiplier": {
-        description: "Amount to scale the gas estimations used for bundling",
-        type: "string",
-        default: "100"
-    },
+    }
 }
 
 export const gasEstimationOptions: CliCommandOptions<IGasEstimationArgsInput> =

From e93cbf593ba1c626e08107ddd82ad84ab97c1416 Mon Sep 17 00:00:00 2001
From: mouseless <97399882+mouseless-eth@users.noreply.github.com>
Date: Fri, 24 Jan 2025 13:06:45 +0000
Subject: [PATCH 4/4] change to 10s

---
 src/cli/config/options.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/cli/config/options.ts b/src/cli/config/options.ts
index dc79cdb8..3b4fc3c0 100644
--- a/src/cli/config/options.ts
+++ b/src/cli/config/options.ts
@@ -237,7 +237,7 @@ export const executorOptions: CliCommandOptions<IExecutorArgsInput> = {
             "Amount of time before retrying a failed userOperation (in ms)",
         type: "number",
         require: true,
-        default: 15_000
+        default: 10_000
     },
     "aa95-gas-multiplier": {
         description: