Skip to content

Commit 370b4ee

Browse files
authored
test: fix with custom transport (#755)
1 parent 82787d7 commit 370b4ee

File tree

8 files changed

+89
-49
lines changed

8 files changed

+89
-49
lines changed

e2e/oracle.e2e.ts

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
// @note: This test is _not_ run automatically as part of git hooks or CI.
22
import dotenv from "dotenv";
33
import winston from "winston";
4-
import { custom } from "viem";
54
import { providers } from "ethers";
65
import { getGasPriceEstimate } from "../src/gasPriceOracle";
76
import { BigNumber, bnZero, parseUnits } from "../src/utils";
8-
import { expect } from "../test/utils";
7+
import { expect, makeCustomTransport } from "../test/utils";
98
dotenv.config({ path: ".env" });
109

1110
const dummyLogger = winston.createLogger({
@@ -16,23 +15,8 @@ const dummyLogger = winston.createLogger({
1615
const stdLastBaseFeePerGas = parseUnits("12", 9);
1716
const stdMaxPriorityFeePerGas = parseUnits("1", 9); // EIP-1559 chains only
1817
const stdMaxFeePerGas = stdLastBaseFeePerGas.add(stdMaxPriorityFeePerGas);
19-
const stdGasPrice = stdMaxFeePerGas;
2018

21-
const customTransport = custom({
22-
// eslint-disable-next-line require-await
23-
async request({ method }: { method: string; params: unknown }) {
24-
switch (method) {
25-
case "eth_gasPrice":
26-
return BigInt(stdGasPrice.toString());
27-
case "eth_getBlockByNumber":
28-
return { baseFeePerGas: BigInt(stdLastBaseFeePerGas.mul(100).div(120).toString()) };
29-
case "eth_maxPriorityFeePerGas":
30-
return BigInt(stdMaxPriorityFeePerGas.toString());
31-
default:
32-
console.log(`Unsupported method: ${method}.`);
33-
}
34-
},
35-
});
19+
const customTransport = makeCustomTransport({ stdLastBaseFeePerGas, stdMaxPriorityFeePerGas });
3620

3721
const eip1559Chains = [1, 10, 137, 324, 8453, 42161, 534352];
3822
const chainIds = [...eip1559Chains, 1337];

src/gasPriceOracle/oracle.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@ import * as polygon from "./adapters/polygon";
99

1010
/**
1111
* Provide an estimate for the current gas price for a particular chain.
12-
* @param chainId The chain ID to query for gas prices.
13-
* @param provider A valid ethers provider.
14-
* @param legacyFallback In the case of an unrecognised chain, fall back to type 0 gas estimation.
12+
* @param providerOrChainId A valid ethers provider or a chain ID.
13+
* @param transport An optional transport object for custom gas price retrieval.
1514
* @returns Am object of type GasPriceEstimate.
1615
*/
1716
export async function getGasPriceEstimate(
18-
provider: providers.Provider,
17+
providerOrChainId: providers.Provider | number,
1918
transport?: Transport
2019
): Promise<GasPriceEstimate> {
21-
const { chainId } = await provider.getNetwork();
20+
const chainId =
21+
typeof providerOrChainId === "number" ? providerOrChainId : (await providerOrChainId.getNetwork()).chainId;
2222
const viemProvider = getPublicClient(chainId, transport);
2323

2424
const gasPriceFeeds = {

src/relayFeeCalculator/chain-queries/baseQuery.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
toBNWei,
1515
} from "../../utils";
1616
import { Logger, QueryInterface } from "../relayFeeCalculator";
17+
import { Transport } from "viem";
1718

1819
type Provider = providers.Provider;
1920
type OptimismProvider = L2Provider<Provider>;
@@ -61,17 +62,25 @@ export class QueryBase implements QueryInterface {
6162
* Retrieves the current gas costs of performing a fillRelay contract at the referenced SpokePool.
6263
* @param deposit V3 deposit instance.
6364
* @param relayerAddress Relayer address to simulate with.
64-
* @param gasPrice Optional gas price to use for the simulation.
65-
* @param gasUnits Optional gas units to use for the simulation.
65+
* @param options
66+
* @param options.gasPrice Optional gas price to use for the simulation.
67+
* @param options.gasUnits Optional gas units to use for the simulation.
68+
* @param options.omitMarkup Optional flag to omit the gas markup.
69+
* @param options.transport Optional transport object for custom gas price retrieval.
6670
* @returns The gas estimate for this function call (multiplied with the optional buffer).
6771
*/
6872
async getGasCosts(
6973
deposit: Deposit,
7074
relayer = DEFAULT_SIMULATED_RELAYER_ADDRESS,
71-
gasPrice = this.fixedGasPrice,
72-
gasUnits?: BigNumberish,
73-
omitMarkup?: boolean
75+
options: Partial<{
76+
gasPrice: BigNumberish;
77+
gasUnits: BigNumberish;
78+
omitMarkup: boolean;
79+
transport: Transport;
80+
}> = {}
7481
): Promise<TransactionCostEstimate> {
82+
const { gasPrice = this.fixedGasPrice, gasUnits, omitMarkup, transport } = options;
83+
7584
const gasMarkup = omitMarkup ? 0 : this.gasMarkup;
7685
assert(
7786
gasMarkup > -1 && gasMarkup <= 4,
@@ -84,8 +93,11 @@ export class QueryBase implements QueryInterface {
8493
tx,
8594
relayer,
8695
this.provider,
87-
gasPrice,
88-
gasUnits
96+
{
97+
gasPrice,
98+
gasUnits,
99+
transport,
100+
}
89101
);
90102

91103
return {

src/relayFeeCalculator/relayFeeCalculator.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ import {
1717
toBN,
1818
toBNWei,
1919
} from "../utils";
20+
import { Transport } from "viem";
2021

2122
// This needs to be implemented for every chain and passed into RelayFeeCalculator
2223
export interface QueryInterface {
2324
getGasCosts: (
2425
deposit: Deposit,
2526
relayer: string,
26-
gasPrice?: BigNumberish,
27-
gasLimit?: BigNumberish
27+
options?: Partial<{ gasPrice: BigNumberish; gasUnits: BigNumberish; omitMarkup: boolean; transport: Transport }>
2828
) => Promise<TransactionCostEstimate>;
2929
getTokenPrice: (tokenSymbol: string) => Promise<number>;
3030
getTokenDecimals: (tokenSymbol: string) => number;
@@ -230,7 +230,8 @@ export class RelayFeeCalculator {
230230
_tokenPrice?: number,
231231
tokenMapping = TOKEN_SYMBOLS_MAP,
232232
gasPrice?: BigNumberish,
233-
gasLimit?: BigNumberish
233+
gasLimit?: BigNumberish,
234+
transport?: Transport
234235
): Promise<BigNumber> {
235236
if (toBN(amountToRelay).eq(bnZero)) return MAX_BIG_INT;
236237

@@ -245,16 +246,18 @@ export class RelayFeeCalculator {
245246
const simulatedAmount = simulateZeroFill ? safeOutputAmount : toBN(amountToRelay);
246247
deposit = { ...deposit, outputAmount: simulatedAmount };
247248

248-
const getGasCosts = this.queries.getGasCosts(deposit, relayerAddress, gasPrice, gasLimit).catch((error) => {
249-
this.logger.error({
250-
at: "sdk/gasFeePercent",
251-
message: "Error while fetching gas costs",
252-
error,
253-
simulateZeroFill,
254-
deposit,
249+
const getGasCosts = this.queries
250+
.getGasCosts(deposit, relayerAddress, { gasPrice, gasUnits: gasLimit, transport })
251+
.catch((error) => {
252+
this.logger.error({
253+
at: "sdk/gasFeePercent",
254+
message: "Error while fetching gas costs",
255+
error,
256+
simulateZeroFill,
257+
deposit,
258+
});
259+
throw error;
255260
});
256-
throw error;
257-
});
258261
const [{ tokenGasCost }, tokenPrice] = await Promise.all([
259262
getGasCosts,
260263
_tokenPrice ??

src/utils/common.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { TypedMessage } from "../interfaces/TypedData";
88
import { BigNumber, BigNumberish, BN, formatUnits, parseUnits, toBN } from "./BigNumberUtils";
99
import { ConvertDecimals } from "./FormattingUtils";
1010
import { chainIsOPStack } from "./NetworkUtils";
11+
import { Transport } from "viem";
1112

1213
export type Decimalish = string | number | Decimal;
1314
export const AddressZero = ethers.constants.AddressZero;
@@ -239,17 +240,24 @@ export type TransactionCostEstimate = {
239240
* @param unsignedTx The unsigned transaction that this function will estimate.
240241
* @param senderAddress The address that the transaction will be submitted from.
241242
* @param provider A valid ethers provider - will be used to reason the gas price.
242-
* @param gasPrice A manually provided gas price - if set, this function will not resolve the current gas price.
243-
* @param gasUnits A manually provided gas units - if set, this function will not estimate the gas units.
243+
* @param options
244+
* @param options.gasPrice A manually provided gas price - if set, this function will not resolve the current gas price.
245+
* @param options.gasUnits A manually provided gas units - if set, this function will not estimate the gas units.
246+
* @param options.transport A custom transport object for custom gas price retrieval.
244247
* @returns Estimated cost in units of gas and the underlying gas token (gasPrice * estimatedGasUnits).
245248
*/
246249
export async function estimateTotalGasRequiredByUnsignedTransaction(
247250
unsignedTx: PopulatedTransaction,
248251
senderAddress: string,
249252
provider: providers.Provider | L2Provider<providers.Provider>,
250-
gasPrice?: BigNumberish,
251-
gasUnits?: BigNumberish
253+
options: Partial<{
254+
gasPrice: BigNumberish;
255+
gasUnits: BigNumberish;
256+
transport: Transport;
257+
}> = {}
252258
): Promise<TransactionCostEstimate> {
259+
const { gasPrice: _gasPrice, gasUnits, transport } = options || {};
260+
253261
const { chainId } = await provider.getNetwork();
254262
const voidSigner = new VoidSigner(senderAddress, provider);
255263

@@ -268,13 +276,14 @@ export async function estimateTotalGasRequiredByUnsignedTransaction(
268276
// `provider.estimateTotalGasCost` to improve performance.
269277
const [l1GasCost, l2GasPrice] = await Promise.all([
270278
provider.estimateL1GasCost(populatedTransaction),
271-
gasPrice || provider.getGasPrice(),
279+
_gasPrice || provider.getGasPrice(),
272280
]);
273281
const l2GasCost = nativeGasCost.mul(l2GasPrice);
274282
tokenGasCost = l1GasCost.add(l2GasCost);
275283
} else {
284+
let gasPrice = _gasPrice;
276285
if (!gasPrice) {
277-
const gasPriceEstimate = await getGasPriceEstimate(provider);
286+
const gasPriceEstimate = await getGasPriceEstimate(chainId, transport);
278287
gasPrice = gasPriceEstimate.maxFeePerGas;
279288
}
280289
tokenGasCost = nativeGasCost.mul(gasPrice);

test/relayFeeCalculator.test.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
getContractFactory,
2626
randomAddress,
2727
setupTokensForWallet,
28+
makeCustomTransport,
2829
} from "./utils";
2930
import { TOKEN_SYMBOLS_MAP } from "@across-protocol/constants";
3031
import { EMPTY_MESSAGE, ZERO_ADDRESS } from "../src/constants";
@@ -286,6 +287,7 @@ describe("RelayFeeCalculator: Composable Bridging", function () {
286287
let owner: SignerWithAddress, relayer: SignerWithAddress, depositor: SignerWithAddress;
287288
let tokenMap: typeof TOKEN_SYMBOLS_MAP;
288289
let testGasFeePct: (message?: string) => Promise<BigNumber>;
290+
const customTransport = makeCustomTransport();
289291

290292
beforeEach(async function () {
291293
[owner, relayer, depositor] = await ethers.getSigners();
@@ -345,7 +347,10 @@ describe("RelayFeeCalculator: Composable Bridging", function () {
345347
false,
346348
relayer.address,
347349
1,
348-
tokenMap
350+
tokenMap,
351+
undefined,
352+
undefined,
353+
customTransport
349354
);
350355
});
351356
it("should not revert if no message is passed", async () => {

test/utils/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ export * from "./utils";
66
export * from "./BlockchainUtils";
77
export * from "./SpokePoolUtils";
88
export * from "./SpyTransport";
9+
export * from "./transport";

test/utils/transport.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { custom } from "viem";
2+
import { BigNumber, parseUnits } from "../../src/utils";
3+
4+
export const makeCustomTransport = (
5+
params: Partial<{ stdLastBaseFeePerGas: BigNumber; stdMaxPriorityFeePerGas: BigNumber }> = {}
6+
) => {
7+
const { stdLastBaseFeePerGas = parseUnits("12", 9), stdMaxPriorityFeePerGas = parseUnits("1", 9) } = params;
8+
const stdMaxFeePerGas = stdLastBaseFeePerGas.add(stdMaxPriorityFeePerGas);
9+
const stdGasPrice = stdMaxFeePerGas;
10+
11+
return custom({
12+
// eslint-disable-next-line require-await
13+
async request({ method }: { method: string; params: unknown }) {
14+
switch (method) {
15+
case "eth_gasPrice":
16+
return BigInt(stdGasPrice.toString());
17+
case "eth_getBlockByNumber":
18+
return { baseFeePerGas: BigInt(stdLastBaseFeePerGas.toString()) };
19+
case "eth_maxPriorityFeePerGas":
20+
return BigInt(stdMaxPriorityFeePerGas.toString());
21+
default:
22+
throw new Error(`Unsupported method: ${method}.`);
23+
}
24+
},
25+
});
26+
};

0 commit comments

Comments
 (0)