Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: update l1 fee calculation in estimateGasFee #285

Merged
merged 15 commits into from
Mar 27, 2024
Merged
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
1 change: 1 addition & 0 deletions packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
},
"dependencies": {
"@axelarjs/core": "workspace:*",
"@axelarjs/utils": "workspace:*",
"isomorphic-unfetch": "^4.0.2",
"rambda": "^9.1.1",
"viem": "^2.8.11"
Expand Down
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
Loading