Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/cli/config/bundler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,10 @@ export const compatibilityArgsSchema = z.object({
.string()
.transform((val) => parseGwei(val))
.optional(),
"max-priority-fee-per-gas-cap": z
.string()
.transform((val) => parseGwei(val))
.optional(),
"supports-eip7623": z.boolean().default(false)
})

Expand Down
6 changes: 6 additions & 0 deletions src/cli/config/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,12 @@ export const compatibilityOptions: CliCommandOptions<ICompatibilityArgsInput> =
type: "string",
require: false
},
"max-priority-fee-per-gas-cap": {
description:
"Maximum value for maxPriorityFeePerGas to enforce (in gwei). Caps the tip taken from the network gas oracle. On low-traffic chains the oracle can feedback-loop on the bundler's own past tips and report an absurd value; without a ceiling the bundler bids it verbatim and overpays. maxFeePerGas is reduced by the same amount the tip is capped.",
type: "string",
require: false
},
"supports-eip7623": {
description:
"Whether the chain supports EIP-7623 (Increase calldata cost to reduce maximum block size)",
Expand Down
68 changes: 44 additions & 24 deletions src/handlers/gasPriceManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,29 +131,49 @@ export class GasPriceManager {
maxPriorityFeePerGas: (maxPriorityFeePerGas * bumpAmount) / 100n
}

if (
this.config.floorMaxFeePerGas ||
this.config.floorMaxPriorityFeePerGas
) {
const maxFeePerGas = this.config.floorMaxFeePerGas
? maxBigInt(this.config.floorMaxFeePerGas, result.maxFeePerGas)
: result.maxFeePerGas

const maxPriorityFeePerGas = this.config.floorMaxPriorityFeePerGas
? maxBigInt(
this.config.floorMaxPriorityFeePerGas,
result.maxPriorityFeePerGas
)
: result.maxPriorityFeePerGas
const finalMaxFeePerGas = this.config.floorMaxFeePerGas
? maxBigInt(this.config.floorMaxFeePerGas, result.maxFeePerGas)
: result.maxFeePerGas

const finalMaxPriorityFeePerGas = this.config.floorMaxPriorityFeePerGas
? maxBigInt(
this.config.floorMaxPriorityFeePerGas,
result.maxPriorityFeePerGas
)
: result.maxPriorityFeePerGas

return {
// Ensure that maxFeePerGas is always greater or equal than maxPriorityFeePerGas
maxFeePerGas: maxBigInt(
finalMaxFeePerGas,
finalMaxPriorityFeePerGas
),
maxPriorityFeePerGas: finalMaxPriorityFeePerGas
}
}

private applyMaxPriorityFeePerGasCap(
gasPriceParameters: GasPriceParameters
): GasPriceParameters {
// Apply after final lower-bound checks so the oracle value cannot restore
// an uncapped priority fee.
if (this.config.maxPriorityFeePerGasCap !== undefined) {
const cappedPriorityFee = minBigInt(
gasPriceParameters.maxPriorityFeePerGas,
this.config.maxPriorityFeePerGasCap
)
const priorityFeeDelta =
gasPriceParameters.maxPriorityFeePerGas - cappedPriorityFee
const maxFeePerGas =
gasPriceParameters.maxFeePerGas - priorityFeeDelta

return {
// Ensure that maxFeePerGas is always greater or equal than maxPriorityFeePerGas
maxFeePerGas: maxBigInt(maxFeePerGas, maxPriorityFeePerGas),
maxPriorityFeePerGas
maxFeePerGas: maxBigInt(maxFeePerGas, cappedPriorityFee),
maxPriorityFeePerGas: cappedPriorityFee
}
}

return result
return gasPriceParameters
}

private async getFallBackMaxPriorityFeePerGas(
Expand Down Expand Up @@ -279,7 +299,7 @@ export class GasPriceManager {
maxPriorityFeePerGas: polygonEstimate.maxPriorityFeePerGas
})

return {
return this.applyMaxPriorityFeePerGasCap({
maxFeePerGas: maxBigInt(
gasPrice.maxFeePerGas,
maxFeePerGas
Expand All @@ -288,21 +308,21 @@ export class GasPriceManager {
gasPrice.maxPriorityFeePerGas,
maxPriorityFeePerGas
)
}
})
}
}

if (this.config.legacyTransactions) {
const gasPrice = this.bumpTheGasPrice(
await this.getLegacyTransactionGasPrice()
)
return {
return this.applyMaxPriorityFeePerGasCap({
maxFeePerGas: maxBigInt(gasPrice.maxFeePerGas, maxFeePerGas),
maxPriorityFeePerGas: maxBigInt(
gasPrice.maxPriorityFeePerGas,
maxPriorityFeePerGas
)
}
})
}

const estimatedPrice = await this.estimateGasPrice()
Expand All @@ -314,13 +334,13 @@ export class GasPriceManager {
maxFeePerGas,
maxPriorityFeePerGas
})
return {
return this.applyMaxPriorityFeePerGasCap({
maxFeePerGas: maxBigInt(gasPrice.maxFeePerGas, maxFeePerGas),
maxPriorityFeePerGas: maxBigInt(
gasPrice.maxPriorityFeePerGas,
maxPriorityFeePerGas
)
}
})
}

// This method throws if it can't get a valid RPC response.
Expand Down
Loading