Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
rouzwelt committed Nov 21, 2024
1 parent 7630d7b commit 8d35140
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 53 deletions.
74 changes: 41 additions & 33 deletions src/modes/routeProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export async function dryrun({
ethPrice,
config,
viemClient,
hasPriceMatch,
}: {
mode: number;
config: BotConfig;
Expand All @@ -61,6 +62,7 @@ export async function dryrun({
toToken: Token;
fromToken: Token;
maximumInput: BigNumber;
hasPriceMatch?: { value: boolean };
}) {
const spanAttributes: SpanAttrs = {};
const result: DryrunResult = {
Expand Down Expand Up @@ -112,6 +114,7 @@ export async function dryrun({

// exit early if market price is lower than order quote ratio
if (price.lt(orderPairObject.takeOrders[0].quote!.ratio)) {
if (hasPriceMatch) hasPriceMatch.value = false;
result.reason = RouteProcessorDryrunHaltReason.NoOpportunity;
spanAttributes["error"] = "Order's ratio greater than market price";
return Promise.reject(result);
Expand Down Expand Up @@ -333,6 +336,9 @@ export async function findOpp({
};

let noRoute = true;
const hasPriceMatch = {
value: true,
};
const initAmount = orderPairObject.takeOrders.reduce(
(a, b) => a.add(b.quote!.maxOutput),
ethers.constants.Zero,
Expand All @@ -355,45 +361,47 @@ export async function findOpp({
ethPrice,
config,
viemClient,
hasPriceMatch,
});
} catch (e: any) {
// the fail reason can only be no route in case all hops fail reasons are no route
if (e.reason !== RouteProcessorDryrunHaltReason.NoRoute) noRoute = false;
allNoneNodeErrors.push(e?.value?.noneNodeError);
allHopsAttributes.push(JSON.stringify(e.spanAttributes));
}
const maxTradeSize = findMaxInput({
orderPairObject,
dataFetcher,
fromToken,
toToken,
maximumInput,
gasPrice,
config,
});
if (maxTradeSize) {
try {
return await dryrun({
mode,
orderPairObject,
dataFetcher,
fromToken,
toToken,
signer,
maximumInput: maxTradeSize,
gasPrice,
arb,
ethPrice,
config,
viemClient,
});
} catch (e: any) {
// the fail reason can only be no route in case all hops fail reasons are no route
if (e.reason !== RouteProcessorDryrunHaltReason.NoRoute) noRoute = false;
delete e.spanAttributes["error"];
delete e.spanAttributes["rawtx"];
allNoneNodeErrors.push(e?.value?.noneNodeError);
allHopsAttributes.push(JSON.stringify(e.spanAttributes));
if (!hasPriceMatch.value) {
const maxTradeSize = findMaxInput({
orderPairObject,
dataFetcher,
fromToken,
toToken,
maximumInput,
gasPrice,
config,
});
if (maxTradeSize) {
try {
return await dryrun({
mode,
orderPairObject,
dataFetcher,
fromToken,
toToken,
signer,
maximumInput: maxTradeSize,
gasPrice,
arb,
ethPrice,
config,
viemClient,
});
} catch (e: any) {
// the fail reason can only be no route in case all hops fail reasons are no route
if (e.reason !== RouteProcessorDryrunHaltReason.NoRoute) noRoute = false;
delete e.spanAttributes["rawtx"];
allNoneNodeErrors.push(e?.value?.noneNodeError);
allHopsAttributes.push(JSON.stringify(e.spanAttributes));
}
}
}
// in case of no successfull hop, allHopsAttributes will be included
Expand Down Expand Up @@ -555,7 +563,7 @@ export function findMaxInput({
} else {
const amountOut = scale18(route.amountOutBI, toToken.decimals);
if (amountOut.gte(maximumOutput)) {
result.unshift(maximumInput);
result.unshift(scale18(maximumInput, fromToken.decimals));
maximumInput = maximumInput.add(initAmount.div(2 ** i));
} else {
maximumInput = maximumInput.sub(initAmount.div(2 ** i));
Expand Down
39 changes: 19 additions & 20 deletions test/mode-routeProcessor.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { assert } = require("chai");
const testData = require("./data");
const { errorSnapshot } = require("../src/error");
const { estimateProfit } = require("../src/utils");
const { estimateProfit, clone } = require("../src/utils");
const {
ethers,
utils: { formatUnits },
Expand Down Expand Up @@ -331,18 +331,17 @@ describe("Test route processor find opp", async function () {
dataFetcher.getCurrentPoolCodeMap = () => {
return poolCodeMap;
};
// mock the signer to reject the first attempt on gas estimation
// so the dryrun goes into binary search
let rejectFirst = true;
signer.estimateGas = async () => {
if (rejectFirst) {
rejectFirst = false;
return Promise.reject(ethers.errors.UNPREDICTABLE_GAS_LIMIT);
} else return gasLimitEstimation;
return gasLimitEstimation;
};
const orderPairObjectCopy = clone(orderPairObject);
orderPairObjectCopy.takeOrders[0].quote.ratio = ethers.utils.parseUnits("0.009900695135");
orderPairObjectCopy.takeOrders[0].quote.maxOutput = ethers.BigNumber.from(
"1" + "0".repeat(25),
);
const result = await findOpp({
mode: 0,
orderPairObject,
orderPairObject: orderPairObjectCopy,
dataFetcher,
fromToken,
toToken,
Expand All @@ -355,7 +354,7 @@ describe("Test route processor find opp", async function () {
});
const expectedTakeOrdersConfigStruct = {
minimumInput: ethers.constants.One,
maximumInput: ethers.utils.parseUnits("9.999999701976776119"),
maximumInput: ethers.utils.parseUnits("9999999.701976776123046875"),
maximumIORatio: ethers.constants.MaxUint256,
orders: [orderPairObject.takeOrders[0].takeOrder],
data: expectedRouteData,
Expand Down Expand Up @@ -384,26 +383,28 @@ describe("Test route processor find opp", async function () {
gasPrice,
gas: gasLimitEstimation.toBigInt(),
},
maximumInput: ethers.utils.parseUnits("9.999999701976776119"),
price: getCurrentPrice(ethers.utils.parseUnits("9.999999701976776119")),
maximumInput: ethers.utils.parseUnits("9999999.701976776123046875"),
price: getCurrentPrice(ethers.utils.parseUnits("9999999.701976776123046875")),
routeVisual: expectedRouteVisual,
oppBlockNumber,
estimatedProfit: estimateProfit(
orderPairObject,
orderPairObjectCopy,
ethers.utils.parseUnits(ethPrice),
undefined,
undefined,
ethers.utils.parseUnits("0.996900529709950975"),
ethers.utils.parseUnits("9.999999701976776119"),
ethers.utils.parseUnits("0.009900695426163716"),
ethers.utils.parseUnits("9999999.701976776123046875"),
),
},
reason: undefined,
spanAttributes: {
oppBlockNumber,
foundOpp: true,
amountIn: "9.999999701976776119",
amountOut: "9.969005",
marketPrice: "0.996900529709950975",
amountIn: "9999999.701976776123046875",
amountOut: "99006.951311",
marketPrice: ethers.utils.formatUnits(
getCurrentPrice(ethers.utils.parseUnits("9999999.701976776123046875")),
),
route: expectedRouteVisual,
},
};
Expand Down Expand Up @@ -472,7 +473,6 @@ describe("Test route processor find opp", async function () {
spanAttributes: {
hops: [
`{"amountIn":"${formatUnits(vaultBalance)}","amountOut":"${formatUnits(getAmountOut(vaultBalance), 6)}","marketPrice":"${formatUnits(getCurrentPrice(vaultBalance))}","route":${JSON.stringify(expectedRouteVisual)},"blockNumber":${oppBlockNumber},"stage":1,"isNodeError":false,"error":${JSON.stringify(errorSnapshot("", ethers.errors.UNPREDICTABLE_GAS_LIMIT))},"rawtx":${JSON.stringify(rawtx)}}`,
`{"amountIn":"9.999999701976776119","amountOut":"9.969005","marketPrice":"0.996900529709950975","route":${JSON.stringify(expectedRouteVisual)},"blockNumber":${oppBlockNumber},"stage":1,"isNodeError":false}`,
],
},
};
Expand Down Expand Up @@ -669,7 +669,6 @@ describe("Test find opp with retries", async function () {
spanAttributes: {
hops: [
`{"amountIn":"${formatUnits(vaultBalance)}","amountOut":"${formatUnits(getAmountOut(vaultBalance), 6)}","marketPrice":"${formatUnits(getCurrentPrice(vaultBalance))}","route":${JSON.stringify(expectedRouteVisual)},"blockNumber":${oppBlockNumber},"stage":1,"isNodeError":false,"error":${JSON.stringify(errorSnapshot("", ethers.errors.UNPREDICTABLE_GAS_LIMIT))},"rawtx":${JSON.stringify(rawtx)}}`,
`{"amountIn":"9.999999701976776119","amountOut":"9.969005","marketPrice":"0.996900529709950975","route":${JSON.stringify(expectedRouteVisual)},"blockNumber":${oppBlockNumber},"stage":1,"isNodeError":false}`,
],
},
};
Expand Down

0 comments on commit 8d35140

Please sign in to comment.