Skip to content

Commit

Permalink
fix: make lifi network fees accurates (#8313)
Browse files Browse the repository at this point in the history
  • Loading branch information
gomesalexandre authored Dec 9, 2024
1 parent c6a71ea commit e387e89
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 52 deletions.
3 changes: 1 addition & 2 deletions packages/swapper/src/swappers/LifiSwapper/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import type { ChainId } from '@shapeshiftoss/caip'
import { fromChainId } from '@shapeshiftoss/caip'
import { evm } from '@shapeshiftoss/chain-adapters'
import { TxStatus } from '@shapeshiftoss/unchained-client'
import { bn } from '@shapeshiftoss/utils'
import type { Result } from '@sniptt/monads/build'
import { Err } from '@sniptt/monads/build'
import type { InterpolationOptions } from 'node-polyglot'
Expand Down Expand Up @@ -154,7 +153,7 @@ export const lifiApi: SwapperApi = {
adapter: assertGetEvmChainAdapter(chainId),
data: data.toString(),
to,
value: bn(value.toString()).toString(),
value,
from,
supportsEIP1559,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ export async function getTrade(
lifiStep,
supportsEIP1559: Boolean(supportsEIP1559),
deps,
from: sendAddress,
})

const source: SwapSource = `${SwapperName.LIFI}${lifiStep.toolDetails.name}`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ import { L1_FEE_CHAIN_IDS, L1_GAS_ORACLE_ADDRESS } from '../constants'

type GetNetworkFeeArgs = {
chainId: ChainId
from: string | undefined
lifiStep: LiFiStep
supportsEIP1559: boolean
deps: SwapperDeps
}

export const getNetworkFeeCryptoBaseUnit = async ({
chainId,
from,
lifiStep,
supportsEIP1559,
deps,
Expand All @@ -28,59 +30,84 @@ export const getNetworkFeeCryptoBaseUnit = async ({

const { average } = await adapter.getGasFeeData()

const l1GasLimit = await (async () => {
if (!L1_FEE_CHAIN_IDS.includes(chainId as KnownChainIds)) return

try {
if (!from) throw new Error('Cannot estimate fees without from')
const { transactionRequest } = await getStepTransaction(lifiStep)
const { data, gasLimit } = transactionRequest ?? {}

if (!data || !gasLimit) {
throw new Error('getStepTransaction failed')
}

const publicClient = viemClientByChainId[chainId as EvmChainId]

const abi = [
{
inputs: [{ internalType: 'bytes', name: '_data', type: 'bytes' }],
name: 'getL1GasUsed',
outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
stateMutability: 'view',
type: 'function',
},
]

const contract = getContract({
address: L1_GAS_ORACLE_ADDRESS,
abi,
client: {
public: publicClient,
},
if (!transactionRequest) throw new Error('transactionRequest is undefined')

const { data, to, value } = transactionRequest

if (data === undefined) throw new Error('transactionRequest: data is required')
if (to === undefined) throw new Error('transactionRequest: to is required')
if (value === undefined) throw new Error('transactionRequest: value is required')

// Attempt own fees estimation if possible (approval granted, wallet connected with from addy to use for simulation)
const feeData = await evm.getFees({
adapter,
data,
to,
value,
from,
supportsEIP1559,
})
return feeData.networkFeeCryptoBaseUnit
} catch (err) {
// Leverage Li.Fi (wrong) estimations if unable to roll our own
const l1GasLimit = await (async () => {
if (!L1_FEE_CHAIN_IDS.includes(chainId as KnownChainIds)) return

const { transactionRequest } = await getStepTransaction(lifiStep)

const { data, gasLimit } = transactionRequest ?? {}

if (!data || !gasLimit) {
throw new Error('getStepTransaction failed')
}

const publicClient = viemClientByChainId[chainId as EvmChainId]

const abi = [
{
inputs: [{ internalType: 'bytes', name: '_data', type: 'bytes' }],
name: 'getL1GasUsed',
outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
stateMutability: 'view',
type: 'function',
},
]

const contract = getContract({
address: L1_GAS_ORACLE_ADDRESS,
abi,
client: {
public: publicClient,
},
})

const l1GasUsed = (await contract.read.getL1GasUsed([data])) as BigInt

return l1GasUsed.toString()
})()

// aggregate all send gas estimations if available
const estimatedGasLimit = lifiStep.estimate.gasCosts?.reduce<bigint | undefined>(
(prev, gasCost) => {
if (gasCost.type !== 'SEND') return prev
if (prev === undefined) return BigInt(gasCost.estimate)
return prev + BigInt(gasCost.estimate)
},
undefined,
)

const l1GasUsed = (await contract.read.getL1GasUsed([data])) as BigInt

return l1GasUsed.toString()
})()

// aggregate all send gas estimations if available
const estimatedGasLimit = lifiStep.estimate.gasCosts?.reduce<bigint | undefined>(
(prev, gasCost) => {
if (gasCost.type !== 'SEND') return prev
if (prev === undefined) return BigInt(gasCost.estimate)
return prev + BigInt(gasCost.estimate)
},
undefined,
)

if (!estimatedGasLimit) throw new Error('failed to get estimated gas limit')
if (!estimatedGasLimit) throw new Error('failed to get estimated gas limit')

const networkFeeCryptoBaseUnit = evm.calcNetworkFeeCryptoBaseUnit({
...average,
supportsEIP1559,
gasLimit: estimatedGasLimit.toString(),
l1GasLimit,
})
const networkFeeCryptoBaseUnit = evm.calcNetworkFeeCryptoBaseUnit({
...average,
supportsEIP1559,
gasLimit: estimatedGasLimit.toString(),
l1GasLimit,
})

return networkFeeCryptoBaseUnit
return networkFeeCryptoBaseUnit
}
}

0 comments on commit e387e89

Please sign in to comment.