Skip to content

Commit d29f97b

Browse files
mergify[bot]Kefancaocoderabbitai[bot]
authored
[ENG-900] [Turnkey] Add safe slippageTolerance. (backport #3118) (#3273)
Co-authored-by: Kefan Cao <76069770+Kefancao@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
1 parent 915097f commit d29f97b

File tree

3 files changed

+42
-10
lines changed

3 files changed

+42
-10
lines changed

indexer/services/comlink/__tests__/helpers/skip-helper.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
nobleToHex,
44
encodeToHexAndPad,
55
nobleToSolana,
6+
getSlippageTolerancePercent,
67
} from '../../src/helpers/skip-helper';
78
import { getETHPrice } from '../../src/helpers/alchemy-helpers';
89
import { ethDenomByChainId, ETH_WEI_QUANTUM, ETH_USDC_QUANTUM } from '../../src/lib/smart-contract-constants';
@@ -18,6 +19,8 @@ jest.mock('../../src/config', () => ({
1819
TURNKEY_API_BASE_URL: 'https://api.turnkey.com',
1920
TURNKEY_API_SENDER_PUBLIC_KEY: 'test-public-key',
2021
TURNKEY_API_SENDER_PRIVATE_KEY: 'test-private-key',
22+
SKIP_SLIPPAGE_TOLERANCE_USDC: 100,
23+
SKIP_SLIPPAGE_TOLERANCE_PERCENTAGE: '0.1',
2124
}));
2225

2326
jest.mock('@dydxprotocol-indexer/base', () => ({
@@ -432,4 +435,27 @@ describe('skip-helper', () => {
432435
});
433436
});
434437

438+
describe('getSlippageTolerancePercent', () => {
439+
it('should return the percentage-based tolerance when it is smaller than USDC-based tolerance', () => {
440+
// When estimatedAmountOut is large, USDC-based tolerance becomes very small
441+
const estimatedAmountOut = '1000000000'; // 1000 USDC (assuming 6 decimals)
442+
// USDC-based: 100 * 100000000 / 1000000000 = 0.1 (10%)
443+
const result = getSlippageTolerancePercent(estimatedAmountOut);
444+
445+
// Should return the smaller value: 0.1% default.
446+
expect(result).toBe('0.1');
447+
});
448+
449+
it('should return the USDC-based tolerance when it is smaller than percentage-based tolerance', () => {
450+
// When estimatedAmountOut is small, USDC-based tolerance becomes large
451+
const estimatedAmountOut = '1000000000000'; // 1,000,000 USDC (1 million with 6 decimals)
452+
const result = getSlippageTolerancePercent(estimatedAmountOut);
453+
454+
// USDC-based: 10_000_000_000 / 1_000_000_000_000 = 0.01 (1%)
455+
// Percentage-based: 0.1 (10%)
456+
// Should return the smaller value: 0.01 (1%)
457+
expect(result).toBe('0.01');
458+
});
459+
});
460+
435461
});

indexer/services/comlink/src/config.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ export const configSchema = {
123123
TURNKEY_ORGANIZATION_ID: parseString({ default: '' }),
124124
SOLANA_SPONSOR_PUBLIC_KEY: parseString({ default: '' }),
125125
SKIP_SLIPPAGE_TOLERANCE_PERCENTAGE: parseString({ default: '0' }),
126+
// this is the largest allowed slippage amount in USDC.
127+
SKIP_SLIPPAGE_TOLERANCE_USDC: parseInteger({ default: 100 }),
126128
TURNKEY_EMAIL_SENDER_ADDRESS: parseString({ default: 'notifications@mail.dydx.trade' }),
127129
TURNKEY_EMAIL_SENDER_NAME: parseString({ default: 'dYdX Notifications' }),
128130
// Alchemy auth token for the skip bridge.
@@ -139,7 +141,7 @@ export const configSchema = {
139141
// if policy approvals are enabled.
140142
APPROVAL_ENABLED: parseBoolean({ default: true }),
141143
// largest amount we will tolerate to swap in usdc.
142-
MAXIMUM_BRIDGE_AMOUNT_USDC: parseInteger({ default: 99_900 }),
144+
MAXIMUM_BRIDGE_AMOUNT_USDC: parseInteger({ default: 999_000 }),
143145

144146
// Apple Sign-In configuration
145147
APPLE_TEAM_ID: parseString({ default: '' }),

indexer/services/comlink/src/helpers/skip-helper.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ export async function buildUserAddresses(
4949
const nobleForwardingModule = 'https://api.noble.xyz/noble/forwarding/v1/address/channel';
5050
const skipMessagesTimeoutSeconds = '60';
5151
const dydxNobleChannel = 33;
52-
const slippageTolerancePercent = config.SKIP_SLIPPAGE_TOLERANCE_PERCENTAGE;
5352
// Grabs the raw skip route data to carry out the bridge on our own.
5453
export async function getSkipCallData(
5554
sourceAddress: string,
@@ -63,7 +62,6 @@ export async function getSkipCallData(
6362
if (amount.startsWith('0x')) {
6463
amountToUse = parseInt(amount, 16).toString();
6564
}
66-
6765
const routeResult = await route({
6866
amountIn: amountToUse, // Desired amount in smallest denomination (e.g., uatom)
6967
sourceAssetDenom,
@@ -88,13 +86,6 @@ export async function getSkipCallData(
8886
throw new Error('Failed to find a route');
8987
}
9088

91-
logger.info({
92-
at: 'skip-helper#getSkipCallData',
93-
message: 'Route result obtained',
94-
routeResult,
95-
dydxAddress,
96-
});
97-
9889
const userAddresses = await buildUserAddresses(
9990
routeResult.requiredChainAddresses,
10091
sourceAddress,
@@ -121,6 +112,9 @@ export async function getSkipCallData(
121112
throw new Error('executeRoute error: invalid address list');
122113
}
123114

115+
// acceptable slippage is smallest of SKIP_SLIPPAGE_TOLERANCE_USDC (Default $100) divided
116+
// by the estimatedAmountOut or the SKIP_SLIPPAGE_TOLERANCE_PERCENTAGE.
117+
const slippageTolerancePercent = getSlippageTolerancePercent(routeResult.estimatedAmountOut);
124118
const response = await messages({
125119
timeoutSeconds: skipMessagesTimeoutSeconds,
126120
amountIn: routeResult?.amountIn,
@@ -394,3 +388,13 @@ export async function limitAmount(
394388
const maxDepositInUsdc = config.MAXIMUM_BRIDGE_AMOUNT_USDC;
395389
return min([amountToUse, BigInt(maxDepositInUsdc * ETH_USDC_QUANTUM)])!.toString();
396390
}
391+
392+
// getSlippageTolerancePercent returns the acceptable slippage is smallest of
393+
// SKIP_SLIPPAGE_TOLERANCE_USDC (Default $100) divided by the estimatedAmountOut
394+
// or the SKIP_SLIPPAGE_TOLERANCE_PERCENTAGE.
395+
export function getSlippageTolerancePercent(estAmountOut: string): string {
396+
return min([
397+
(100 * (config.SKIP_SLIPPAGE_TOLERANCE_USDC * ETH_USDC_QUANTUM)) / parseInt(estAmountOut, 10),
398+
parseFloat(config.SKIP_SLIPPAGE_TOLERANCE_PERCENTAGE),
399+
])!.toString();
400+
}

0 commit comments

Comments
 (0)