From 94375a705c14f3390c1cd43bcbae98b4a089eb3c Mon Sep 17 00:00:00 2001 From: "Siyu Jiang (See-You John)" <91580504+jsy1218@users.noreply.github.com> Date: Mon, 9 Dec 2024 10:45:06 -0800 Subject: [PATCH] chore: bump sor to 4.8.7 - feat: tenderly sim status SlippageTooLow (#780) * feat: tenderly sim status SlippageTooLow * add unit test * feedback * 4.8.7 --- package-lock.json | 4 +- package.json | 2 +- src/providers/simulation-provider.ts | 1 + src/providers/tenderly-simulation-provider.ts | 17 +++++++ .../tick-based-heuristic-gas-model.ts | 13 ++++-- src/util/tenderlySimulationErrorBreakDown.ts | 21 +++++++++ .../tenderlySimulationErrorBreakDown.test.ts | 46 +++++++++++++++++++ 7 files changed, 96 insertions(+), 8 deletions(-) create mode 100644 src/util/tenderlySimulationErrorBreakDown.ts create mode 100644 test/unit/util/tenderlySimulationErrorBreakDown.test.ts diff --git a/package-lock.json b/package-lock.json index 8b3b51de0..265ead981 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@uniswap/smart-order-router", - "version": "4.8.6", + "version": "4.8.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@uniswap/smart-order-router", - "version": "4.8.6", + "version": "4.8.7", "license": "GPL", "dependencies": { "@eth-optimism/sdk": "^3.2.2", diff --git a/package.json b/package.json index ebcb38965..e897978d9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@uniswap/smart-order-router", - "version": "4.8.6", + "version": "4.8.7", "description": "Uniswap Smart Order Router", "main": "build/main/index.js", "typings": "build/main/index.d.ts", diff --git a/src/providers/simulation-provider.ts b/src/providers/simulation-provider.ts index 4ae6e1aec..b2143297e 100644 --- a/src/providers/simulation-provider.ts +++ b/src/providers/simulation-provider.ts @@ -32,6 +32,7 @@ export enum SimulationStatus { InsufficientBalance = 3, NotApproved = 4, SystemDown = 5, + SlippageTooLow = 6, } /** diff --git a/src/providers/tenderly-simulation-provider.ts b/src/providers/tenderly-simulation-provider.ts index 0fd945914..3e34790ff 100644 --- a/src/providers/tenderly-simulation-provider.ts +++ b/src/providers/tenderly-simulation-provider.ts @@ -31,6 +31,7 @@ import { initSwapRouteFromExisting, } from '../util/gas-factory-helpers'; +import { breakDownTenderlySimulationError } from '../util/tenderlySimulationErrorBreakDown'; import { EthEstimateGasSimulator } from './eth-estimate-gas-provider'; import { IPortionProvider } from './portion-provider'; import { @@ -464,6 +465,22 @@ export class TenderlySimulator extends Simulator { 2 )}.` ); + + if ( + resp && + resp.result && + resp.result.length >= 3 && + (resp.result[2] as JsonRpcError).error && + (resp.result[2] as JsonRpcError).error.data + ) { + return { + ...swapRoute, + simulationStatus: breakDownTenderlySimulationError( + (resp.result[2] as JsonRpcError).error.data + ), + }; + } + return { ...swapRoute, simulationStatus: SimulationStatus.Failed }; } diff --git a/src/routers/alpha-router/gas-models/tick-based-heuristic-gas-model.ts b/src/routers/alpha-router/gas-models/tick-based-heuristic-gas-model.ts index fa4475b69..1cbc15b84 100644 --- a/src/routers/alpha-router/gas-models/tick-based-heuristic-gas-model.ts +++ b/src/routers/alpha-router/gas-models/tick-based-heuristic-gas-model.ts @@ -208,13 +208,16 @@ export abstract class TickBasedHeuristicGasModelFactory< // Only use syntheticGasCostInTermsOfQuoteToken if it's within 30% of the original gasCostInTermsOfQuoteToken as a safeguard. if ( syntheticGasCostInTermsOfQuoteToken !== null && - (gasCostInTermsOfQuoteToken === null || ( - syntheticGasCostInTermsOfQuoteToken.lessThan( + (gasCostInTermsOfQuoteToken === null || + (syntheticGasCostInTermsOfQuoteToken.lessThan( gasCostInTermsOfQuoteToken.asFraction ) && - gasCostInTermsOfQuoteToken.subtract(syntheticGasCostInTermsOfQuoteToken) - .lessThan(gasCostInTermsOfQuoteToken.multiply(new Percent(30, 100)).asFraction) - )) + gasCostInTermsOfQuoteToken + .subtract(syntheticGasCostInTermsOfQuoteToken) + .lessThan( + gasCostInTermsOfQuoteToken.multiply(new Percent(30, 100)) + .asFraction + ))) ) { log.info( { diff --git a/src/util/tenderlySimulationErrorBreakDown.ts b/src/util/tenderlySimulationErrorBreakDown.ts new file mode 100644 index 000000000..17ce323b2 --- /dev/null +++ b/src/util/tenderlySimulationErrorBreakDown.ts @@ -0,0 +1,21 @@ +import { SimulationStatus } from '../providers'; + +export function breakDownTenderlySimulationError( + data?: string +): SimulationStatus { + if (data) { + switch (data) { + case '0x739dbe52': // V3TooMuchRequested + case '0x39d35496': // V3TooLittleReceived + case '0x849eaf98': // V2TooLittleReceived + case '0x8ab0bc16': // V2TooMuchRequested + case '0x08c379a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000025556e697377617056323a20494e53554646494349454e545f4f55545055545f414d4f554e54000000000000000000000000000000000000000000000000000000': // INSUFFICIENT_OUTPUT_AMOUNT + case '0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000034949410000000000000000000000000000000000000000000000000000000000': // IIA + return SimulationStatus.SlippageTooLow; + default: // we don't know why onchain execution reverted, just return generic failed. + return SimulationStatus.Failed; + } + } + + return SimulationStatus.Failed; +} diff --git a/test/unit/util/tenderlySimulationErrorBreakDown.test.ts b/test/unit/util/tenderlySimulationErrorBreakDown.test.ts new file mode 100644 index 000000000..e1a5ac326 --- /dev/null +++ b/test/unit/util/tenderlySimulationErrorBreakDown.test.ts @@ -0,0 +1,46 @@ +import { + breakDownTenderlySimulationError +} from '../../../src/util/tenderlySimulationErrorBreakDown'; +import { SimulationStatus } from '../../../build/main'; + +describe('tenderly simulation error break down', () => { + it('V3TooMuchRequested', async () => { + const simulationStatus = breakDownTenderlySimulationError('0x739dbe52') + expect(simulationStatus).toEqual(SimulationStatus.SlippageTooLow) + }) + + it('V3TooLittleReceived', async () => { + const simulationStatus = breakDownTenderlySimulationError('0x39d35496') + expect(simulationStatus).toEqual(SimulationStatus.SlippageTooLow) + }) + + it('V2TooLittleReceived', async () => { + const simulationStatus = breakDownTenderlySimulationError('0x849eaf98') + expect(simulationStatus).toEqual(SimulationStatus.SlippageTooLow) + }) + + it('V2TooMuchRequested', async () => { + const simulationStatus = breakDownTenderlySimulationError('0x8ab0bc16') + expect(simulationStatus).toEqual(SimulationStatus.SlippageTooLow) + }) + + it('INSUFFICIENT_OUTPUT_AMOUNT', async () => { + const simulationStatus = breakDownTenderlySimulationError('0x08c379a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000025556e697377617056323a20494e53554646494349454e545f4f55545055545f414d4f554e54000000000000000000000000000000000000000000000000000000'); + expect(simulationStatus).toEqual(SimulationStatus.SlippageTooLow) + }) + + it('IIA', async () => { + const simulationStatus = breakDownTenderlySimulationError('0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000034949410000000000000000000000000000000000000000000000000000000000'); + expect(simulationStatus).toEqual(SimulationStatus.SlippageTooLow) + }) + + it('InsufficientToken', () => { + const simulationStatus = breakDownTenderlySimulationError('0x675cae38'); + expect(simulationStatus).toEqual(SimulationStatus.Failed); + }); + + it('unknown data', () => { + const simulationStatus = breakDownTenderlySimulationError(undefined); + expect(simulationStatus).toEqual(SimulationStatus.Failed); + }); +});