Skip to content

Commit

Permalink
Merge branch 'master' into 2024-12-12-minor-update
Browse files Browse the repository at this point in the history
  • Loading branch information
rouzwelt authored Dec 26, 2024
2 parents ca70a8d + 76b2b17 commit a0c0364
Show file tree
Hide file tree
Showing 16 changed files with 160 additions and 140 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ Other optional arguments are:
- `--owner-profile`, Specifies the owner limit, example: --owner-profile 0x123456=12 . Will override the 'OWNER_PROFILE' in env variables
- `--public-rpc`, Allows to use public RPCs as fallbacks, default is false. Will override the 'PUBLIC_RPC' in env variables
- `--gas-price-multiplier`, Option to multiply the gas price fetched from the rpc as percentage, default is 107, ie +7%. Will override the 'GAS_PRICE_MULTIPLIER' in env variables
- `--gas-limit-multiplier`, Option to multiply the gas limit estimation from the rpc as percentage, default is 108, ie +8%. Will override the 'GAS_LIMIT_MULTIPLIER' in env variables
- `--tx-gas`, Option to set a static gas limit for all submitting txs. Will override the 'TX_GAS' in env variables
- `--gas-limit-multiplier`, Option to multiply the gas limit estimation from the rpc as percentage, default is 100, ie no change. Will override the 'GAS_LIMIT_MULTIPLIER' in env variables
- `--tx-gas`, Option to set a gas limit for all submitting txs optionally with appended percentage sign to apply as percentage to original gas. Will override the 'TX_GAS' in env variables
- `--rp-only`, Only clear orders through RP4, excludes intra and inter orderbook clears. Will override the 'RP_ONLY' in env variablesin env variables
- `-V` or `--version`, output the version number
- `-h` or `--help`, output usage information
Expand Down Expand Up @@ -263,10 +263,10 @@ ROUTE="single"
# Option to multiply the gas price fetched from the rpc as percentage, default is 107, ie +7%
GAS_PRICE_MULTIPLIER=

# Option to multiply the gas limit estimation from the rpc as percentage, default is 108, ie +8%
# Option to multiply the gas limit estimation from the rpc as percentage, default is 100, ie no change
GAS_LIMIT_MULTIPLIER=

# Option to set a static gas limit for all submitting txs
# Option to set a gas limit for all submitting txs optionally with appended percentage sign to apply as percentage to original gas
TX_GAS=

# Only clear orders through RP4, excludes intra and inter orderbook clears
Expand Down
4 changes: 2 additions & 2 deletions example.env
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ ROUTE="single"
# Option to multiply the gas price fetched from the rpc as percentage, default is 107, ie +7%
GAS_PRICE_MULTIPLIER=

# Option to multiply the gas limit estimation from the rpc as percentage, default is 108, ie +8%
# Option to multiply the gas limit estimation from the rpc as percentage, default is 100, ie no change
GAS_LIMIT_MULTIPLIER=

# Option to set a static gas limit for all submitting txs
# Option to set a gas limit for all submitting txs optionally with appended percentage sign to apply as percentage to original gas
TX_GAS=

# Only clear orders through RP4, excludes intra and inter orderbook clears
Expand Down
18 changes: 6 additions & 12 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,11 @@ const getOptions = async (argv: any, version?: string) => {
)
.option(
"--gas-limit-multiplier <integer>",
"Option to multiply the gas limit estimation from the rpc as percentage, default is 108, ie +8%. Will override the 'GAS_LIMIT_MULTIPLIER' in env variables",
"Option to multiply the gas limit estimation from the rpc as percentage, default is 100, ie no change. Will override the 'GAS_LIMIT_MULTIPLIER' in env variables",
)
.option(
"--tx-gas <integer>",
"Option to set a static gas limit for all submitting txs. Will override the 'TX_GAS' in env variables",
"Option to set a gas limit for all submitting txs optionally with appended percentage sign to apply as percentage to original gas. Will override the 'TX_GAS' in env variables",
)
.option(
"--rp-only",
Expand Down Expand Up @@ -452,18 +452,12 @@ export async function startup(argv: any, version?: string, tracer?: Tracer, ctx?
throw "invalid gasLimitMultiplier value, must be an integer greater than zero";
} else throw "invalid gasLimitMultiplier value, must be an integer greater than zero";
} else {
options.gasLimitMultiplier = 108;
options.gasLimitMultiplier = 100;
}
if (options.txGas) {
if (typeof options.txGas === "number") {
if (options.txGas <= 0 || !Number.isInteger(options.txGas))
throw "invalid txGas value, must be an integer greater than zero";
else options.txGas = BigInt(options.txGas);
} else if (typeof options.txGas === "string" && /^[0-9]+$/.test(options.txGas)) {
options.txGas = BigInt(options.txGas);
if (options.txGas <= 0n)
throw "invalid txGas value, must be an integer greater than zero";
} else throw "invalid txGas value, must be an integer greater than zero";
if (typeof options.txGas !== "string" || !/^[0-9]+%?$/.test(options.txGas)) {
throw "invalid txGas value, must be an integer greater than zero optionally with appended percentage sign to apply as percentage to original gas";
}
}
const poolUpdateInterval = _poolUpdateInterval * 60 * 1000;
let ordersDetails: SgOrder[] = [];
Expand Down
27 changes: 19 additions & 8 deletions src/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ export function errorSnapshot(
* Checks if a viem BaseError is from eth node, copied from
* "viem/_types/utils/errors/getNodeError" since not a default export
*/
export function containsNodeError(err: BaseError): boolean {
export function containsNodeError(err: BaseError, circuitBreaker = 0): boolean {
if (circuitBreaker > 25) return false;
try {
const snapshot = errorSnapshot("", err);
const parsed = parseRevertError(err);
Expand All @@ -145,7 +146,7 @@ export function containsNodeError(err: BaseError): boolean {
err instanceof InsufficientFundsError ||
(err instanceof RpcRequestError && err.code === ExecutionRevertedError.code) ||
(snapshot.includes("exceeds allowance") && !snapshot.includes("out of gas")) ||
("cause" in err && containsNodeError(err.cause as any))
("cause" in err && containsNodeError(err.cause as any, ++circuitBreaker))
);
} catch (error) {
return false;
Expand All @@ -155,14 +156,15 @@ export function containsNodeError(err: BaseError): boolean {
/**
* Checks if a viem BaseError is timeout error
*/
export function isTimeout(err: BaseError): boolean {
export function isTimeout(err: BaseError, circuitBreaker = 0): boolean {
if (circuitBreaker > 25) return false;
try {
return (
err instanceof TimeoutError ||
err instanceof TransactionNotFoundError ||
err instanceof TransactionReceiptNotFoundError ||
err instanceof WaitForTransactionReceiptTimeoutError ||
("cause" in err && isTimeout(err.cause as any))
("cause" in err && isTimeout(err.cause as any, ++circuitBreaker))
);
} catch (error) {
return false;
Expand Down Expand Up @@ -227,14 +229,23 @@ export async function handleRevert(
/**
* Parses a revert error to TxRevertError type
*/
export function parseRevertError(error: BaseError): TxRevertError {
export function parseRevertError(error: BaseError, circuitBreaker = 0): TxRevertError {
if (circuitBreaker > 25) {
return {
raw: {
code: -2,
message:
"Couldn't extract rpc error from the viem error object because the viem error object is circular",
},
};
}
if ("cause" in error) {
return parseRevertError(error.cause as any);
return parseRevertError(error.cause as any, ++circuitBreaker);
} else {
let decoded: DecodedError | undefined;
const raw: RawError = {
code: (error as any).code ?? NaN,
message: error.message,
code: (error as any).code ?? -2,
message: error.message ?? "No error msg",
data: (error as any).data ?? undefined,
};
if ("data" in error && isHex(error.data)) {
Expand Down
3 changes: 2 additions & 1 deletion src/modes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@ export async function findOpp({
fromToken: Token;
}): Promise<DryrunResult> {
try {
gasPrice = BigNumber.from(await viemClient.getGasPrice())
const gp = BigNumber.from(await viemClient.getGasPrice())
.mul(config.gasPriceMultiplier)
.div("100")
.toBigInt();
if (gp > gasPrice) gasPrice = gp;
} catch {
/**/
}
Expand Down
18 changes: 8 additions & 10 deletions src/modes/interOrderbook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { BaseError, PublicClient } from "viem";
import { getBountyEnsureBytecode } from "../config";
import { BigNumber, Contract, ethers } from "ethers";
import { containsNodeError, errorSnapshot } from "../error";
import { estimateProfit, extendSpanAttributes, withBigintSerializer } from "../utils";
import { BotConfig, BundledOrders, ViemClient, DryrunResult, SpanAttrs } from "../types";
import { estimateProfit, scale18To, withBigintSerializer, extendSpanAttributes } from "../utils";

/**
* Executes a extimateGas call for an inter-orderbook arb() tx, to determine if the tx is successfull ot not
Expand Down Expand Up @@ -39,16 +39,17 @@ export async function dryrun({
spanAttributes,
};

const maximumInput = maximumInputFixed.div(
"1" + "0".repeat(18 - orderPairObject.sellTokenDecimals),
);
const maximumInput = scale18To(maximumInputFixed, orderPairObject.sellTokenDecimals);
spanAttributes["maxInput"] = maximumInput.toString();

const opposingMaxInput = orderPairObject.takeOrders[0].quote!.ratio.isZero()
? ethers.constants.MaxUint256
: maximumInputFixed
.mul(orderPairObject.takeOrders[0].quote!.ratio)
.div(`1${"0".repeat(36 - orderPairObject.buyTokenDecimals)}`);
: scale18To(
maximumInputFixed
.mul(orderPairObject.takeOrders[0].quote!.ratio)
.div(`1${"0".repeat(18)}`),
orderPairObject.buyTokenDecimals,
);

const opposingMaxIORatio = orderPairObject.takeOrders[0].quote!.ratio.isZero()
? ethers.constants.MaxUint256
Expand Down Expand Up @@ -195,9 +196,6 @@ export async function dryrun({
}
}
rawtx.gas = gasLimit.toBigInt();
if (typeof config.txGas === "bigint") {
rawtx.gas = config.txGas;
}

// if reached here, it means there was a success and found opp
spanAttributes["oppBlockNumber"] = blockNumber;
Expand Down
54 changes: 24 additions & 30 deletions src/modes/intraOrderbook.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { orderbookAbi } from "../abis";
import { BigNumber, ethers } from "ethers";
import { BaseError, PublicClient } from "viem";
import { erc20Abi, orderbookAbi } from "../abis";
import { getWithdrawEnsureBytecode } from "../config";
import { BaseError, erc20Abi, PublicClient } from "viem";
import { containsNodeError, errorSnapshot } from "../error";
import { estimateProfit, extendSpanAttributes, withBigintSerializer } from "../utils";
import { estimateProfit, scale18, withBigintSerializer, extendSpanAttributes } from "../utils";
import {
SpanAttrs,
BotConfig,
BundledOrders,
ViemClient,
TakeOrderDetails,
DryrunResult,
SpanAttrs,
BundledOrders,
TakeOrderDetails,
} from "../types";

/**
Expand Down Expand Up @@ -211,9 +211,6 @@ export async function dryrun({
}
}
rawtx.gas = gasLimit.toBigInt();
if (typeof config.txGas === "bigint") {
rawtx.gas = config.txGas;
}

// if reached here, it means there was a success and found opp
spanAttributes["oppBlockNumber"] = blockNumber;
Expand Down Expand Up @@ -288,27 +285,24 @@ export async function findOpp({
if (!opposingOrders || !opposingOrders.length) throw undefined;

const allNoneNodeErrors: (string | undefined)[] = [];
const erc20 = new ethers.utils.Interface(erc20Abi);
const inputBalance = ethers.BigNumber.from(
(
await viemClient.call({
to: orderPairObject.buyToken as `0x${string}`,
data: erc20.encodeFunctionData("balanceOf", [
signer.account.address,
]) as `0x${string}`,
})
).data,
).mul("1" + "0".repeat(18 - orderPairObject.buyTokenDecimals));
const outputBalance = ethers.BigNumber.from(
(
await viemClient.call({
to: orderPairObject.sellToken as `0x${string}`,
data: erc20.encodeFunctionData("balanceOf", [
signer.account.address,
]) as `0x${string}`,
})
).data,
).mul("1" + "0".repeat(18 - orderPairObject.sellTokenDecimals));
const inputBalance = scale18(
await viemClient.readContract({
address: orderPairObject.buyToken as `0x${string}`,
abi: erc20Abi,
functionName: "balanceOf",
args: [signer.account.address],
}),
orderPairObject.buyTokenDecimals,
);
const outputBalance = scale18(
await viemClient.readContract({
address: orderPairObject.sellToken as `0x${string}`,
abi: erc20Abi,
functionName: "balanceOf",
args: [signer.account.address],
}),
orderPairObject.sellTokenDecimals,
);
for (let i = 0; i < opposingOrders.length; i++) {
try {
return await dryrun({
Expand Down
29 changes: 7 additions & 22 deletions src/modes/routeProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { BigNumber, Contract, ethers } from "ethers";
import { containsNodeError, errorSnapshot } from "../error";
import { BotConfig, BundledOrders, ViemClient, DryrunResult, SpanAttrs } from "../types";
import {
ONE18,
scale18,
scale18To,
RPoolFilter,
Expand All @@ -23,16 +24,6 @@ export enum RouteProcessorDryrunHaltReason {
NoRoute = 2,
}

/**
* Route Processor versions
*/
const getRouteProcessorParamsVersion = {
"3": Router.routeProcessor3Params,
"3.1": Router.routeProcessor3_1Params,
"3.2": Router.routeProcessor3_2Params,
"4": Router.routeProcessor4Params,
} as const;

/**
* Executes a extimateGas call for an arb() tx, to determine if the tx is successfull ot not
*/
Expand Down Expand Up @@ -72,9 +63,7 @@ export async function dryrun({
spanAttributes,
};

const maximumInput = maximumInputFixed.div(
"1" + "0".repeat(18 - orderPairObject.sellTokenDecimals),
);
const maximumInput = scale18To(maximumInputFixed, orderPairObject.sellTokenDecimals);
spanAttributes["amountIn"] = ethers.utils.formatUnits(maximumInputFixed);

// get route details from sushi dataFetcher
Expand All @@ -92,15 +81,14 @@ export async function dryrun({
config.route,
);
if (route.status == "NoWay") {
if (hasPriceMatch) hasPriceMatch.value = false;
spanAttributes["route"] = "no-way";
result.reason = RouteProcessorDryrunHaltReason.NoRoute;
return Promise.reject(result);
} else {
spanAttributes["amountOut"] = ethers.utils.formatUnits(route.amountOutBI, toToken.decimals);
const rateFixed = ethers.BigNumber.from(route.amountOutBI).mul(
"1" + "0".repeat(18 - orderPairObject.buyTokenDecimals),
);
const price = rateFixed.mul("1" + "0".repeat(18)).div(maximumInputFixed);
const rateFixed = scale18(route.amountOutBI, orderPairObject.buyTokenDecimals);
const price = rateFixed.mul(ONE18).div(maximumInputFixed);
spanAttributes["marketPrice"] = ethers.utils.formatEther(price);

const routeVisual: string[] = [];
Expand All @@ -121,7 +109,7 @@ export async function dryrun({
return Promise.reject(result);
}

const rpParams = getRouteProcessorParamsVersion["4"](
const rpParams = Router.routeProcessor4Params(
pcMap,
route,
fromToken,
Expand Down Expand Up @@ -274,9 +262,6 @@ export async function dryrun({
}
}
rawtx.gas = gasLimit.toBigInt();
if (typeof config.txGas === "bigint") {
rawtx.gas = config.txGas;
}

// if reached here, it means there was a success and found opp
// rest of span attr are not needed since they are present in the result.data
Expand Down Expand Up @@ -560,7 +545,7 @@ export function findMaxInput({
maximumInput = maximumInput.sub(initAmount.div(2 ** i));
} else {
const amountOut = scale18(route.amountOutBI, toToken.decimals);
const price = amountOut.mul("1" + "0".repeat(18)).div(maxInput18);
const price = amountOut.mul(ONE18).div(maxInput18);

if (price.lt(ratio)) {
maximumInput = maximumInput.sub(initAmount.div(2 ** i));
Expand Down
Loading

0 comments on commit a0c0364

Please sign in to comment.