diff --git a/packages/bridge-ui/src/components/Dialogs/ClaimDialog/ClaimDialog.svelte b/packages/bridge-ui/src/components/Dialogs/ClaimDialog/ClaimDialog.svelte index 608af1b173..20c6731de6 100644 --- a/packages/bridge-ui/src/components/Dialogs/ClaimDialog/ClaimDialog.svelte +++ b/packages/bridge-ui/src/components/Dialogs/ClaimDialog/ClaimDialog.svelte @@ -29,10 +29,10 @@ import { pendingTransactions } from '$stores/pendingTransactions'; import { ClaimConfirmStep, ReviewStep } from '../Shared'; + import ClaimPreCheck from '../Shared/ClaimPreCheck.svelte'; import { ClaimAction } from '../Shared/types'; import { DialogStep, DialogStepper } from '../Stepper'; import ClaimStepNavigation from './ClaimStepNavigation.svelte'; - import ClaimPreCheck from './ClaimSteps/ClaimPreCheck.svelte'; import { ClaimSteps, INITIAL_STEP } from './types'; const log = getLogger('ClaimDialog'); @@ -171,8 +171,6 @@ claimingDone = false; }; - let checkingPrerequisites: boolean; - let previousStep: ClaimSteps; $: if (activeStep !== previousStep) { previousStep = activeStep; @@ -202,7 +200,7 @@ isActive={activeStep === ClaimSteps.CONFIRM}>{$t('bridge.step.confirm.title')} {#if activeStep === ClaimSteps.CHECK} - + {:else if activeStep === ClaimSteps.REVIEW} {:else if activeStep === ClaimSteps.CONFIRM} diff --git a/packages/bridge-ui/src/components/Dialogs/RetryDialog/RetryDialog.svelte b/packages/bridge-ui/src/components/Dialogs/RetryDialog/RetryDialog.svelte index 664846463b..afe32b1f25 100644 --- a/packages/bridge-ui/src/components/Dialogs/RetryDialog/RetryDialog.svelte +++ b/packages/bridge-ui/src/components/Dialogs/RetryDialog/RetryDialog.svelte @@ -17,6 +17,7 @@ import Claim from '../Claim.svelte'; import { ClaimConfirmStep, ReviewStep } from '../Shared'; + import ClaimPreCheck from '../Shared/ClaimPreCheck.svelte'; import { ClaimAction } from '../Shared/types'; import RetryStepNavigation from './RetryStepNavigation.svelte'; import RetryOptionStep from './RetrySteps/RetryOptionStep.svelte'; @@ -34,7 +35,7 @@ const dialogId = `dialog-${uid()}`; - export let activeStep: RetrySteps = RetrySteps.SELECT; + export let activeStep: RetrySteps = INITIAL_STEP; let canContinue = false; let retrying: boolean; @@ -42,6 +43,8 @@ let ClaimComponent: Claim; let isDesktopOrLarger = false; + let hideContinueButton = false; + let txHash: Hash; const handleRetryError = () => { @@ -116,6 +119,10 @@
+ {$t('transactions.claim.steps.pre_check.title')} {$t('common.confirm')} - {#if activeStep === RetrySteps.SELECT} + {#if activeStep === RetrySteps.CHECK} + + {:else if activeStep === RetrySteps.SELECT} {:else if activeStep === RetrySteps.REVIEW} diff --git a/packages/bridge-ui/src/components/Dialogs/RetryDialog/types.ts b/packages/bridge-ui/src/components/Dialogs/RetryDialog/types.ts index 5d2562bc92..182804cd24 100644 --- a/packages/bridge-ui/src/components/Dialogs/RetryDialog/types.ts +++ b/packages/bridge-ui/src/components/Dialogs/RetryDialog/types.ts @@ -1,10 +1,11 @@ export const enum RetrySteps { + CHECK, SELECT, REVIEW, CONFIRM, } -export const INITIAL_STEP = RetrySteps.SELECT; +export const INITIAL_STEP = RetrySteps.CHECK; export const enum RetryStatus { PENDING, diff --git a/packages/bridge-ui/src/components/Dialogs/ClaimDialog/ClaimSteps/ClaimPreCheck.svelte b/packages/bridge-ui/src/components/Dialogs/Shared/ClaimPreCheck.svelte similarity index 57% rename from packages/bridge-ui/src/components/Dialogs/ClaimDialog/ClaimSteps/ClaimPreCheck.svelte rename to packages/bridge-ui/src/components/Dialogs/Shared/ClaimPreCheck.svelte index c053ec0aff..94e66690b8 100644 --- a/packages/bridge-ui/src/components/Dialogs/ClaimDialog/ClaimSteps/ClaimPreCheck.svelte +++ b/packages/bridge-ui/src/components/Dialogs/Shared/ClaimPreCheck.svelte @@ -1,16 +1,16 @@
@@ -146,9 +108,9 @@
{$t('transactions.claim.steps.pre_check.chain_check')} -

What is "Connected to the correct chain"?

- Lorem ipsum dolor sit amet consectetur adipisicing elit. Saepe error soluta ut accusantium in doloremque commodi - et earum nisi quisquam quo placeat rerum exercitationem minus optio, voluptate architecto officiis consequatur! +

{$t('transactions.claim.steps.pre_check.tooltip.chain.title')}

+ + {$t('transactions.claim.steps.pre_check.tooltip.chain.description')}
@@ -164,9 +126,8 @@
{$t('transactions.claim.steps.pre_check.funds_check')} -

What is "Sufficient funds"?

- You need to have enough funds on the destination chain to pay for the transaction fees in order to claim. If - you paid the processing fee, wait for the relayer to claim it for you. +

{$t('transactions.claim.steps.pre_check.tooltip.funds.title')}

+ {$t('transactions.claim.steps.pre_check.tooltip.funds.description')}
{#if checkingPrerequisites} @@ -177,17 +138,15 @@ {/if}
- {#if isL2Chain(Number(tx.destChainId))} + {#if isL2Chain(Number(tx.srcChainId))}
{$t('transactions.claim.steps.pre_check.quota_check')} -

What is "Sufficient daily quota"?

- Lorem ipsum dolor sit amet consectetur, adipisicing elit. Explicabo, sint. Quo quidem hic accusantium eaque - esse cupiditate rerum velit pariatur ab eligendi repellat, iusto aliquam id, dolorum animi ducimus earum. +

{$t('transactions.claim.steps.pre_check.tooltip.quota.title')}

+ {$t('transactions.claim.steps.pre_check.tooltip.quota.description')}
- {#if checkingPrerequisites} {:else if hasEnoughQuota} diff --git a/packages/bridge-ui/src/i18n/en.json b/packages/bridge-ui/src/i18n/en.json index 76dfac6f86..8c3d5eb3d5 100644 --- a/packages/bridge-ui/src/i18n/en.json +++ b/packages/bridge-ui/src/i18n/en.json @@ -472,7 +472,21 @@ "ready": "You can continue with the claim process!", "step": "Claim step", "switch_chain": "This transaction is bridging to {chain} You need to be connected to this chain", - "title": "Requirements" + "title": "Requirements", + "tooltip": { + "chain": { + "description": "You need to be connected to the chain you want to bridge your funds to.", + "title": "What is \"Connected to the correct chain\"?" + }, + "funds": { + "description": "In order to claim the transaction yourself, you need enough funds on the destination chain. If you've kept the default processing fee, the relayer will likely claim for you soon.", + "title": "What is \"Sufficient funds to claim\"?" + }, + "quota": { + "description": "Currently there is a daily limit of how much ETH can be bridged to L1. If the quota is reached, please try again the next day.", + "title": "What is \"Sufficient daily quota\"?" + } + } }, "review": { "name": "Review", diff --git a/packages/bridge-ui/src/libs/bridge/ETHBridge.ts b/packages/bridge-ui/src/libs/bridge/ETHBridge.ts index 881b288364..625db1d151 100644 --- a/packages/bridge-ui/src/libs/bridge/ETHBridge.ts +++ b/packages/bridge-ui/src/libs/bridge/ETHBridge.ts @@ -56,11 +56,13 @@ export class ETHBridge extends Bridge { id: BigInt(0), // will be set in contract }; - const minGasLimit = await bridgeContract.read.getMessageMinGasLimit([0n]); - log('Min gas limit for message', minGasLimit); + if (processingFee !== 0n) { + const minGasLimit = await bridgeContract.read.getMessageMinGasLimit([0n]); + log('Min gas limit for message', minGasLimit); - const gasLimit = minGasLimit + 1; - message.gasLimit = gasLimit; + const gasLimit = minGasLimit + 1; + message.gasLimit = gasLimit; + } log('Preparing transaction with message', message); diff --git a/packages/bridge-ui/src/libs/bridge/checkBridgeQuota.ts b/packages/bridge-ui/src/libs/bridge/checkBridgeQuota.ts new file mode 100644 index 0000000000..5224d0957c --- /dev/null +++ b/packages/bridge-ui/src/libs/bridge/checkBridgeQuota.ts @@ -0,0 +1,63 @@ +import { readContract } from '@wagmi/core'; +import { type Address, zeroAddress } from 'viem'; + +import { quotaManagerAbi } from '$abi'; +import { isL2Chain } from '$libs/chain'; +import { getLogger } from '$libs/util/logger'; +import { config } from '$libs/wagmi'; + +import { type BridgeTransaction, ContractType } from '.'; +import { getContractAddressByType } from './getContractAddressByType'; + +const log = getLogger('bridge:checkBridgeQuota'); + +export const checkBridgeQuota = async ({ + transaction, + amount, +}: { + transaction: BridgeTransaction; + tokenAddress?: Address; + amount: bigint; +}) => { + log( + 'Checking bridge quota', + transaction.canonicalTokenAddress, + amount, + isL2Chain(Number(transaction.destChainId)), + transaction.destChainId, + transaction.srcChainId, + ); + + const tokenAddress = + transaction.canonicalTokenAddress && (transaction.canonicalTokenAddress as string) !== '' + ? transaction.canonicalTokenAddress + : zeroAddress; + + if (isL2Chain(Number(transaction.destChainId))) { + // Quota only applies for transactions from L2-L1. + // So if the destination chain is an L2 chain, we can skip this check. + log('Skipping quota check for L2 chain'); + return true; + } + + const quotaManagerAddress = getContractAddressByType({ + srcChainId: Number(transaction.destChainId), + destChainId: Number(transaction.srcChainId), + contractType: ContractType.QUOTAMANAGER, + }); + + const quota = await readContract(config, { + address: quotaManagerAddress, + abi: quotaManagerAbi, + chainId: Number(transaction.destChainId), + functionName: 'availableQuota', + args: [tokenAddress, 0n], + }); + + if (amount > quota) { + log('Not enough quota', quota, amount); + return false; + } + log('Quota:', quota, 'Amount:', amount, 'Has enough quota:', amount <= quota); + return true; +};