From 40888c405db19f1860f0d3f22e26cc5dc541306f Mon Sep 17 00:00:00 2001 From: nicholaspai <9457025+nicholaspai@users.noreply.github.com> Date: Thu, 9 Jan 2025 09:20:19 -0500 Subject: [PATCH] feat(GasPriceAdapter): Allow caller to set a minimum priority fee for eip1559Raw adapter (#821) --- package.json | 2 +- src/gasPriceOracle/adapters/ethereum.ts | 8 +++- test/GasPriceOracle.test.ts | 57 +++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index ab2093e9..7428d47e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@across-protocol/sdk", "author": "UMA Team", - "version": "3.4.6", + "version": "3.4.7", "license": "AGPL-3.0", "homepage": "https://docs.across.to/reference/sdk", "files": [ diff --git a/src/gasPriceOracle/adapters/ethereum.ts b/src/gasPriceOracle/adapters/ethereum.ts index 4de4f39a..3c8fbca1 100644 --- a/src/gasPriceOracle/adapters/ethereum.ts +++ b/src/gasPriceOracle/adapters/ethereum.ts @@ -1,6 +1,6 @@ import assert from "assert"; import { providers } from "ethers"; -import { BigNumber, bnZero, fixedPointAdjustment, getNetworkName } from "../../utils"; +import { BigNumber, bnZero, fixedPointAdjustment, getNetworkName, parseUnits } from "../../utils"; import { GasPriceEstimate } from "../types"; import { gasPriceError } from "../util"; import { GasPriceEstimateOptions } from "../oracle"; @@ -43,7 +43,11 @@ export async function eip1559Raw( provider.getBlock("pending"), (provider as providers.JsonRpcProvider).send("eth_maxPriorityFeePerGas", []), ]); - const maxPriorityFeePerGas = BigNumber.from(_maxPriorityFeePerGas); + let maxPriorityFeePerGas = BigNumber.from(_maxPriorityFeePerGas); + const flooredPriorityFeePerGas = parseUnits(process.env[`MIN_PRIORITY_FEE_PER_GAS_${chainId}`] || "0", 9); + if (maxPriorityFeePerGas.lt(flooredPriorityFeePerGas)) { + maxPriorityFeePerGas = BigNumber.from(flooredPriorityFeePerGas); + } assert(BigNumber.isBigNumber(baseFeePerGas), `No baseFeePerGas received on ${getNetworkName(chainId)}`); const scaledPriorityFee = maxPriorityFeePerGas.mul(priorityFeeMultiplier).div(fixedPointAdjustment); diff --git a/test/GasPriceOracle.test.ts b/test/GasPriceOracle.test.ts index 4f33d365..e5c06510 100644 --- a/test/GasPriceOracle.test.ts +++ b/test/GasPriceOracle.test.ts @@ -182,6 +182,63 @@ describe("Gas Price Oracle", function () { expect(markedUpMaxPriorityFeePerGas).to.equal(expectedMarkedUpPriorityFee); delete process.env[chainKey]; }); + it("Ethers EIP1559 Raw: min priority fee is respected", async function () { + const baseFeeMultiplier = toBNWei("2.0"); + const priorityFeeMultiplier = toBNWei("1.5"); + const minPriorityFeeScaler = "1.5"; + const minPriorityFee = parseUnits(minPriorityFeeScaler, 9); + const chainId = 1; + const chainKey = `GAS_PRICE_EIP1559_RAW_${chainId}`; + const minPriorityFeeKey = `MIN_PRIORITY_FEE_PER_GAS_${chainId}`; + process.env[chainKey] = "true"; + process.env[minPriorityFeeKey] = minPriorityFeeScaler; + + const { maxFeePerGas: markedUpMaxFeePerGas, maxPriorityFeePerGas: markedUpMaxPriorityFeePerGas } = + await getGasPriceEstimate(provider, { chainId, baseFeeMultiplier, priorityFeeMultiplier }); + + // Base fee should be multiplied by multiplier. Returned max fee includes priority fee + // so back it out before scaling. + const expectedMarkedUpPriorityFee = minPriorityFee.mul(priorityFeeMultiplier).div(fixedPointAdjustment); + const expectedMarkedUpMaxFeePerGas = stdLastBaseFeePerGas + .mul(baseFeeMultiplier) + .div(fixedPointAdjustment) + .add(expectedMarkedUpPriorityFee); + expect(markedUpMaxFeePerGas).to.equal(expectedMarkedUpMaxFeePerGas); + + // Priority fees should be scaled. + expect(markedUpMaxPriorityFeePerGas).to.equal(expectedMarkedUpPriorityFee); + delete process.env[chainKey]; + delete process.env[minPriorityFeeKey]; + }); + it("Ethers EIP1559 Raw: min priority fee is ignored", async function () { + const baseFeeMultiplier = toBNWei("2.0"); + const priorityFeeMultiplier = toBNWei("1.5"); + const minPriorityFeeScaler = "0.5"; + const minPriorityFee = parseUnits(minPriorityFeeScaler, 9); + expect(minPriorityFee.lt(stdMaxPriorityFeePerGas)).to.be.true; + const chainId = 1; + const chainKey = `GAS_PRICE_EIP1559_RAW_${chainId}`; + const minPriorityFeeKey = `MIN_PRIORITY_FEE_PER_GAS_${chainId}`; + process.env[chainKey] = "true"; + process.env[minPriorityFeeKey] = minPriorityFeeScaler.toString(); + + const { maxFeePerGas: markedUpMaxFeePerGas, maxPriorityFeePerGas: markedUpMaxPriorityFeePerGas } = + await getGasPriceEstimate(provider, { chainId, baseFeeMultiplier, priorityFeeMultiplier }); + + // Base fee should be multiplied by multiplier. Returned max fee includes priority fee + // so back it out before scaling. + const expectedMarkedUpPriorityFee = stdMaxPriorityFeePerGas.mul(priorityFeeMultiplier).div(fixedPointAdjustment); + const expectedMarkedUpMaxFeePerGas = stdLastBaseFeePerGas + .mul(baseFeeMultiplier) + .div(fixedPointAdjustment) + .add(expectedMarkedUpPriorityFee); + expect(markedUpMaxFeePerGas).to.equal(expectedMarkedUpMaxFeePerGas); + + // Priority fees should be scaled. + expect(markedUpMaxPriorityFeePerGas).to.equal(expectedMarkedUpPriorityFee); + delete process.env[chainKey]; + delete process.env[minPriorityFeeKey]; + }); it("Ethers EIP1559 Bad", async function () { // This test should return identical results to the Raw test but it makes different // provider calls, so we're really testing that the expected provider functions are called.