Skip to content
Open
Show file tree
Hide file tree
Changes from all 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 @@ -200,6 +200,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 @@ -560,6 +560,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 @@ -137,29 +137,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 @@ -285,7 +305,7 @@ export class GasPriceManager {
maxPriorityFeePerGas: polygonEstimate.maxPriorityFeePerGas
})

return {
return this.applyMaxPriorityFeePerGasCap({
maxFeePerGas: maxBigInt(
gasPrice.maxFeePerGas,
maxFeePerGas
Expand All @@ -294,21 +314,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 @@ -320,13 +340,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