Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
rouzwelt committed Jan 20, 2025
1 parent 9c970ab commit b32a96c
Show file tree
Hide file tree
Showing 9 changed files with 281 additions and 140 deletions.
2 changes: 1 addition & 1 deletion src/account.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ChainId, RPParams } from "sushi";
import { BigNumber, ethers } from "ethers";
import { estimateGasCost, getTxFee } from "./gas";
import { estimateGasCost, getTxFee } from "./tx";
import { ErrorSeverity, errorSnapshot } from "./error";
import { Native, Token, WNATIVE } from "sushi/currency";
import { ROUTE_PROCESSOR_4_ADDRESS } from "sushi/config";
Expand Down
2 changes: 1 addition & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { config } from "dotenv";
import { isAddress } from "viem";
import { getGasPrice } from "./gas";
import { getGasPrice } from "./tx";
import { Command } from "commander";
import { getMetaInfo } from "./config";
import { BigNumber, ethers } from "ethers";
Expand Down
264 changes: 132 additions & 132 deletions src/gas.ts
Original file line number Diff line number Diff line change
@@ -1,141 +1,141 @@
import { ChainId } from "sushi";
import { BigNumber } from "ethers";
import { getQuoteConfig } from "./utils";
import { publicActionsL2 } from "viem/op-stack";
import { encodeFunctionData, multicall3Abi, toHex } from "viem";
import { BotConfig, BundledOrders, OperationState, RawTx, ViemClient } from "./types";
import { ArbitrumNodeInterfaceAbi, ArbitrumNodeInterfaceAddress, OrderbookQuoteAbi } from "./abis";
// import { ChainId } from "sushi";
// import { BigNumber } from "ethers";
// import { getQuoteConfig } from "./utils";
// import { publicActionsL2 } from "viem/op-stack";
// import { encodeFunctionData, multicall3Abi, toHex } from "viem";
// import { BotConfig, BundledOrders, OperationState, RawTx, ViemClient } from "./types";
// import { ArbitrumNodeInterfaceAbi, ArbitrumNodeInterfaceAddress, OrderbookQuoteAbi } from "./abis";

// default gas price for bsc chain, 1 gwei
export const BSC_DEFAULT_GAS_PRICE = 1_000_000_000n as const;
// // default gas price for bsc chain, 1 gwei
// export const BSC_DEFAULT_GAS_PRICE = 1_000_000_000n as const;

/**
* Estimates gas cost of the given tx, also takes into account L1 gas cost if the chain is a special L2.
*/
export async function estimateGasCost(
tx: RawTx,
signer: ViemClient,
config: BotConfig,
l1GasPrice?: bigint,
l1Signer?: any,
) {
const gasPrice =
tx.gasPrice ?? ((await signer.getGasPrice()) * BigInt(config.gasPriceMultiplier)) / 100n;
const gas = await signer.estimateGas(tx);
const result = {
gas,
gasPrice,
l1GasPrice: 0n,
l1Cost: 0n,
totalGasCost: gasPrice * gas,
};
if (config.isSpecialL2) {
try {
const l1Signer_ = l1Signer ? l1Signer : signer.extend(publicActionsL2());
if (typeof l1GasPrice !== "bigint") {
l1GasPrice = (await l1Signer_.getL1BaseFee()) as bigint;
}
const l1Cost = await l1Signer_.estimateL1Fee({
to: tx.to,
data: tx.data,
});
result.l1GasPrice = l1GasPrice;
result.l1Cost = l1Cost;
result.totalGasCost += l1Cost;
} catch {}
}
return result;
}
// /**
// * Estimates gas cost of the given tx, also takes into account L1 gas cost if the chain is a special L2.
// */
// export async function estimateGasCost(
// tx: RawTx,
// signer: ViemClient,
// config: BotConfig,
// l1GasPrice?: bigint,
// l1Signer?: any,
// ) {
// const gasPrice =
// tx.gasPrice ?? ((await signer.getGasPrice()) * BigInt(config.gasPriceMultiplier)) / 100n;
// const gas = await signer.estimateGas(tx);
// const result = {
// gas,
// gasPrice,
// l1GasPrice: 0n,
// l1Cost: 0n,
// totalGasCost: gasPrice * gas,
// };
// if (config.isSpecialL2) {
// try {
// const l1Signer_ = l1Signer ? l1Signer : signer.extend(publicActionsL2());
// if (typeof l1GasPrice !== "bigint") {
// l1GasPrice = (await l1Signer_.getL1BaseFee()) as bigint;
// }
// const l1Cost = await l1Signer_.estimateL1Fee({
// to: tx.to,
// data: tx.data,
// });
// result.l1GasPrice = l1GasPrice;
// result.l1Cost = l1Cost;
// result.totalGasCost += l1Cost;
// } catch {}
// }
// return result;
// }

/**
* Retruns the L1 gas cost of a transaction if operating chain is special L2 else returns 0.
*/
export function getL1Fee(receipt: any, config: BotConfig): bigint {
if (!config.isSpecialL2) return 0n;
// /**
// * Retruns the L1 gas cost of a transaction if operating chain is special L2 else returns 0.
// */
// export function getL1Fee(receipt: any, config: BotConfig): bigint {
// if (!config.isSpecialL2) return 0n;

if (typeof receipt.l1Fee === "bigint") {
return receipt.l1Fee;
} else if (typeof receipt.l1GasPrice === "bigint" && typeof receipt.l1GasUsed === "bigint") {
return (receipt.l1GasPrice as bigint) * (receipt.l1GasUsed as bigint);
} else {
return 0n;
}
}
// if (typeof receipt.l1Fee === "bigint") {
// return receipt.l1Fee;
// } else if (typeof receipt.l1GasPrice === "bigint" && typeof receipt.l1GasUsed === "bigint") {
// return (receipt.l1GasPrice as bigint) * (receipt.l1GasUsed as bigint);
// } else {
// return 0n;
// }
// }

/**
* Get Transaction total gas cost from receipt (includes L1 fee)
*/
export function getTxFee(receipt: any, config: BotConfig): bigint {
const gasUsed = BigNumber.from(receipt.gasUsed).toBigInt();
const effectiveGasPrice = BigNumber.from(receipt.effectiveGasPrice).toBigInt();
return effectiveGasPrice * gasUsed + getL1Fee(receipt, config);
}
// /**
// * Get Transaction total gas cost from receipt (includes L1 fee)
// */
// export function getTxFee(receipt: any, config: BotConfig): bigint {
// const gasUsed = BigNumber.from(receipt.gasUsed).toBigInt();
// const effectiveGasPrice = BigNumber.from(receipt.effectiveGasPrice).toBigInt();
// return effectiveGasPrice * gasUsed + getL1Fee(receipt, config);
// }

/**
* Fetches the gas price (L1 gas price as well if chain is special L2)
*/
export async function getGasPrice(config: BotConfig, state: OperationState) {
const promises = [config.viemClient.getGasPrice()];
if (config.isSpecialL2) {
const l1Client = config.viemClient.extend(publicActionsL2());
promises.push(l1Client.getL1BaseFee());
}
const [gasPriceResult, l1GasPriceResult = undefined] = await Promise.allSettled(promises);
if (gasPriceResult.status === "fulfilled") {
let gasPrice = gasPriceResult.value;
if (config.chain.id === ChainId.BSC && gasPrice < BSC_DEFAULT_GAS_PRICE) {
gasPrice = BSC_DEFAULT_GAS_PRICE;
}
state.gasPrice = (gasPrice * BigInt(config.gasPriceMultiplier)) / 100n;
}
if (l1GasPriceResult?.status === "fulfilled") {
state.l1GasPrice = l1GasPriceResult.value;
}
}
// /**
// * Fetches the gas price (L1 gas price as well if chain is special L2)
// */
// export async function getGasPrice(config: BotConfig, state: OperationState) {
// const promises = [config.viemClient.getGasPrice()];
// if (config.isSpecialL2) {
// const l1Client = config.viemClient.extend(publicActionsL2());
// promises.push(l1Client.getL1BaseFee());
// }
// const [gasPriceResult, l1GasPriceResult = undefined] = await Promise.allSettled(promises);
// if (gasPriceResult.status === "fulfilled") {
// let gasPrice = gasPriceResult.value;
// if (config.chain.id === ChainId.BSC && gasPrice < BSC_DEFAULT_GAS_PRICE) {
// gasPrice = BSC_DEFAULT_GAS_PRICE;
// }
// state.gasPrice = (gasPrice * BigInt(config.gasPriceMultiplier)) / 100n;
// }
// if (l1GasPriceResult?.status === "fulfilled") {
// state.l1GasPrice = l1GasPriceResult.value;
// }
// }

/**
* Calculates the gas limit that used for quoting orders
*/
export async function getQuoteGas(
config: BotConfig,
orderDetails: BundledOrders,
multicallAddressOverride?: string,
): Promise<bigint> {
if (config.chain.id === ChainId.ARBITRUM) {
// build the calldata of a quote call
const quoteConfig = getQuoteConfig(orderDetails.takeOrders[0]) as any;
quoteConfig.inputIOIndex = BigInt(quoteConfig.inputIOIndex);
quoteConfig.outputIOIndex = BigInt(quoteConfig.outputIOIndex);
quoteConfig.order.evaluable.bytecode = toHex(quoteConfig.order.evaluable.bytecode);
const multicallConfig = {
target: orderDetails.orderbook as `0x${string}`,
allowFailure: true,
callData: encodeFunctionData({
abi: OrderbookQuoteAbi,
functionName: "quote",
args: [quoteConfig],
}),
};
const calldata = encodeFunctionData({
abi: multicall3Abi,
functionName: "aggregate3",
args: [[multicallConfig] as const],
});
// /**
// * Calculates the gas limit that used for quoting orders
// */
// export async function getQuoteGas(
// config: BotConfig,
// orderDetails: BundledOrders,
// multicallAddressOverride?: string,
// ): Promise<bigint> {
// if (config.chain.id === ChainId.ARBITRUM) {
// // build the calldata of a quote call
// const quoteConfig = getQuoteConfig(orderDetails.takeOrders[0]) as any;
// quoteConfig.inputIOIndex = BigInt(quoteConfig.inputIOIndex);
// quoteConfig.outputIOIndex = BigInt(quoteConfig.outputIOIndex);
// quoteConfig.order.evaluable.bytecode = toHex(quoteConfig.order.evaluable.bytecode);
// const multicallConfig = {
// target: orderDetails.orderbook as `0x${string}`,
// allowFailure: true,
// callData: encodeFunctionData({
// abi: OrderbookQuoteAbi,
// functionName: "quote",
// args: [quoteConfig],
// }),
// };
// const calldata = encodeFunctionData({
// abi: multicall3Abi,
// functionName: "aggregate3",
// args: [[multicallConfig] as const],
// });

const multicallAddress =
(multicallAddressOverride as `0x${string}` | undefined) ??
config.viemClient.chain?.contracts?.multicall3?.address;
if (!multicallAddress) throw "unknown multicall address";
// const multicallAddress =
// (multicallAddressOverride as `0x${string}` | undefined) ??
// config.viemClient.chain?.contracts?.multicall3?.address;
// if (!multicallAddress) throw "unknown multicall address";

// call Arbitrum Node Interface for the calldata to get L1 gas
const result = await config.viemClient.simulateContract({
abi: ArbitrumNodeInterfaceAbi,
address: ArbitrumNodeInterfaceAddress,
functionName: "gasEstimateL1Component",
args: [multicallAddress, false, calldata],
});
return config.quoteGas + result.result[0];
} else {
return config.quoteGas;
}
}
// // call Arbitrum Node Interface for the calldata to get L1 gas
// const result = await config.viemClient.simulateContract({
// abi: ArbitrumNodeInterfaceAbi,
// address: ArbitrumNodeInterfaceAddress,
// functionName: "gasEstimateL1Component",
// args: [multicallAddress, false, calldata],
// });
// return config.quoteGas + result.result[0];
// } else {
// return config.quoteGas;
// }
// }
2 changes: 1 addition & 1 deletion src/modes/interOrderbook.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { orderbookAbi } from "../abis";
import { estimateGasCost } from "../gas";
import { estimateGasCost } from "../tx";
import { BigNumber, Contract, ethers } from "ethers";
import { containsNodeError, errorSnapshot } from "../error";
import { getBountyEnsureRainlang, parseRainlang } from "../task";
Expand Down
2 changes: 1 addition & 1 deletion src/modes/intraOrderbook.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { orderbookAbi } from "../abis";
import { estimateGasCost } from "../gas";
import { estimateGasCost } from "../tx";
import { BigNumber, ethers } from "ethers";
import { containsNodeError, errorSnapshot } from "../error";
import { getWithdrawEnsureRainlang, parseRainlang } from "../task";
Expand Down
2 changes: 1 addition & 1 deletion src/modes/routeProcessor.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Token } from "sushi/currency";
import { estimateGasCost } from "../gas";
import { estimateGasCost } from "../tx";
import { ChainId, DataFetcher, Router } from "sushi";
import { BigNumber, Contract, ethers } from "ethers";
import { containsNodeError, errorSnapshot } from "../error";
Expand Down
2 changes: 1 addition & 1 deletion src/processOrders.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ChainId } from "sushi";
import { findOpp } from "./modes";
import { getGasPrice, getQuoteGas } from "./gas";
import { getGasPrice, getQuoteGas } from "./tx";
import { PublicClient } from "viem";
import { Token } from "sushi/currency";
import { createViemClient } from "./config";
Expand Down
Loading

0 comments on commit b32a96c

Please sign in to comment.