Skip to content

Commit

Permalink
Merge branch 'feat/sdk-syn-intents' into staging/syn-intents-api-sdk
Browse files Browse the repository at this point in the history
  • Loading branch information
ChiTimesChi committed Dec 20, 2024
2 parents c928462 + 0819f24 commit 60393c7
Show file tree
Hide file tree
Showing 17 changed files with 154 additions and 584 deletions.
2 changes: 1 addition & 1 deletion packages/sdk-router/src/abi/SynapseIntentPreviewer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"inputs": [
{ "name": "swapQuoter", "type": "address", "internalType": "address" },
{ "name": "forwardTo", "type": "address", "internalType": "address" },
{ "name": "strictOut", "type": "bool", "internalType": "bool" },
{ "name": "slippageWei", "type": "uint256", "internalType": "uint256" },
{ "name": "tokenIn", "type": "address", "internalType": "address" },
{ "name": "tokenOut", "type": "address", "internalType": "address" },
{ "name": "amountIn", "type": "uint256", "internalType": "uint256" }
Expand Down
94 changes: 0 additions & 94 deletions packages/sdk-router/src/abi/TokenZapV1.json

This file was deleted.

4 changes: 2 additions & 2 deletions packages/sdk-router/src/constants/addresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export const FAST_BRIDGE_V2_ADDRESS_MAP: AddressMap = generateAddressMap(
* TokenZapV1 contract address for all chains except ones from TOKEN_ZAP_V1_EXCEPTION_MAP.
* TODO: this is a staging TokenZapV1 deployment, update to the production deployment when ready.
*/
const TOKEN_ZAP_V1_ADDRESS = '0x6327797F149a75D506aFda46D5fCE6E74fC409D5'
const TOKEN_ZAP_V1_ADDRESS = '0x289db76b9E19487190D356ecB64324A5c716fFe1'
const TOKEN_ZAP_V1_EXCEPTION_MAP: AddressMap = {}
export const TOKEN_ZAP_V1_ADDRESS_MAP: AddressMap = generateAddressMap(
RFQ_SUPPORTED_CHAIN_IDS,
Expand All @@ -108,7 +108,7 @@ export const SYNAPSE_INTENT_ROUTER_ADDRESS_MAP: AddressMap = generateAddressMap(
* TODO: this is a staging SynapseIntentPreviewer deployment, update to the production deployment when ready.
*/
const SYNAPSE_INTENT_PREVIEWER_ADDRESS =
'0x89ed77DcEaFBc4F92DAB2e865e11E7885F8daAf9'
'0xfC2352150681A96E591F3a1ea511970FEF005A55'
const SYNAPSE_INTENT_PREVIEWER_EXCEPTION_MAP: AddressMap = {}
export const SYNAPSE_INTENT_PREVIEWER_ADDRESS_MAP: AddressMap =
generateAddressMap(
Expand Down
3 changes: 2 additions & 1 deletion packages/sdk-router/src/rfq/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ export const fetchWithTimeout = async (
init?: RequestInit
): Promise<Response> => {
const controller = new AbortController()
const timeoutId = setTimeout(() => controller.abort(), timeout)
const reason = `Timeout of ${timeout}ms exceeded for ${url}`
const timeoutId = setTimeout(() => (controller.abort as any)(reason), timeout)
return fetch(url, { signal: controller.signal, ...init }).finally(() =>
clearTimeout(timeoutId)
)
Expand Down
128 changes: 9 additions & 119 deletions packages/sdk-router/src/rfq/engine/defaultEngine.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Interface } from '@ethersproject/abi'
import { hexlify } from '@ethersproject/bytes'
import { AddressZero, Zero } from '@ethersproject/constants'
import { BigNumber, Contract } from 'ethers'
import invariant from 'tiny-invariant'
Expand All @@ -15,7 +14,6 @@ import { ChainProvider } from '../../router'
import { SynapseIntentPreviewer as PreviewerContract } from '../../typechain/SynapseIntentPreviewer'
import { IDefaultActionsInterface } from '../../typechain/IDefaultActions'
import { isSameAddress } from '../../utils/addressUtils'
import { decodeZapData, encodeZapData, ZapDataV1 } from '../zapData'
import {
SwapEngine,
SwapEngineRoute,
Expand All @@ -24,8 +22,10 @@ import {
RecipientEntity,
EngineID,
Slippage,
toWei,
applySlippage,
isCorrectSlippage,
} from './swapEngine'
import { applySlippage } from '../../module'

export class DefaultEngine implements SwapEngine {
static defaultActions = new Interface(
Expand Down Expand Up @@ -77,14 +77,13 @@ export class DefaultEngine implements SwapEngine {
finalRecipient: Recipient,
slippage: Slippage
): Promise<SwapEngineRoute> {
// TODO: Previewer should take slippage into account
const strictOut = slippage.numerator !== slippage.denominator
const { previewer, swapQuoter } = this.contracts[chainId]
if (
!previewer ||
!swapQuoter ||
isSameAddress(tokenIn, tokenOut) ||
BigNumber.from(amountIn).eq(Zero)
BigNumber.from(amountIn).eq(Zero) ||
!isCorrectSlippage(slippage)
) {
return EmptyRoute
}
Expand All @@ -93,138 +92,29 @@ export class DefaultEngine implements SwapEngine {
const { amountOut, steps: stepsOutput } = await previewer.previewIntent(
swapQuoter,
forwardTo,
strictOut,
toWei(slippage),
tokenIn,
tokenOut,
amountIn
)
const minAmountOut = applySlippage(amountOut, slippage)
// Remove extra fields before the encoding
const route = {
return {
engineID: this.id,
expectedAmountOut: amountOut,
minAmountOut: amountOut,
minAmountOut,
steps: stepsOutput.map(({ token, amount, msgValue, zapData }) => ({
token,
amount,
msgValue,
zapData,
})),
}
return strictOut ? this.applySlippage(chainId, route, slippage) : route
}

public applySlippage(
_chainId: number,
route: SwapEngineRoute,
slippage: Slippage
): SwapEngineRoute {
const minAmountOut = applySlippage(
route.expectedAmountOut,
slippage.numerator,
slippage.denominator
)
if (minAmountOut.eq(route.minAmountOut)) {
// Nothing to do
return route
}
const decodedZapData = this.getLastStepZapData(route)
if (!decodedZapData.payload) {
throw new Error(
'DefaultEngine.applySlippage: no payload in the last step zapData'
)
}
let newPayload

if (this.isSelectorMatching(decodedZapData.payload, 'addLiquidity')) {
const params = DefaultEngine.defaultActions.decodeFunctionData(
'addLiquidity',
decodedZapData.payload
) as [BigNumber[], BigNumber, BigNumber]
// addLiquidity(amounts, minToMint, deadline)
newPayload = DefaultEngine.defaultActions.encodeFunctionData(
'addLiquidity',
[params[0], minAmountOut, params[2]]
)
}

if (
this.isSelectorMatching(decodedZapData.payload, 'removeLiquidityOneToken')
) {
const params = DefaultEngine.defaultActions.decodeFunctionData(
'removeLiquidityOneToken',
decodedZapData.payload
) as [BigNumber, BigNumber, BigNumber, BigNumber]
// removeLiquidityOneToken(tokenAmount, tokenIndex, minAmount, deadline)
newPayload = DefaultEngine.defaultActions.encodeFunctionData(
'removeLiquidityOneToken',
[params[0], params[1], minAmountOut, params[3]]
)
}

if (this.isSelectorMatching(decodedZapData.payload, 'swap')) {
const params = DefaultEngine.defaultActions.decodeFunctionData(
'swap',
decodedZapData.payload
) as [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber]
// swap(tokenIndexFrom, tokenIndexTo, dx, minDy, deadline)
newPayload = DefaultEngine.defaultActions.encodeFunctionData('swap', [
params[0],
params[1],
params[2],
minAmountOut,
params[4],
])
}

if (
this.isSelectorMatching(decodedZapData.payload, 'deposit') ||
this.isSelectorMatching(decodedZapData.payload, 'withdraw')
) {
newPayload = decodedZapData.payload
}

if (!newPayload) {
throw new Error(
'DefaultEngine.applySlippage: no matching payload for the last step'
)
}
// Last step exists after `getLastStepZapData`
route.minAmountOut = BigNumber.from(minAmountOut)
route.steps[route.steps.length - 1].zapData = encodeZapData({
...decodedZapData,
payload: newPayload,
})
return route
}

private getLastStepZapData(route: SwapEngineRoute): Partial<ZapDataV1> {
const stepsCount = route.steps.length
if (stepsCount === 0) {
throw new Error('getLastStepZapData: no steps')
}
const lastStepZapData = hexlify(route.steps[stepsCount - 1].zapData)
return decodeZapData(lastStepZapData)
}

private getForwardTo(recipient: Recipient): string {
return recipient.entity === RecipientEntity.Self
? AddressZero
: recipient.address
}

private isSelectorMatching(
payload: string,
functionName:
| 'addLiquidity'
| 'deposit'
| 'removeLiquidityOneToken'
| 'swap'
| 'withdraw'
): boolean {
return payload.startsWith(
DefaultEngine.defaultActions.getSighash(
DefaultEngine.defaultActions.getFunction(functionName)
)
)
}
}
12 changes: 0 additions & 12 deletions packages/sdk-router/src/rfq/engine/engineSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,18 +156,6 @@ export class EngineSet {
return route.steps.length > 1 ? EmptyRoute : route
}

public applySlippage(
chainId: number,
route: SwapEngineRoute,
slippage: Slippage
): SwapEngineRoute {
return this._getEngine(route.engineID).applySlippage(
chainId,
route,
slippage
)
}

public getTokenZap(chainId: number): string {
const tokenZap = this.tokenZaps[chainId]
if (!tokenZap) {
Expand Down
8 changes: 0 additions & 8 deletions packages/sdk-router/src/rfq/engine/noOpEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,4 @@ export class NoOpEngine implements SwapEngine {
steps: [],
}
}

public applySlippage(
_chainId: number,
route: SwapEngineRoute
): SwapEngineRoute {
// Slippage settings are ignored for NoOpEngine
return route
}
}
Loading

0 comments on commit 60393c7

Please sign in to comment.