Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config.env.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ botMinBalance: $BOT_MIN_BALANCE
gasPriceMultiplier: $GAS_PRICE_MULTIPLIER
txTimeThreshold: $TX_TIME_THRESHOLD
blockTime: $BLOCK_TIME
routerPartialFallback: $ROUTER_PARTIAL_FALLBACK
gasBoostProfitThreshold: $GAS_BOOST_PROFIT_THRESHOLD
gasBoostMultiplier: $GAS_BOOST_MULTIPLIER
gasBoostUsdThreshold: $GAS_BOOST_USD_THRESHOLD
Expand Down
3 changes: 3 additions & 0 deletions config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ txTimeThreshold: 15000
# The average block time (in ms) of the operating chain, used as the polling interval of the block number watcher, default is 5000ms (5 seconds)
blockTime: 2000

# Enables the halving backoff retries for router mode partial trades that get rejected onchain, default is true
routerPartialFallback: true

# Time (in minutes) to to check the operating wallet balances, 0 means dont ever check wallet balance, default is 15 mins
checkWalletBalanceTime: 15

Expand Down
1 change: 1 addition & 0 deletions src/cli/commands/sweep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export async function sweepFunds(opts: SweepOptions) {
gasPriceMultiplier: 107,
txTimeThreshold: 2_500,
blockTime: 5_000,
routerPartialFallback: true,
timeout: 15_000,

// unused fields but need to be defined
Expand Down
3 changes: 3 additions & 0 deletions src/config/yaml.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ botMinBalance: 50.5
gasPriceMultiplier: 150
txTimeThreshold: 4000
blockTime: 3000
routerPartialFallback: false
checkWalletBalanceTime: 30
gasBoostProfitThreshold: 7
gasBoostMultiplier: 3.5
Expand Down Expand Up @@ -166,6 +167,7 @@ orderbookTradeTypes:
sweepWalletTime: 0,
convertToGasTime: 0,
rotateMultiWallet: false,
routerPartialFallback: false,
checkWalletBalanceTime: 30,
gasBoostProfitThreshold: 7,
gasBoostMultiplier: 3.5,
Expand Down Expand Up @@ -358,6 +360,7 @@ orderbookTradeTypes:
assert.equal(result.sweepWalletTime, 10);
assert.equal(result.convertToGasTime, 2);
assert.equal(result.rotateMultiWallet, true);
assert.equal(result.routerPartialFallback, true); // should be default true
assert.equal(result.checkWalletBalanceTime, 15); // should be default 15
assert.equal(result.wsRpc, undefined); // no ws rpc when unset
assert.equal(result.gasBoostProfitThreshold, undefined); // no boost when unset
Expand Down
7 changes: 7 additions & 0 deletions src/config/yaml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ export type AppOptions = {
txTimeThreshold: number;
/** The average block time (in ms) of the operating chain, used as the polling interval of the block number watcher, default is 5000 ms */
blockTime: number;
/** Enables the halving backoff retries for router mode partial trades that get rejected onchain, default is true */
routerPartialFallback: boolean;
/** Time (in minutes) to to check the operating wallet balances, 0 means dont ever check wallet balance, default is 15 mins */
checkWalletBalanceTime: number;
/** Optional threshold as the min expected bounty multiple that the estimated profit must exceed to boost the tx gas price, no boost applies if unset */
Expand Down Expand Up @@ -379,6 +381,11 @@ export namespace AppOptions {
"invalid blockTime value, must be an integer greater than 0",
),
),
routerPartialFallback: Validator.resolveBool(
input.routerPartialFallback,
"expected a boolean value for routerPartialFallback",
true,
),
checkWalletBalanceTime: Validator.resolveNumericValue(
input.checkWalletBalanceTime,
INT_PATTERN,
Expand Down
43 changes: 42 additions & 1 deletion src/core/modes/router/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ describe("Test findBestRouterTrade", () => {
};
destination = "0xdestination";
mockRainSolver = {
appOptions: {},
appOptions: { routerPartialFallback: true },
state: {
gasPrice: 100n,
client: {
Expand Down Expand Up @@ -560,6 +560,47 @@ describe("Test findBestRouterTrade", () => {
expect(result.error.spanAttributes["partialFallback2.error"]).toBeUndefined();
});

it("should skip backoff when routerPartialFallback is disabled in config", async () => {
mockRainSolver.appOptions.routerPartialFallback = false;
const mockFullTradeError = Result.err({
type: TradeType.RouteProcessor,
reason: SimulationHaltReason.OrderRatioGreaterThanMarketPrice,
spanAttributes: { error: "ratio too high" },
noneNodeError: "order ratio issue",
});
const mockViolationError = Result.err({
type: TradeType.RouteProcessor,
reason: SimulationHaltReason.NoOpportunity,
spanAttributes: {
error: "execution reverted: MinimalOutputBalanceViolation(0xtoken, 123)",
},
});

(trySimulateTradeSpy as Mock)
.mockResolvedValueOnce(mockFullTradeError) // full size
.mockResolvedValue(mockViolationError); // partial size
(mockRainSolver.state.router.findLargestTradeSize as Mock).mockReturnValue(1000n);

const result: SimulationResult = await findBestRouterTrade.call(
mockRainSolver,
orderDetails,
signer,
ethPrice,
toToken,
fromToken,
blockNumber,
);

assert(result.isErr());
// only 1 full + 1 partial, no fallback attempts despite the violation error
expect(trySimulateTradeSpy).toHaveBeenCalledTimes(2);
expect(result.error.reason).toBe(SimulationHaltReason.NoOpportunity);
expect(result.error.spanAttributes["partial.error"]).toContain(
"MinimalOutputBalanceViolation",
);
expect(result.error.spanAttributes["partialFallback1.error"]).toBeUndefined();
});

it("should retry with the failing route dexes excluded when full trade dryrun fails", async () => {
const sushiQuote = {
route: {
Expand Down
7 changes: 5 additions & 2 deletions src/core/modes/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,12 @@ export async function tryFindBestRouterTrade(
// it means the offchain pool data overestimated the output for the found partial trade
// size, so backoff by halving the trade size at each step validated against onchain
// dryrun and accept the first size that passes, the backoff stops early if a step fails
// with any other error
// with any other error, the backoff only runs when enabled by config
const reason = partialTradeSizeSimResult.error.reason;
if (SimulationHaltReason.needsRetry(partialTradeSizeSimResult.error.spanAttributes["error"])) {
if (
this.appOptions.routerPartialFallback &&
SimulationHaltReason.needsRetry(partialTradeSizeSimResult.error.spanAttributes["error"])
) {
let fallbackTradeSize = partialTradeSize;
for (let i = 1; i <= 4; i++) {
fallbackTradeSize /= 2n;
Expand Down
Loading