Skip to content

Commit

Permalink
chore: update l1 fee calculation in estimateGasFee (#285)
Browse files Browse the repository at this point in the history
* chore: update l1 fee calculation in estimateGasFee

* chore: remove `destinationContractAddress` from EstimateL1FeeParams

* chore: remove unused params

* chore: update changeset

* chore: remove test.only

* chore: fix gas limit low error

* chore: fix use l1GasOracleAddress

* chore: remove multicall

* chore: fix potential math error

* chore: remove mantle fee

* chore: update tests

* chore: cleanup

* chore: make gasMultiplier optional

* chore: add @axelarjs/utils as dependency
  • Loading branch information
npty authored Mar 27, 2024
1 parent 3125296 commit dfcf1a1
Show file tree
Hide file tree
Showing 15 changed files with 219 additions and 275 deletions.
5 changes: 5 additions & 0 deletions .changeset/fluffy-elephants-shake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@axelarjs/api": patch
---

Improve l1 fee calculation for estimateGasFee
52 changes: 17 additions & 35 deletions packages/api/src/axelar-query/client.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ENVIRONMENTS } from "@axelarjs/core";

import { formatEther, pad } from "viem";
import { formatEther } from "viem";

import type {
AxelarQueryAPIClient,
Expand All @@ -12,7 +12,7 @@ import { createAxelarQueryClient } from "./client";
describe("axelar-query (node client)", () => {
describe("estimateGasFee", () => {
const requestParam: EstimateGasFeeParams = {
sourceChain: "ethereum-2",
sourceChain: "ethereum",
destinationChain: "avalanche",
gasLimit: 700_000n,
gasMultiplier: 1.1,
Expand All @@ -22,14 +22,16 @@ describe("axelar-query (node client)", () => {
amountInUnits: "1000000",
};

let api: AxelarQueryAPIClient;
let mainnetApi: AxelarQueryAPIClient;
// let testnetApi: AxelarQueryAPIClient;

beforeEach(() => {
api = createAxelarQueryClient(ENVIRONMENTS.testnet, {});
mainnetApi = createAxelarQueryClient(ENVIRONMENTS.mainnet, {});
// testnetApi = createAxelarQueryClient(ENVIRONMENTS.testnet, {});
});

test("It should return estimated gas amount in terms of native tokens", async () => {
const fees = await api.estimateGasFee({
const fees = await mainnetApi.estimateGasFee({
...requestParam,
showDetailedFees: false,
});
Expand All @@ -40,57 +42,37 @@ describe("axelar-query (node client)", () => {
);
});

test.skip("It should include the L1 gas fee", async () => {
test("It should include the L1 gas fee", async () => {
const l2RequestParams: EstimateGasFeeParams = {
sourceChain: "avalanche",
sourceChain: "ethereum",
destinationChain: "optimism",
gasLimit: 700_000n,
gasMultiplier: 1.1,
executeData: pad("0x1234", { size: 5000 }),
amount: 1,
amountInUnits: "1000000",
};

const fees = (await api.estimateGasFee({
const fees = (await mainnetApi.estimateGasFee({
...l2RequestParams,
showDetailedFees: true,
})) as EstimateGasFeeResponse;

const l1ExecutionFeeWithMultiplier = parseInt(
const l1ExecutionFeeWithMultiplier = BigInt(
fees.l1ExecutionFeeWithMultiplier
);
const executionFeeWithMultiplier = parseInt(
const l1ExecutionFee = BigInt(fees.l1ExecutionFee);
const executionFee = BigInt(fees.executionFee);
const executionFeeWithMultiplier = BigInt(
fees.executionFeeWithMultiplier
);

expect(fees).toBeTruthy();
expect(l1ExecutionFeeWithMultiplier).toBeGreaterThan(
executionFeeWithMultiplier
);
});

test("it should throw an error if the destination chain is L2 but not specified the executeData", async () => {
const l2RequestParams: EstimateGasFeeParams = {
sourceChain: "ethereum-2",
destinationChain: "optimism",
gasLimit: 700_000n,
gasMultiplier: 1.1,
amount: 1,
amountInUnits: "1000000",
};

await expect(
api.estimateGasFee({
...l2RequestParams,
showDetailedFees: true,
})
).rejects.toThrowError(
"executeData is required to calculate the L1 execution fee for optimism"
);
expect(l1ExecutionFeeWithMultiplier).toBeGreaterThan(l1ExecutionFee);
expect(executionFeeWithMultiplier).toBeGreaterThan(executionFee);
});

test("It should return a detailed object response with the components of the fee", async () => {
const res: EstimateGasFeeResponse = (await api.estimateGasFee({
const res: EstimateGasFeeResponse = (await mainnetApi.estimateGasFee({
...requestParam,
showDetailedFees: true,
})) as EstimateGasFeeResponse;
Expand Down
2 changes: 2 additions & 0 deletions packages/api/src/axelar-query/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
type HttpClientOptions,
} from "@axelarjs/utils/http-client";

import { createAxelarscanClient } from "../axelarscan";
import { createGMPClient } from "../gmp/client";
import { AxelarQueryAPIClient } from "./isomorphic";

Expand All @@ -17,6 +18,7 @@ export const createAxelarQueryClient = (
},
{
gmpClient: createGMPClient(env),
axelarscanClient: createAxelarscanClient(env),
},
env
);
3 changes: 3 additions & 0 deletions packages/api/src/axelar-query/constant.ts

Large diffs are not rendered by default.

39 changes: 28 additions & 11 deletions packages/api/src/axelar-query/fee/getL1Fee.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import { createGMPClient, GMPClient } from "../..";
import {
createAxelarscanClient,
createGMPClient,
GMPClient,
type EVMChainConfig,
} from "../..";
import { getL1FeeForL2 } from "./getL1Fee";
import { EstimateL1FeeParams } from "./types";

describe("getL1Fee", () => {
const env = "mainnet";
let client: GMPClient;
let configs: { evm: EVMChainConfig[] };

beforeAll(() => {
beforeAll(async () => {
client = createGMPClient(env);
const axelarscanClient = createAxelarscanClient(env);
configs = await axelarscanClient.getChainConfigs();
});

it("query arbitrum l1 fee should work", async () => {
Expand All @@ -17,31 +25,38 @@ describe("getL1Fee", () => {
});

const params: EstimateL1FeeParams = {
destinationContractAddress: "0xce16F69375520ab01377ce7B88f5BA8C48F8D666",
executeData:
"0x1a98b2e0e68ba0eb84262d4bcf91955ec2680b37bcedd59a1f48e18d183dac9961bf9d1400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000d40000000000000000000000000000000000000000000000000000000000deac2c6000000000000000000000000000000000000000000000000000000000000000762696e616e636500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a307863653136463639333735353230616230313337376365374238386635424138433438463844363636000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bc000000000000000000000000000000000000000000000000000000000000000400000000000000000000000004607cad6135d7a119185ebe062d3b369b1b536ef000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000009200000000000000000000000000000000000000000000000000000000000000a8000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f4052150000000000000000000000000000000000000000000000000000000000000001000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f405215000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000044095ea7b300000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc450000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f4052150000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000e404e45aaf000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f405215000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc800000000000000000000000000000000000000000000000000000000000000640000000000000000000000004fd39c9e151e50580779bd04b1f7ecc310079fd3000000000000000000000000000000000000000000000000000000000deac2c6000000000000000000000000000000000000000000000000000000000dc647500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f40521500000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000044095ea7b300000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc450000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc80000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000e404e45aaf000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc800000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab100000000000000000000000000000000000000000000000000000000000000640000000000000000000000004fd39c9e151e50580779bd04b1f7ecc310079fd3000000000000000000000000000000000000000000000000000000000de83dbf000000000000000000000000000000000000000000000000015d8c7908dbe7130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc80000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000100000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000242e1a7d4d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000004607cad6135d7a119185ebe062d3b369b1b536ef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000761786c5553444300000000000000000000000000000000000000000000000000",
l1GasOracleAddress: fees.destination_native_token.l1_gas_oracle_address!,
l1GasPrice: fees.destination_native_token.l1_gas_price_in_units!,
};

const fee = await getL1FeeForL2("mainnet", "arbitrum", params);
const rpcUrl = configs.evm.find((chain) => chain.id === "arbitrum")
?.endpoints.rpc?.[0];

const fee = await getL1FeeForL2(rpcUrl!, params);
expect(fee).toBeDefined();
});

it("query optimism l1 fee should work", async () => {
const destChain = "optimism";
const config = configs.evm.find((c) => c.id === destChain);
const rpcUrl = config?.endpoints.rpc[0];
const fees = await client.getFees({
sourceChain: "avalanche",
destinationChain: "optimism",
destinationChain: destChain,
});

// reference: https://optimistic.etherscan.io/tx/0x5203e3629019b8bae494ec5e6b83ddfaf660ae6d5c88ba79093f5f5429143c00
const params: EstimateL1FeeParams = {
destinationContractAddress: "0xce16F69375520ab01377ce7B88f5BA8C48F8D666",
executeData:
"0x1a98b2e04ee0e180bcfb26420ebb9e7a86f1fdf8c627d79ade87880bf74b7dd73c1b749b00000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000258380180000000000000000000000000000000000000000000000000000000000000000646616e746f6d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a3078636531364636393337353532306162303133373763653742383866354241384334384638443636360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000040000000000000000000000000c9f7113042615ce4796f8cbbfa6f42170d908e0500000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f4052150000000000000000000000000000000000000000000000000000000000000001000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f405215000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000044095ea7b300000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc450000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f4052150000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000e404e45aaf000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f4052150000000000000000000000007f5c764cbc14f9669b88837ca1490cca17c316070000000000000000000000000000000000000000000000000000000000000064000000000000000000000000c9f7113042615ce4796f8cbbfa6f42170d908e0500000000000000000000000000000000000000000000000000000002583801800000000000000000000000000000000000000000000000000000000254660d5a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000eb466342c4d449bc9f53a865d5cb90586f4052150000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000761786c5553444300000000000000000000000000000000000000000000000000",
l1GasPrice: fees.destination_native_token.l1_gas_price_in_units!,
l1GasOracleAddress: fees.destination_native_token.l1_gas_oracle_address!,
l2Type: "op",
};

const fee = await getL1FeeForL2("mainnet", "optimism", params);
const fee = await getL1FeeForL2(rpcUrl!, params);
expect(fee).toBeGreaterThan(0n);
});

Expand All @@ -52,14 +67,16 @@ describe("getL1Fee", () => {
});

const params: EstimateL1FeeParams = {
destinationContractAddress: "0xce16F69375520ab01377ce7B88f5BA8C48F8D666",
executeData:
"0x1a98b2e04ee0e180bcfb26420ebb9e7a86f1fdf8c627d79ade87880bf74b7dd73",
l1GasPrice: fees.destination_native_token.l1_gas_price_in_units!,
l2Type: "mantle",
l1GasOracleAddress: fees.destination_native_token.l1_gas_oracle_address!,
};
const rpcUrl = configs.evm.find((chain) => chain.id === "mantle")?.endpoints
?.rpc[0];

const fee = await getL1FeeForL2("mainnet", "mantle", params);
expect(fee).toBeDefined();
expect(fee).toBeGreaterThan(0n);
const fee = await getL1FeeForL2(rpcUrl!, params);
expect(fee).toBe(0n);
});
});
Loading

0 comments on commit dfcf1a1

Please sign in to comment.