From 842988fa2885e0462d1fcb662b00922e4298e259 Mon Sep 17 00:00:00 2001 From: nicholaspai <9457025+nicholaspai@users.noreply.github.com> Date: Wed, 8 Jan 2025 10:38:38 -0500 Subject: [PATCH 1/4] improve(API): Remove GAS_MARKUP deprecated env var (#1358) Replaced by BASE_FEE_MARKUP and PRIORITY_FEE_MARKUP --- api/_utils.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/api/_utils.ts b/api/_utils.ts index 69851b2de..4b94d2296 100644 --- a/api/_utils.ts +++ b/api/_utils.ts @@ -85,7 +85,6 @@ const { REACT_APP_HUBPOOL_CHAINID, REACT_APP_PUBLIC_INFURA_ID, REACT_APP_COINGECKO_PRO_API_KEY, - GAS_MARKUP, // To be deprecated and replaced by BASE_FEE_MARKUP and PRIORITY_FEE_MARKUP BASE_FEE_MARKUP, PRIORITY_FEE_MARKUP, VERCEL_ENV, @@ -94,7 +93,7 @@ const { export const baseFeeMarkup: { [chainId: string]: number; -} = JSON.parse(BASE_FEE_MARKUP || GAS_MARKUP || "{}"); +} = JSON.parse(BASE_FEE_MARKUP || "{}"); export const priorityFeeMarkup: { [chainId: string]: number; } = JSON.parse(PRIORITY_FEE_MARKUP || "{}"); From d2f677b0f9d81689377283fd68b6305d8fc9a488 Mon Sep 17 00:00:00 2001 From: Gerhard Steenkamp <51655063+gsteenkamp89@users.noreply.github.com> Date: Thu, 9 Jan 2025 11:48:43 +0200 Subject: [PATCH 2/4] support per-chain fillDeadline env var (#1363) --- src/utils/bridge.ts | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/utils/bridge.ts b/src/utils/bridge.ts index c2b5acd7b..b196f9788 100644 --- a/src/utils/bridge.ts +++ b/src/utils/bridge.ts @@ -236,7 +236,7 @@ export async function sendDepositV3Tx( const outputAmount = inputAmount.sub( inputAmount.mul(relayerFeePct).div(fixedPointAdjustment) ); - fillDeadline ??= await getFillDeadline(spokePool); + fillDeadline ??= await getFillDeadline(spokePool, destinationChainId); const useExclusiveRelayer = exclusiveRelayer !== ethers.constants.AddressZero && @@ -350,7 +350,7 @@ export async function sendSwapAndBridgeTx( const outputAmount = inputAmount.sub( inputAmount.mul(relayerFeePct).div(fixedPointAdjustment) ); - fillDeadline ??= await getFillDeadline(spokePool); + fillDeadline ??= await getFillDeadline(spokePool, destinationChainId); const tx = await swapAndBridge.populateTransaction.swapAndBridge( swapQuote.routerCalldata, @@ -424,11 +424,21 @@ export async function getSpokePoolAndVerifier({ }; } -async function getFillDeadline(spokePool: SpokePool): Promise { - const fillDeadlineBuffer = Number( - process.env.FILL_DEADLINE_BUFFER_SECONDS ?? - DEFAULT_FILL_DEADLINE_BUFFER_SECONDS - ); +function getFillDeadlineBuffer(chainId: number) { + const bufferFromEnv = ( + JSON.parse(process.env.FILL_DEADLINE_BUFFER_SECONDS || "{}") as Record< + string, + string + > + )?.[chainId.toString()]; + return Number(bufferFromEnv ?? DEFAULT_FILL_DEADLINE_BUFFER_SECONDS); +} + +async function getFillDeadline( + spokePool: SpokePool, + chainId: number +): Promise { + const fillDeadlineBuffer = getFillDeadlineBuffer(chainId); const currentTime = await spokePool.callStatic.getCurrentTime(); return Number(currentTime) + fillDeadlineBuffer; } From da72cca711a888ad0f849315ea0e13f00d966add Mon Sep 17 00:00:00 2001 From: Dong-Ha Kim Date: Thu, 9 Jan 2025 14:08:24 +0100 Subject: [PATCH 3/4] fix: serve fill deadline from api and use in UI (#1364) * fix: move fillDeadline computation to API * fix: use fillDeadline from API in UI --- api/_constants.ts | 2 ++ api/_fill-deadline.ts | 19 +++++++++++++ api/suggested-fees.ts | 4 +++ src/utils/bridge.ts | 27 +++---------------- src/utils/constants.ts | 2 -- .../mocked/suggested-fees.mocked.ts | 1 + .../prod/suggested-fees.prod.ts | 1 + src/utils/serverless-api/types.ts | 1 + src/views/Bridge/hooks/useBridgeAction.ts | 2 ++ 9 files changed, 34 insertions(+), 25 deletions(-) create mode 100644 api/_fill-deadline.ts diff --git a/api/_constants.ts b/api/_constants.ts index ee5cc58a5..8f1b20d4d 100644 --- a/api/_constants.ts +++ b/api/_constants.ts @@ -202,3 +202,5 @@ export const DOMAIN_CALLDATA_DELIMITER = "0x1dc0de"; export const DEFAULT_LITE_CHAIN_USD_MAX_BALANCE = "250000"; export const DEFAULT_LITE_CHAIN_USD_MAX_DEPOSIT = "25000"; + +export const DEFAULT_FILL_DEADLINE_BUFFER_SECONDS = 2.5 * 60 * 60; // 2.5 hours diff --git a/api/_fill-deadline.ts b/api/_fill-deadline.ts new file mode 100644 index 000000000..2016e28b4 --- /dev/null +++ b/api/_fill-deadline.ts @@ -0,0 +1,19 @@ +import { DEFAULT_FILL_DEADLINE_BUFFER_SECONDS } from "./_constants"; +import { getSpokePool } from "./_utils"; + +function getFillDeadlineBuffer(chainId: number) { + const bufferFromEnv = ( + JSON.parse(process.env.FILL_DEADLINE_BUFFER_SECONDS || "{}") as Record< + string, + string + > + )?.[chainId.toString()]; + return Number(bufferFromEnv ?? DEFAULT_FILL_DEADLINE_BUFFER_SECONDS); +} + +export async function getFillDeadline(chainId: number): Promise { + const fillDeadlineBuffer = getFillDeadlineBuffer(chainId); + const spokePool = getSpokePool(chainId); + const currentTime = await spokePool.callStatic.getCurrentTime(); + return Number(currentTime) + fillDeadlineBuffer; +} diff --git a/api/suggested-fees.ts b/api/suggested-fees.ts index a1ad89a28..35a9ebdf4 100644 --- a/api/suggested-fees.ts +++ b/api/suggested-fees.ts @@ -39,6 +39,7 @@ import { AmountTooHighError, AmountTooLowError, } from "./_errors"; +import { getFillDeadline } from "./_fill-deadline"; const { BigNumber } = ethers; @@ -187,6 +188,7 @@ const handler = async ( [currentUt, nextUt, _quoteTimestamp, rawL1TokenConfig], tokenPriceUsd, limits, + fillDeadline, ] = await Promise.all([ callViaMulticall3(provider, multiCalls, { blockTag: quoteBlockNumber }), getCachedTokenPrice(l1Token.address, "usd"), @@ -203,6 +205,7 @@ const handler = async ( depositWithMessage ? relayer : undefined, depositWithMessage ? message : undefined ), + getFillDeadline(destinationChainId), ]); const { maxDeposit, maxDepositInstant, minDeposit, relayerFeeDetails } = limits; @@ -341,6 +344,7 @@ const handler = async ( maxDepositShortDelay: limits.maxDepositShortDelay, recommendedDepositInstant: limits.recommendedDepositInstant, }, + fillDeadline: fillDeadline.toString(), }; logger.debug({ diff --git a/src/utils/bridge.ts b/src/utils/bridge.ts index b196f9788..d60e15127 100644 --- a/src/utils/bridge.ts +++ b/src/utils/bridge.ts @@ -1,7 +1,6 @@ import { ethers, BigNumber } from "ethers"; import { ChainId, - DEFAULT_FILL_DEADLINE_BUFFER_SECONDS, fixedPointAdjustment, referrerDelimiterHex, } from "./constants"; @@ -32,6 +31,7 @@ export type BridgeFees = { estimatedFillTimeSec: number; exclusiveRelayer: string; exclusivityDeadline: number; + fillDeadline: number; }; type GetBridgeFeesArgs = { @@ -77,6 +77,7 @@ export async function getBridgeFees({ estimatedFillTimeSec, exclusiveRelayer, exclusivityDeadline, + fillDeadline, } = await getApiEndpoint().suggestedFees( amount, getConfig().getTokenInfoBySymbol(fromChainId, inputTokenSymbol).address, @@ -103,6 +104,7 @@ export async function getBridgeFees({ estimatedFillTimeSec, exclusiveRelayer, exclusivityDeadline, + fillDeadline, }; } @@ -150,7 +152,7 @@ export type AcrossDepositArgs = { export type AcrossDepositV3Args = AcrossDepositArgs & { inputTokenAddress: string; outputTokenAddress: string; - fillDeadline?: number; + fillDeadline: number; exclusivityDeadline?: number; exclusiveRelayer?: string; }; @@ -236,7 +238,6 @@ export async function sendDepositV3Tx( const outputAmount = inputAmount.sub( inputAmount.mul(relayerFeePct).div(fixedPointAdjustment) ); - fillDeadline ??= await getFillDeadline(spokePool, destinationChainId); const useExclusiveRelayer = exclusiveRelayer !== ethers.constants.AddressZero && @@ -350,7 +351,6 @@ export async function sendSwapAndBridgeTx( const outputAmount = inputAmount.sub( inputAmount.mul(relayerFeePct).div(fixedPointAdjustment) ); - fillDeadline ??= await getFillDeadline(spokePool, destinationChainId); const tx = await swapAndBridge.populateTransaction.swapAndBridge( swapQuote.routerCalldata, @@ -424,25 +424,6 @@ export async function getSpokePoolAndVerifier({ }; } -function getFillDeadlineBuffer(chainId: number) { - const bufferFromEnv = ( - JSON.parse(process.env.FILL_DEADLINE_BUFFER_SECONDS || "{}") as Record< - string, - string - > - )?.[chainId.toString()]; - return Number(bufferFromEnv ?? DEFAULT_FILL_DEADLINE_BUFFER_SECONDS); -} - -async function getFillDeadline( - spokePool: SpokePool, - chainId: number -): Promise { - const fillDeadlineBuffer = getFillDeadlineBuffer(chainId); - const currentTime = await spokePool.callStatic.getCurrentTime(); - return Number(currentTime) + fillDeadlineBuffer; -} - async function _tagRefAndSignTx( tx: ethers.PopulatedTransaction, referrer: string, diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 40ec3d9e2..46b82c189 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -550,5 +550,3 @@ export const defaultSwapSlippage = Number( export const indexerApiBaseUrl = process.env.REACT_APP_INDEXER_BASE_URL || undefined; - -export const DEFAULT_FILL_DEADLINE_BUFFER_SECONDS = 2.5 * 60 * 60; // 2.5 hours diff --git a/src/utils/serverless-api/mocked/suggested-fees.mocked.ts b/src/utils/serverless-api/mocked/suggested-fees.mocked.ts index 4477ebf10..b02d76bfe 100644 --- a/src/utils/serverless-api/mocked/suggested-fees.mocked.ts +++ b/src/utils/serverless-api/mocked/suggested-fees.mocked.ts @@ -51,5 +51,6 @@ export async function suggestedFeesMockedApiCall( }, exclusiveRelayer: ethers.constants.AddressZero, exclusivityDeadline: 0, + fillDeadline: Date.now(), }; } diff --git a/src/utils/serverless-api/prod/suggested-fees.prod.ts b/src/utils/serverless-api/prod/suggested-fees.prod.ts index 7481cee24..3e5ea2bf5 100644 --- a/src/utils/serverless-api/prod/suggested-fees.prod.ts +++ b/src/utils/serverless-api/prod/suggested-fees.prod.ts @@ -89,5 +89,6 @@ export async function suggestedFeesApiCall( estimatedFillTimeSec, exclusiveRelayer, exclusivityDeadline, + fillDeadline: result.fillDeadline, }; } diff --git a/src/utils/serverless-api/types.ts b/src/utils/serverless-api/types.ts index 488b9afab..c85d4b2d5 100644 --- a/src/utils/serverless-api/types.ts +++ b/src/utils/serverless-api/types.ts @@ -58,6 +58,7 @@ export type SuggestedApiFeeReturnType = { estimatedFillTimeSec: number; exclusiveRelayer: string; exclusivityDeadline: number; + fillDeadline: number; }; export type SuggestedApiFeeType = ( diff --git a/src/views/Bridge/hooks/useBridgeAction.ts b/src/views/Bridge/hooks/useBridgeAction.ts index 868bd4bfb..85c1a110f 100644 --- a/src/views/Bridge/hooks/useBridgeAction.ts +++ b/src/views/Bridge/hooks/useBridgeAction.ts @@ -167,6 +167,7 @@ export function useBridgeAction( // Disabling until we update the contract. exclusiveRelayer: constants.AddressZero, exclusivityDeadline: 0, + fillDeadline: frozenFeeQuote.fillDeadline, }, networkMismatchHandler ); @@ -191,6 +192,7 @@ export function useBridgeAction( ...frozenDepositArgs, inputTokenAddress: frozenRoute.fromTokenAddress, outputTokenAddress: frozenRoute.toTokenAddress, + fillDeadline: frozenFeeQuote.fillDeadline, }, spokePool, networkMismatchHandler From 948b6f2cb8395ef773b61fe4f6dbbb64bfcf3198 Mon Sep 17 00:00:00 2001 From: nicholaspai <9457025+nicholaspai@users.noreply.github.com> Date: Thu, 9 Jan 2025 10:52:09 -0500 Subject: [PATCH 4/4] improve(API): Use newer SDK version for updated gas price oracle logic (#1361) * improve(API): Use newer SDK version for updated gas price oracle logic - Applies `priorityFeeMultiplier` to Linea's priority fee rather than the `baseFeeMultiplier` - Allows caller to set a floor on any EIP1559's `priorityFee` with a default of 0.5 gwei for chainId=1 hardcoded * 3.4.7 --- package.json | 2 +- yarn.lock | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 67a167b89..6ec93dc78 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "@across-protocol/constants": "^3.1.24", "@across-protocol/contracts": "^3.0.19", "@across-protocol/contracts-v3.0.6": "npm:@across-protocol/contracts@3.0.6", - "@across-protocol/sdk": "^3.4.5", + "@across-protocol/sdk": "^3.4.7", "@amplitude/analytics-browser": "^2.3.5", "@balancer-labs/sdk": "1.1.6-beta.16", "@emotion/react": "^11.13.0", diff --git a/yarn.lock b/yarn.lock index 1b7066726..9b06bf5bf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21,11 +21,6 @@ resolved "https://registry.yarnpkg.com/@across-protocol/constants/-/constants-3.1.25.tgz#60d6d9814582ff91faf2b6d9f51d6dccb447b4ce" integrity sha512-GpZoYn7hETYL2BPMM2GqXAer6+l/xuhder+pvpb00HJcb/sqCjF7vaaeKxjKJ3jKtyeulYmdu0NDkeNm5KbNWA== -"@across-protocol/constants@^3.1.25": - version "3.1.25" - resolved "https://registry.yarnpkg.com/@across-protocol/constants/-/constants-3.1.25.tgz#60d6d9814582ff91faf2b6d9f51d6dccb447b4ce" - integrity sha512-GpZoYn7hETYL2BPMM2GqXAer6+l/xuhder+pvpb00HJcb/sqCjF7vaaeKxjKJ3jKtyeulYmdu0NDkeNm5KbNWA== - "@across-protocol/constants@^3.1.9": version "3.1.13" resolved "https://registry.yarnpkg.com/@across-protocol/constants/-/constants-3.1.13.tgz#b4caf494e9d9fe50290cca91b7883ea408fdb90a" @@ -88,10 +83,10 @@ yargs "^17.7.2" zksync-web3 "^0.14.3" -"@across-protocol/sdk@^3.4.5": - version "3.4.5" - resolved "https://registry.yarnpkg.com/@across-protocol/sdk/-/sdk-3.4.5.tgz#343f53be92e92afd2fd4dbea16f180533093ea26" - integrity sha512-o1DovRfSriL0GTa304rd2KcBDwWYbK2SHT8mElyCLg6beX5RnJKT0YiMUMuCMfZ7MZJscdGzV023e5BhbyeP5A== +"@across-protocol/sdk@^3.4.7": + version "3.4.7" + resolved "https://registry.yarnpkg.com/@across-protocol/sdk/-/sdk-3.4.7.tgz#6ddf9698f918d7b7e0216327d60b54b37fe14f22" + integrity sha512-GeyzDG8EzlN8oddmjXASqND+usZPkWDLpzbdWfAfBfHT3pjIMatntZqZghfCfjy+ICf+rlYrAb8I24H4jlct8Q== dependencies: "@across-protocol/across-token" "^1.0.0" "@across-protocol/constants" "^3.1.25"