Skip to content

Commit 940a456

Browse files
cowdanshoom3301
andauthored
fix(bridge): increase gas for Gnosis bridge hook (#448)
* chore: increase gas for Gnosis bridge hook to 150k * chore: increase extra gas for hook to 200k and for proxy to 400k * chore: remove logs - bump version * chore: improve test coverage and bump version * Update package.json --------- Co-authored-by: Alexandr Kazachenko <[email protected]>
1 parent 06d07b2 commit 940a456

File tree

10 files changed

+114
-35
lines changed

10 files changed

+114
-35
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@cowprotocol/cow-sdk",
3-
"version": "6.3.1",
3+
"version": "6.3.2",
44
"license": "(MIT OR Apache-2.0)",
55
"files": [
66
"/dist"

src/bridging/PROVIDER_README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -381,14 +381,15 @@ import { getGasLimitEstimationForHook } from '../utils/getGasLimitEstimationForH
381381

382382
export class YourBridgeProvider implements BridgeProvider<YourBridgeQuoteResult> {
383383
async getGasLimitEstimationForHook(
384-
request: Omit<QuoteBridgeRequest, 'amount'> & { extraGas?: number },
384+
request: Omit<QuoteBridgeRequest, 'amount'> & { extraGas?: number; extraGasProxyCreation?: number },
385385
): Promise<number> {
386386
// Use utility function or implement custom gas estimation
387387
return getGasLimitEstimationForHook(
388-
this.cowShedSdk,
389-
request as QuoteBridgeRequest, // cast needed due to omit
390-
this.getRpcProvider(request.sellTokenChainId),
391-
request.extraGas, // to add extra gas to the hook.
388+
cowshed: this.cowShedSdk,
389+
request: request as QuoteBridgeRequest, // cast needed due to omit
390+
provider: this.getRpcProvider(request.sellTokenChainId),
391+
extraGas: request.extraGas, // to add extra gas to the hook
392+
extraGasProxyCreation: request.extraGasProxyCreation // to add extra gas to the hook and deploy proxy account
392393
)
393394
}
394395

src/bridging/const.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { RAW_FILES_PATH } from '../common/consts/path'
33
export const RAW_PROVIDERS_FILES_PATH = `${RAW_FILES_PATH}/src/bridging/providers`
44
// Based on https://dashboard.tenderly.co/shoom/project/simulator/a5e29dac-d0f2-407f-9e3d-d1b916da595b
55
export const DEFAULT_GAS_COST_FOR_HOOK_ESTIMATION = 240_000
6-
export const DEFAULT_EXTRA_GAS_FOR_HOOK_ESTIMATION = 100_000
6+
export const DEFAULT_EXTRA_GAS_FOR_HOOK_ESTIMATION = 200_000
77
// Based on https://dashboard.tenderly.co/shoom/project/tx/0x2971aee9aa7237d24b254da8ccd4345ff77410c8829c8e825e9a02cb2cece5e6/gas-usage
88
export const COW_SHED_PROXY_CREATION_GAS = 360_000
9+
export const DEFAULT_EXTRA_GAS_PROXY_CREATION = 400_000
910
export const HOOK_DAPP_BRIDGE_PROVIDER_PREFIX = 'cow-sdk://bridging/providers'

src/bridging/providers/across/AcrossBridgeProvider.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,11 @@ export class AcrossBridgeProvider implements BridgeProvider<AcrossQuoteResult> {
145145
}
146146

147147
async getGasLimitEstimationForHook(request: QuoteBridgeRequest): Promise<number> {
148-
return getGasLimitEstimationForHook(this.cowShedSdk, request, this.getRpcProvider(request.sellTokenChainId))
148+
return getGasLimitEstimationForHook({
149+
cowShedSdk: this.cowShedSdk,
150+
request,
151+
provider: this.getRpcProvider(request.sellTokenChainId),
152+
})
149153
}
150154

151155
async getSignedHook(

src/bridging/providers/bungee/BungeeApi.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ function isValidBungeeEventsResponse(response: unknown): response is BungeeEvent
508508
'fromChainId' in e &&
509509
'isCowswapTrade' in e &&
510510
'orderId' in e &&
511-
'recipient' in e &&
511+
// 'recipient' in e &&
512512
'sender' in e &&
513513
'srcTxStatus' in e &&
514514
'destTxStatus' in e

src/bridging/providers/bungee/BungeeBridgeProvider.test.ts

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ import { latest as latestAppData } from '@cowprotocol/app-data'
22
import { OrderKind } from '@cowprotocol/contracts'
33
import { JsonRpcProvider } from '@ethersproject/providers'
44
import { SupportedChainId, TargetChainId } from '../../../chains'
5-
import { DEFAULT_EXTRA_GAS_FOR_HOOK_ESTIMATION, DEFAULT_GAS_COST_FOR_HOOK_ESTIMATION } from '../../const'
5+
import {
6+
COW_SHED_PROXY_CREATION_GAS,
7+
DEFAULT_EXTRA_GAS_FOR_HOOK_ESTIMATION,
8+
DEFAULT_EXTRA_GAS_PROXY_CREATION,
9+
DEFAULT_GAS_COST_FOR_HOOK_ESTIMATION,
10+
} from '../../const'
611
import { BridgeStatus, QuoteBridgeRequest } from '../../types'
712
import { BungeeApi } from './BungeeApi'
813
import {
@@ -33,6 +38,8 @@ class BungeeBridgeProviderTest extends BungeeBridgeProvider {
3338
}
3439
}
3540

41+
const mockGetCode = jest.fn()
42+
3643
describe('BungeeBridgeProvider', () => {
3744
let provider: BungeeBridgeProviderTest
3845

@@ -41,7 +48,7 @@ describe('BungeeBridgeProvider', () => {
4148
apiOptions: {},
4249
getRpcProvider() {
4350
return {
44-
getCode: jest.fn().mockResolvedValue('0x1234567890'),
51+
getCode: mockGetCode,
4552
} as unknown as JsonRpcProvider
4653
},
4754
}
@@ -396,7 +403,9 @@ describe('BungeeBridgeProvider', () => {
396403
})
397404

398405
describe('getGasLimitEstimationForHook', () => {
399-
it('should return default gas limit estimation for non-Mainnet to Gnosis', async () => {
406+
it('should return default gas limit estimation for Mainnet to Polygon', async () => {
407+
mockGetCode.mockResolvedValue('0x1234567890')
408+
400409
const request: QuoteBridgeRequest = {
401410
kind: OrderKind.SELL,
402411
sellTokenAddress: '0x123',
@@ -417,7 +426,32 @@ describe('BungeeBridgeProvider', () => {
417426
expect(gasLimit).toEqual(DEFAULT_GAS_COST_FOR_HOOK_ESTIMATION)
418427
})
419428

429+
it('should return default gas limit estimation for Mainnet to Polygon and deploy proxy account', async () => {
430+
mockGetCode.mockResolvedValue(undefined)
431+
432+
const request: QuoteBridgeRequest = {
433+
kind: OrderKind.SELL,
434+
sellTokenAddress: '0x123',
435+
sellTokenChainId: SupportedChainId.MAINNET,
436+
buyTokenChainId: SupportedChainId.POLYGON,
437+
amount: 1000000000000000000n,
438+
receiver: '0x789',
439+
account: '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef', // need to find cowshed account address
440+
sellTokenDecimals: 18,
441+
buyTokenAddress: '0x456',
442+
buyTokenDecimals: 6,
443+
appCode: '0x123',
444+
signer: '0xa43ccc40ff785560dab6cb0f13b399d050073e8a54114621362f69444e1421ca',
445+
}
446+
447+
const gasLimit = await provider.getGasLimitEstimationForHook(request)
448+
449+
expect(gasLimit).toEqual(DEFAULT_GAS_COST_FOR_HOOK_ESTIMATION + COW_SHED_PROXY_CREATION_GAS)
450+
})
451+
420452
it('should return default gas limit estimation for Mainnet to Gnosis', async () => {
453+
mockGetCode.mockResolvedValue('0x1234567890')
454+
421455
const request: QuoteBridgeRequest = {
422456
kind: OrderKind.SELL,
423457
sellTokenAddress: '0x123',
@@ -437,5 +471,30 @@ describe('BungeeBridgeProvider', () => {
437471

438472
expect(gasLimit).toEqual(DEFAULT_GAS_COST_FOR_HOOK_ESTIMATION + DEFAULT_EXTRA_GAS_FOR_HOOK_ESTIMATION)
439473
})
474+
475+
it('should return default gas limit estimation for Mainnet to Gnosis and deploy proxy account', async () => {
476+
mockGetCode.mockResolvedValue('0x')
477+
478+
const request: QuoteBridgeRequest = {
479+
kind: OrderKind.SELL,
480+
sellTokenAddress: '0x123',
481+
sellTokenChainId: SupportedChainId.MAINNET,
482+
buyTokenChainId: SupportedChainId.GNOSIS_CHAIN,
483+
amount: 1000000000000000000n,
484+
receiver: '0x789',
485+
account: '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef', // need to find cowshed account address
486+
sellTokenDecimals: 18,
487+
buyTokenAddress: '0x456',
488+
buyTokenDecimals: 6,
489+
appCode: '0x123',
490+
signer: '0xa43ccc40ff785560dab6cb0f13b399d050073e8a54114621362f69444e1421ca',
491+
}
492+
493+
const gasLimit = await provider.getGasLimitEstimationForHook(request)
494+
495+
expect(gasLimit).toEqual(
496+
DEFAULT_GAS_COST_FOR_HOOK_ESTIMATION + COW_SHED_PROXY_CREATION_GAS + DEFAULT_EXTRA_GAS_PROXY_CREATION,
497+
)
498+
})
440499
})
441500
})

src/bridging/providers/bungee/BungeeBridgeProvider.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ import {
1313
GetProviderBuyTokens,
1414
QuoteBridgeRequest,
1515
} from '../../types'
16-
import { DEFAULT_EXTRA_GAS_FOR_HOOK_ESTIMATION, RAW_PROVIDERS_FILES_PATH } from '../../const'
16+
import {
17+
DEFAULT_EXTRA_GAS_FOR_HOOK_ESTIMATION,
18+
DEFAULT_EXTRA_GAS_PROXY_CREATION,
19+
RAW_PROVIDERS_FILES_PATH,
20+
} from '../../const'
1721
import { ChainId, ChainInfo, SupportedChainId } from '../../../chains'
1822
import { EvmCall, TokenInfo } from '../../../common'
1923
import { mainnet } from '../../../chains/details/mainnet'
@@ -150,14 +154,17 @@ export class BungeeBridgeProvider implements BridgeProvider<BungeeQuoteResult> {
150154
}
151155

152156
async getGasLimitEstimationForHook(request: QuoteBridgeRequest): Promise<number> {
153-
const extraGas = this.isExtraGasRequired(request) ? DEFAULT_EXTRA_GAS_FOR_HOOK_ESTIMATION : undefined
157+
const isExtraGasRequired = this.isExtraGasRequired(request)
158+
const extraGas = isExtraGasRequired ? DEFAULT_EXTRA_GAS_FOR_HOOK_ESTIMATION : undefined
159+
const extraGasProxyCreation = isExtraGasRequired ? DEFAULT_EXTRA_GAS_PROXY_CREATION : undefined
154160

155-
return getGasLimitEstimationForHook(
156-
this.cowShedSdk,
161+
return getGasLimitEstimationForHook({
162+
cowShedSdk: this.cowShedSdk,
157163
request,
158-
this.getRpcProvider(request.sellTokenChainId),
164+
provider: this.getRpcProvider(request.sellTokenChainId),
159165
extraGas,
160-
)
166+
extraGasProxyCreation,
167+
})
161168
}
162169

163170
async getSignedHook(
@@ -204,7 +211,7 @@ export class BungeeBridgeProvider implements BridgeProvider<BungeeQuoteResult> {
204211
_txHash: string,
205212
): Promise<{ params: BridgingDepositParams; status: BridgeStatusResult } | null> {
206213
const events = await this.api.getEvents({ orderId })
207-
const event = events[0]
214+
const event = events?.[0]
208215

209216
if (!event) return null
210217

src/bridging/providers/bungee/getBridgingStatusFromEvents.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export async function getBridgingStatusFromEvents(
3737
console.error('BungeeBridgeProvider get across status error', e)
3838
}
3939
}
40+
4041
// if not across or across API fails, waiting for dest tx, return in_progress
4142
return { status: BridgeStatus.IN_PROGRESS, depositTxHash: event.srcTransactionHash }
4243
}

src/bridging/providers/utils/getGasLimitEstimationForHook.ts

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,27 @@ import type { JsonRpcProvider } from '@ethersproject/providers'
33
import { COW_SHED_PROXY_CREATION_GAS, DEFAULT_GAS_COST_FOR_HOOK_ESTIMATION } from '../../const'
44
import { CowShedSdk } from '../../../cow-shed'
55

6-
export async function getGasLimitEstimationForHook(
7-
cowShedSdk: CowShedSdk,
8-
request: QuoteBridgeRequest,
9-
provider: JsonRpcProvider,
10-
extraGas?: number,
11-
): Promise<number> {
6+
export async function getGasLimitEstimationForHook({
7+
cowShedSdk,
8+
request,
9+
provider,
10+
extraGas,
11+
extraGasProxyCreation,
12+
}: {
13+
cowShedSdk: CowShedSdk
14+
request: QuoteBridgeRequest
15+
provider: JsonRpcProvider
16+
extraGas?: number
17+
extraGasProxyCreation?: number
18+
}): Promise<number> {
1219
const proxyAddress = cowShedSdk.getCowShedAccount(request.sellTokenChainId, request.owner || request.account)
1320
const proxyCode = await provider.getCode(proxyAddress)
1421

1522
// Proxy is not deployed
1623
if (!proxyCode || proxyCode === '0x') {
17-
return DEFAULT_GAS_COST_FOR_HOOK_ESTIMATION + COW_SHED_PROXY_CREATION_GAS
24+
const baseGas = DEFAULT_GAS_COST_FOR_HOOK_ESTIMATION + COW_SHED_PROXY_CREATION_GAS
25+
return baseGas + (extraGasProxyCreation && extraGasProxyCreation > 0 ? extraGasProxyCreation : 0)
1826
}
1927

20-
// Some bridges require extra gas to be added to the hook.
21-
if (extraGas && extraGas > 0) {
22-
return DEFAULT_GAS_COST_FOR_HOOK_ESTIMATION + extraGas
23-
}
24-
25-
return DEFAULT_GAS_COST_FOR_HOOK_ESTIMATION
28+
return DEFAULT_GAS_COST_FOR_HOOK_ESTIMATION + (extraGas && extraGas > 0 ? extraGas : 0)
2629
}

src/bridging/types.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,10 +209,13 @@ export interface BridgeProvider<Q extends BridgeQuoteResult> {
209209
* 2. The final amount could affect hook gas costs
210210
*
211211
* By estimating gas costs independently, we can resolve this dependency cycle.
212-
* For some providers, the `extraGas` flag adds a 100,000 gas‐unit buffer to the hook
213-
* (see DEFAULT_EXTRA_GAS_FOR_HOOK_ESTIMATION).
212+
* For some providers, the `extraGas` parameter adds additional gas‐unit buffer to the hook
213+
* and `extraGasProxyCreation` parameter adds additional gas‐unit buffer for the proxy creation
214+
* (see DEFAULT_EXTRA_GAS_FOR_HOOK_ESTIMATION and DEFAULT_EXTRA_GAS_PROXY_CREATION).
214215
*/
215-
getGasLimitEstimationForHook(request: Omit<QuoteBridgeRequest, 'amount'> & { extraGas?: number }): Promise<number>
216+
getGasLimitEstimationForHook(
217+
request: Omit<QuoteBridgeRequest, 'amount'> & { extraGas?: number; extraGasProxyCreation?: number },
218+
): Promise<number>
216219

217220
/**
218221
* Get a pre-authorized hook for initiating a bridge.

0 commit comments

Comments
 (0)