Skip to content

Commit

Permalink
Merge branch 'pimlicolabs:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
osrm authored Dec 9, 2024
2 parents da119fd + 52395dd commit b4206f7
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 44 deletions.
2 changes: 1 addition & 1 deletion src/cli/config/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ export const debugOptions: CliCommandOptions<IDebugArgsInput> = {
"Should the bundler deploy the simulations contract on startup",
type: "boolean",
require: true,
default: false
default: true
},
tenderly: {
description: "RPC url follows the tenderly format",
Expand Down
10 changes: 10 additions & 0 deletions src/cli/deploySimulationsContract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ export const deploySimulationsContract = async ({
)
}

if (args.entrypointSimulationContract) {
const simulations = args.entrypointSimulationContract
const simulationsCode = await publicClient.getCode({
address: simulations
})
if (simulationsCode !== undefined && simulationsCode !== "0x") {
return args.entrypointSimulationContract
}
}

const walletClient = createWalletClient({
transport: http(args.rpcUrl),
account: utilityPrivateKey
Expand Down
118 changes: 89 additions & 29 deletions src/executor/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import {
type UserOperationV06,
type UserOperationV07,
type UserOperationWithHash,
deriveUserOperation
deriveUserOperation,
GasPriceParameters
} from "@alto/types"
import type { Logger, Metrics } from "@alto/utils"
import {
Expand Down Expand Up @@ -152,8 +153,15 @@ export class Executor {
): Promise<ReplaceTransactionResult> {
const newRequest = { ...transactionInfo.transactionRequest }

const gasPriceParameters =
await this.gasPriceManager.getNetworkGasPrice()
let gasPriceParameters
try {
gasPriceParameters =
await this.gasPriceManager.tryGetNetworkGasPrice()
} catch (err) {
this.logger.error({ error: err }, "Failed to get network gas price")
this.markWalletProcessed(transactionInfo.executor)
return { status: "failed" }
}

newRequest.maxFeePerGas = maxBigInt(
gasPriceParameters.maxFeePerGas,
Expand Down Expand Up @@ -495,15 +503,23 @@ export class Executor {

const wallets = Array.from(allWallets)

const gasPrice = await this.gasPriceManager.getNetworkGasPrice()
const gasPrice = await this.gasPriceManager.tryGetNetworkGasPrice()

const promises = wallets.map((wallet) => {
flushStuckTransaction(
this.config.publicClient,
this.config.walletClient,
wallet,
gasPrice.maxFeePerGas * 5n,
this.logger
)
try {
flushStuckTransaction(
this.config.publicClient,
this.config.walletClient,
wallet,
gasPrice.maxFeePerGas * 5n,
this.logger
)
} catch (e) {
this.logger.error(
{ error: e },
"error flushing stuck transaction"
)
}
})

await Promise.all(promises)
Expand Down Expand Up @@ -709,15 +725,35 @@ export class Executor {
})
childLogger.debug("bundling user operation")

const gasPriceParameters =
await this.gasPriceManager.getNetworkGasPrice()
childLogger.debug({ gasPriceParameters }, "got gas price")

const nonce = await this.config.publicClient.getTransactionCount({
address: wallet.address,
blockTag: "pending"
})
childLogger.trace({ nonce }, "got nonce")
// These calls can throw, so we try/catch them to mark wallet as processed in event of error.
let nonce: number
let gasPriceParameters: GasPriceParameters
try {
;[gasPriceParameters, nonce] = await Promise.all([
this.gasPriceManager.tryGetNetworkGasPrice(),
this.config.publicClient.getTransactionCount({
address: wallet.address,
blockTag: "pending"
})
])
} catch (err) {
childLogger.error(
{ error: err },
"Failed to get parameters for bundling"
)
this.markWalletProcessed(wallet)
return opsWithHashes.map((owh) => {
return {
status: "resubmit",
info: {
entryPoint,
userOpHash: owh.userOperationHash,
userOperation: owh.mempoolUserOperation,
reason: "Failed to get parameters for bundling"
}
}
})
}

const callContext: DefaultFilterOpsAndEstimateGasParams = {
ep,
Expand Down Expand Up @@ -989,15 +1025,39 @@ export class Executor {
})
childLogger.debug("bundling compressed user operation")

const gasPriceParameters =
await this.gasPriceManager.getNetworkGasPrice()
childLogger.debug({ gasPriceParameters }, "got gas price")

const nonce = await this.config.publicClient.getTransactionCount({
address: wallet.address,
blockTag: "pending"
})
childLogger.trace({ nonce }, "got nonce")
let nonce: number
let gasPriceParameters: GasPriceParameters
try {
;[gasPriceParameters, nonce] = await Promise.all([
this.gasPriceManager.tryGetNetworkGasPrice(),
this.config.publicClient.getTransactionCount({
address: wallet.address,
blockTag: "pending"
})
])
} catch (err) {
childLogger.error(
{ error: err },
"Failed to get parameters for bundling"
)
this.markWalletProcessed(wallet)
return compressedOps.map((compressedOp) => {
const userOpHash = getUserOperationHash(
compressedOp.inflatedOp,
entryPoint,
this.config.walletClient.chain.id
)
return {
status: "resubmit",
info: {
entryPoint,
userOpHash,
userOperation: compressedOp,
reason: "Failed to get parameters for bundling"
}
}
})
}

const callContext: CompressedFilterOpsAndEstimateGasParams = {
publicClient: this.config.publicClient,
Expand Down
2 changes: 1 addition & 1 deletion src/executor/executorManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,7 @@ export class ExecutorManager {

// for all still not included check if needs to be replaced (based on gas price)
const gasPriceParameters =
await this.gasPriceManager.getNetworkGasPrice()
await this.gasPriceManager.tryGetNetworkGasPrice()
this.logger.trace(
{ gasPriceParameters },
"fetched gas price parameters"
Expand Down
17 changes: 9 additions & 8 deletions src/executor/senderManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,18 +127,19 @@ export class SenderManager {
},
"utility wallet has insufficient balance to refill wallets"
)
throw new Error(
`utility wallet ${
this.utilityAccount.address
} has insufficient balance ${formatEther(
utilityWalletBalance
)} < ${formatEther(totalBalanceMissing)}`
)
return
// throw new Error(
// `utility wallet ${
// this.utilityAccount.address
// } has insufficient balance ${formatEther(
// utilityWalletBalance
// )} < ${formatEther(totalBalanceMissing)}`
// )
}

if (Object.keys(balancesMissing).length > 0) {
const { maxFeePerGas, maxPriorityFeePerGas } =
await this.gasPriceManager.getNetworkGasPrice()
await this.gasPriceManager.tryGetNetworkGasPrice()

if (this.config.refillHelperContract) {
const instructions = []
Expand Down
13 changes: 8 additions & 5 deletions src/handlers/gasPriceManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export class GasPriceManager {
this.updateBaseFee()
}

this.updateGasPrice()
this.tryUpdateGasPrice()
}, this.config.gasPriceRefreshInterval * 1000)
}

Expand All @@ -81,7 +81,7 @@ export class GasPriceManager {

public init() {
return Promise.all([
this.updateGasPrice(),
this.tryUpdateGasPrice(),
this.config.legacyTransactions === false
? this.updateBaseFee()
: Promise.resolve()
Expand Down Expand Up @@ -296,6 +296,7 @@ export class GasPriceManager {
return { maxFeePerGas, maxPriorityFeePerGas }
}

// This method throws if it can't get a valid RPC response.
private async innerGetGasPrice(): Promise<GasPriceParameters> {
let maxFeePerGas = 0n
let maxPriorityFeePerGas = 0n
Expand Down Expand Up @@ -386,7 +387,8 @@ export class GasPriceManager {
return baseFee
}

private async updateGasPrice(): Promise<GasPriceParameters> {
// This method throws if it can't get a valid RPC response.
private async tryUpdateGasPrice(): Promise<GasPriceParameters> {
const gasPrice = await this.innerGetGasPrice()

this.maxFeePerGasQueue.saveValue(gasPrice.maxFeePerGas)
Expand All @@ -397,7 +399,7 @@ export class GasPriceManager {

public async getGasPrice(): Promise<GasPriceParameters> {
if (this.config.gasPriceRefreshInterval === 0) {
return await this.updateGasPrice()
return await this.tryUpdateGasPrice()
}

const maxFeePerGas = this.maxFeePerGasQueue.getLatestValue()
Expand All @@ -414,7 +416,8 @@ export class GasPriceManager {
}
}

public async getNetworkGasPrice(): Promise<GasPriceParameters> {
// This method throws if it can't get a valid RPC response.
public async tryGetNetworkGasPrice(): Promise<GasPriceParameters> {
return await this.innerGetGasPrice()
}

Expand Down

0 comments on commit b4206f7

Please sign in to comment.